fix: Report media failures once per failure (#2666)
This commit is contained in:
1 parent
8d8d486afa
commit
5e199b5612
22 files changed
+484
-123
No files matched your search
@@ -11,6 +11,8 @@ import {
|
||||
|
||||
const UNRELATED_ENTITY = 'input_boolean.unrelated';
|
||||
|
||||
const IMAGE_ERROR_EVENT = 'advanced-camera-card:image-updating-player:error';
|
||||
|
||||
// The size of the static image fixture the player loads. Everything downstream
|
||||
// sizes the card from what the player measured, so these are read from the
|
||||
// media rather than declared anywhere in the configuration.
|
||||
@@ -57,6 +59,28 @@ describe('AdvancedCameraCardImageUpdatingPlayer', () => {
|
||||
expect(loads[0].info.targetID).toBe(CAMERA_ENTITY);
|
||||
});
|
||||
|
||||
it('should ignore an image failure that arrives after the card leaves the page', async () => {
|
||||
const card = await mount();
|
||||
const player = await card.waitForSelector(
|
||||
'advanced-camera-card-image-updating-player',
|
||||
);
|
||||
const image = await card.waitForSelector('img');
|
||||
|
||||
const failures: Event[] = [];
|
||||
player.addEventListener(IMAGE_ERROR_EVENT, (ev) => failures.push(ev));
|
||||
|
||||
image.dispatchEvent(new Event('error'));
|
||||
expect(failures).toHaveLength(1);
|
||||
|
||||
// The browser answers a request the player made before the card came off
|
||||
// the page. Nobody is looking at the media it was for, so the player must
|
||||
// say nothing about it.
|
||||
card.detach();
|
||||
image.dispatchEvent(new Event('error'));
|
||||
|
||||
expect(failures).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should announce the size of the media itself', async () => {
|
||||
const card = await mount();
|
||||
|
||||
|
||||
@@ -179,6 +179,40 @@ describe('AdvancedCameraCardViewerCarousel', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should build a new player for a failed clip when the retry control is used', async () => {
|
||||
vi.useFakeTimers();
|
||||
onTestFinished(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
const { card, frigate } = await mountCardWithFrigate(EVENTS, {
|
||||
// Automatic retries switched off, so the control below is the only one.
|
||||
view: { default: 'clips', issues: { retry_seconds: 0 } },
|
||||
status_bar: { style: 'outside' },
|
||||
});
|
||||
frigate.setMediaURL('newer', 'clips', createFailingMediaURL());
|
||||
|
||||
await waitForThumbnails(card, EVENTS.length);
|
||||
await clickThumbnail(card.card, 0);
|
||||
const failedPlayer = await card.waitForSelector('video');
|
||||
await card.advanceSeconds(MEDIA_LOADING_TIMEOUT_SECONDS);
|
||||
await card.waitForRender(
|
||||
() => getStatusBarItem(card.card, MEDIA_ISSUE_TITLE),
|
||||
`the ${MEDIA_ISSUE_TITLE} issue being reported`,
|
||||
);
|
||||
|
||||
await card.clickControl(MEDIA_ISSUE_TITLE);
|
||||
await card.clickControl('Retry');
|
||||
|
||||
// A second player, not the one that failed: the retry throws the old one
|
||||
// away, and the replacement has to render and ask for the clip again rather
|
||||
// than sit there empty.
|
||||
await card.waitForRender(() => {
|
||||
const player = deepQuery(card.card, 'video');
|
||||
return player && player !== failedPlayer ? player : null;
|
||||
}, 'the clip player being rebuilt');
|
||||
});
|
||||
|
||||
it('should return to the gallery from the viewer', async () => {
|
||||
const card = await mountViewer(EVENTS, {
|
||||
config: {
|
||||
|
||||
Reference in new issue
Block a user