test: Add regression test for media info stability (#2571)
- Relates to: #2563
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
import { MediaLoadedInfoManager } from '../../src/card-controller/media-info-manager';
|
import { MediaLoadedInfoManager } from '../../src/card-controller/media-info-manager';
|
||||||
|
import { MediaLoadedInfoSourceController } from '../../src/components-lib/media-loaded-info-source-controller';
|
||||||
|
import type { MediaLoadedInfoEventDetail } from '../../src/types';
|
||||||
import {
|
import {
|
||||||
createCardAPI,
|
createCardAPI,
|
||||||
|
createLitElement,
|
||||||
createMediaLoadedInfo,
|
createMediaLoadedInfo,
|
||||||
createMediaLoadedInfoEvent,
|
createMediaLoadedInfoEvent,
|
||||||
} from '../test-utils.js';
|
} from '../test-utils.js';
|
||||||
@@ -340,6 +343,67 @@ describe('MediaLoadedInfoManager', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The play/pause, mute and screenshot menu buttons render only while there is
|
||||||
|
// active info for the selected target. These tests wire the real source
|
||||||
|
// controller to the manager the way the card does and pin the invariants that
|
||||||
|
// keep the buttons stable: a transient host disconnect/reconnect under the
|
||||||
|
// same target restores the info, while a genuine target change drops it.
|
||||||
|
// See: https://github.com/dermotduffy/advanced-camera-card/issues/2563
|
||||||
|
describe('active info stability across host disconnect and reconnect', () => {
|
||||||
|
const wire = (target: { id: string | null }) => {
|
||||||
|
const api = createCardAPI();
|
||||||
|
const manager = new MediaLoadedInfoManager(api);
|
||||||
|
const host = createLitElement();
|
||||||
|
host.addEventListener('advanced-camera-card:media:loaded', (ev) =>
|
||||||
|
manager.handleLoadEvent(ev as CustomEvent<MediaLoadedInfoEventDetail>),
|
||||||
|
);
|
||||||
|
const source = new MediaLoadedInfoSourceController(host, {
|
||||||
|
getTargetID: () => target.id,
|
||||||
|
});
|
||||||
|
return { api, manager, source };
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should restore the active info when the player host transiently disconnects and reconnects', () => {
|
||||||
|
const target = { id: 'media-1' as string | null };
|
||||||
|
const { api, manager, source } = wire(target);
|
||||||
|
|
||||||
|
manager.setSelected('media-1');
|
||||||
|
source.set(createMediaLoadedInfo());
|
||||||
|
expect(manager.has()).toBe(true);
|
||||||
|
|
||||||
|
// The host disconnects and reconnects under the same targetID: the info
|
||||||
|
// is gone for an instant, then replayed on reconnect.
|
||||||
|
source.hostDisconnected();
|
||||||
|
expect(manager.has()).toBe(false);
|
||||||
|
|
||||||
|
source.hostConnected();
|
||||||
|
|
||||||
|
expect(manager.has()).toBe(true);
|
||||||
|
expect(api.getConditionStateManager().setState).toHaveBeenLastCalledWith({
|
||||||
|
mediaLoadedInfo: expect.objectContaining({ targetID: 'media-1' }),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not restore the active info when the target genuinely changes', () => {
|
||||||
|
const target = { id: 'media-1' as string | null };
|
||||||
|
const { manager, source } = wire(target);
|
||||||
|
|
||||||
|
manager.setSelected('media-1');
|
||||||
|
source.set(createMediaLoadedInfo());
|
||||||
|
expect(manager.has()).toBe(true);
|
||||||
|
|
||||||
|
// The target actually changes across the disconnect/reconnect, so the
|
||||||
|
// reconnect discards the stale cache instead of replaying it -- the
|
||||||
|
// restore must not keep info alive when media really unloads.
|
||||||
|
target.id = 'media-2';
|
||||||
|
source.hostDisconnected();
|
||||||
|
source.hostConnected();
|
||||||
|
|
||||||
|
manager.setSelected('media-2');
|
||||||
|
expect(manager.has()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('initialize', () => {
|
describe('initialize', () => {
|
||||||
it('should clear active state, last-known and selected', () => {
|
it('should clear active state, last-known and selected', () => {
|
||||||
const api = createCardAPI();
|
const api = createCardAPI();
|
||||||
|
|||||||
Reference in New Issue
Block a user