test(player): lock primary-device audio policy for issue 260
This commit is contained in:
18
docs/ISSUE-260-PHONE-CLIENT-NO-AUDIO-GUARD-ARTIFACT.md
Normal file
18
docs/ISSUE-260-PHONE-CLIENT-NO-AUDIO-GUARD-ARTIFACT.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Issue #260 Artifact — Phone/client no-audio guard (primary-device only playback)
|
||||
|
||||
## Scope
|
||||
Added regression coverage for MVP audio policy to ensure phone/client flows never claim playback ownership, while primary-device playback stays unaffected.
|
||||
|
||||
## Acceptance mapping
|
||||
1. **client/phone triggers no playback**
|
||||
- Existing test coverage retained in `player-shell.component.spec.ts`:
|
||||
- `does not trigger original media play during player-shell init path`
|
||||
- `installs secondary-device audio guard while player shell is mounted`
|
||||
2. **primary device playback unaffected**
|
||||
- New negative test in `player-shell.component.spec.ts`:
|
||||
- `keeps primary-device playback untouched when no-audio capability is disabled`
|
||||
3. **one negative test for phone audio**
|
||||
- Existing negative path preserved:
|
||||
- `does not trigger original media play during player-shell init path`
|
||||
4. **no backend contract changes**
|
||||
- Frontend test/docs-only scope; no backend contract files changed.
|
||||
@@ -468,6 +468,33 @@ describe('PlayerShellComponent gameplay wiring', () => {
|
||||
component.ngOnDestroy();
|
||||
});
|
||||
|
||||
it('keeps primary-device playback untouched when no-audio capability is disabled', async () => {
|
||||
const originalPlay = vi.fn().mockResolvedValue(undefined);
|
||||
const mediaPrototype = { play: originalPlay };
|
||||
|
||||
vi.stubGlobal('window', {
|
||||
location: { hash: '', search: '' },
|
||||
history: { state: null, replaceState: vi.fn() },
|
||||
localStorage: { getItem: vi.fn().mockReturnValue('en'), setItem: vi.fn(), removeItem: vi.fn() },
|
||||
sessionStorage: { getItem: vi.fn().mockReturnValue(null), setItem: vi.fn(), removeItem: vi.fn() },
|
||||
HTMLMediaElement: { prototype: mediaPrototype },
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
});
|
||||
vi.stubGlobal('navigator', { language: 'en-US', onLine: true });
|
||||
|
||||
const component = new PlayerShellComponent();
|
||||
(component as any).clientHasNoAudioOutput = false;
|
||||
|
||||
component.ngOnInit();
|
||||
|
||||
await expect(mediaPrototype.play()).resolves.toBeUndefined();
|
||||
expect(mediaPrototype.play).toBe(originalPlay);
|
||||
expect((mediaPrototype as any).__wppSecondaryDeviceAudioGuard__).toBeUndefined();
|
||||
|
||||
component.ngOnDestroy();
|
||||
});
|
||||
|
||||
it('resolves i18n warning copy from shared catalog without key fallback', () => {
|
||||
const component = new PlayerShellComponent();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user