Skip to content

Commit deca2e2

Browse files
Make the video player poster screenshot test resilient to external video URL failures (#2244)
2 parents 0beb076 + 682f975 commit deca2e2

4 files changed

Lines changed: 25 additions & 16 deletions

File tree

packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,30 +106,39 @@ test.describe("Error page", () => {
106106
});
107107

108108
test.describe("External video", () => {
109-
test.beforeEach(async ({ page }) => {
109+
test("renders a poster", async ({ page }, testInfo) => {
110+
// Register the route before navigation so the mp4 fetch is intercepted
111+
// from the start. The beforeEach can't be used here because it runs
112+
// before the test body, after which it's too late to register the route.
113+
const stubPath = testInfo.file.replace("VideoPlayer.spec.js", "fixtures/stub.mp4");
114+
await page.route("**/*.mp4", route =>
115+
route.fulfill({
116+
status: 200,
117+
contentType: "video/mp4",
118+
path: stubPath
119+
})
120+
);
110121
await page.goto("/p/external");
111-
});
112122

113-
test("renders a poster", async ({ page }) => {
114123
const widget = page.locator(".widget-video-player");
115124
const videoLocator = page.locator(".widget-video-player video");
116125
await widget.scrollIntoViewIfNeeded();
117126
await expect(widget).toBeVisible();
118127
await expect(videoLocator).toHaveAttribute("poster", /.+/);
119-
// Wait for poster image to decode in-page before screenshotting.
120-
// page.evaluate with a separate Image() is unreliable — the promise can
121-
// resolve before the <video> element itself has rendered the poster frame.
122-
await videoLocator.evaluate(el =>
123-
el.poster
124-
? new Promise(r => {
125-
const i = new Image();
126-
i.onload = i.onerror = r;
127-
i.src = el.poster;
128-
if (i.complete) r();
129-
})
130-
: Promise.resolve()
128+
// Poll for a terminal state: metadata loaded OR all sources failed (networkState 3).
129+
// Polling avoids the race where loadedmetadata/error events fire on <source> before
130+
// we can attach listeners on the <video> element inside evaluate().
131+
await page.waitForFunction(
132+
() => {
133+
const el = document.querySelector(".widget-video-player video");
134+
return (
135+
el !== null &&
136+
(el.readyState >= 1 || el.networkState === HTMLMediaElement.NETWORK_NO_SOURCE || el.error !== null)
137+
);
138+
},
139+
{ timeout: 8000 }
131140
);
132-
// Wait two animation frames so the browser flushes layout and paints the poster frame.
141+
// Flush layout and paint after metadata is ready.
133142
await waitFrames(page, 2);
134143
await expect(widget).toHaveScreenshot("videoPlayerExternalPoster.png");
135144
});
180 KB
Loading
665 Bytes
Loading
669 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)