Skip to content

Commit b3251f2

Browse files
test: add a route to use local video file
1 parent 9f13a3f commit b3251f2

2 files changed

Lines changed: 35 additions & 14 deletions

File tree

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

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from "path";
12
import { test, expect } from "@mendix/run-e2e/fixtures";
23
import { waitForWidget, waitFrames } from "@mendix/run-e2e/mendix-helpers";
34

@@ -111,25 +112,45 @@ test.describe("External video", () => {
111112
});
112113

113114
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.
117+
await page.route("**/*.mp4", route =>
118+
route.fulfill({
119+
status: 200,
120+
contentType: "video/mp4",
121+
path: path.join(import.meta.dirname, "fixtures/stub.mp4")
122+
})
123+
);
124+
// Reload so the intercepted route applies to the video element fetch.
125+
await page.reload();
126+
114127
const widget = page.locator(".widget-video-player");
115128
const videoLocator = page.locator(".widget-video-player video");
116129
await widget.scrollIntoViewIfNeeded();
117130
await expect(widget).toBeVisible();
118131
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()
131-
);
132-
// Wait two animation frames so the browser flushes layout and paints the poster frame.
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 }
150+
);
151+
});
152+
});
153+
// Flush layout and paint after metadata is ready.
133154
await waitFrames(page, 2);
134155
await expect(widget).toHaveScreenshot("videoPlayerExternalPoster.png");
135156
});
489 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)