Skip to content

Commit c7e60b7

Browse files
test: fix stub and fixture path
1 parent b3251f2 commit c7e60b7

3 files changed

Lines changed: 19 additions & 31 deletions

File tree

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

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import path from "path";
21
import { test, expect } from "@mendix/run-e2e/fixtures";
32
import { waitForWidget, waitFrames } from "@mendix/run-e2e/mendix-helpers";
43

@@ -107,49 +106,38 @@ test.describe("Error page", () => {
107106
});
108107

109108
test.describe("External video", () => {
110-
test.beforeEach(async ({ page }) => {
111-
await page.goto("/p/external");
112-
});
113-
114-
test("renders a poster", async ({ page }) => {
115-
// Intercept the external video URL and serve a local stub so the test
116-
// doesn't depend on third-party CDN availability in CI.
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");
117114
await page.route("**/*.mp4", route =>
118115
route.fulfill({
119116
status: 200,
120117
contentType: "video/mp4",
121-
path: path.join(import.meta.dirname, "fixtures/stub.mp4")
118+
path: stubPath
122119
})
123120
);
124-
// Reload so the intercepted route applies to the video element fetch.
125-
await page.reload();
121+
await page.goto("/p/external");
126122

127123
const widget = page.locator(".widget-video-player");
128124
const videoLocator = page.locator(".widget-video-player video");
129125
await widget.scrollIntoViewIfNeeded();
130126
await expect(widget).toBeVisible();
131127
await expect(videoLocator).toHaveAttribute("poster", /.+/);
132-
// Wait for the video element to reach HAVE_METADATA (readyState >= 1).
133-
// Until metadata loads, Chrome renders the <video> without its native chrome
134-
// (controls bar, dark background) — producing a screenshot that doesn't match
135-
// the baseline. Guard against a pre-existing error to avoid waiting forever
136-
// when onerror already fired before we attach the listener.
137-
await videoLocator.evaluate(el => {
138-
if (el.readyState >= 1) {
139-
return Promise.resolve();
140-
}
141-
if (el.error !== null) {
142-
return Promise.reject(new Error("Video failed to load metadata before screenshot"));
143-
}
144-
return new Promise((resolve, reject) => {
145-
el.addEventListener("loadedmetadata", resolve, { once: true });
146-
el.addEventListener(
147-
"error",
148-
() => reject(new Error("Video failed to load metadata before screenshot")),
149-
{ once: true }
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)
150137
);
151-
});
152-
});
138+
},
139+
{ timeout: 8000 }
140+
);
153141
// Flush layout and paint after metadata is ready.
154142
await waitFrames(page, 2);
155143
await expect(widget).toHaveScreenshot("videoPlayerExternalPoster.png");
180 KB
Loading
180 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)