You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Test related change (New E2E test, test automation, etc.)
Description
The "renders a poster" screenshot test was flaky in CI because it depended on a third-party CDN (file-examples-com.github.io) that is unreachable from the runner. When the video fails to load, the widget shows an error overlay and hides native controls, producing a screenshot that doesn't match the baseline.
Two fixes:
Route interception — page.route("**/*.mp4") intercepts the CDN request before the page reloads and fulfills it with a local 489-byte stub MP4 (e2e/fixtures/stub.mp4). The stub has a valid ftyp+moov structure so Chrome can parse metadata without fetching any actual video data. The widget is still configured with the external URL — only the network call is replaced.
Condition-based wait — replaced the unreliable Image() preload trick with a loadedmetadata event listener on the video element itself. The old approach only waited for the poster image bytes to decode, not for the
New binary: minimal valid MP4 stub served by the route interceptor
Skipped (out of scope): dist/, pnpm-lock.yaml
CI check results could not be retrieved (command required approval). No CHANGELOG entry required — this is a test-only change with no runtime/XML/behavior impact.
Findings
⚠️ Low — afterEach session logout missing from the "External video" describe block
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js lines 109–184 Note: The "External video" describe block (and its nested "Video aspect ratio" block) has no afterEach logout. This pre-exists the PR, but the new "renders a poster" test now calls page.reload() mid-test, which is an additional session action that makes the missing cleanup more noticeable. Under the repo's E2E rules every describe block needs:
Without it, CI can exhaust Mendix's 5-session limit across parallel workers.
⚠️ Low — Route pattern "**/*.mp4" is broader than intended
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js line 117 Note:"**/*.mp4" will intercept every.mp4 request on the page, including any future video sources added to the test app. If another test on the same page loads a different video, it will silently receive the stub. A URL-specific pattern is safer:
awaitpage.route("**/file-examples-com.github.io/**/*.mp4",route=> ...);// or match the exact URL the widget uses:awaitpage.route(/file-examples-com\.github\.io/,route=> ...);
⚠️ Low — page.reload() without waitForLoadState after reload
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js line 125 Note:page.reload() returns once navigation completes but the Mendix runtime may not have re-rendered the widget yet. Per repo E2E guidelines, follow reloads with waitForLoadState("networkidle") to avoid racing the widget initialisation before the locator assertions:
The route-interception approach correctly eliminates the external CDN dependency without changing the widget's configured URL — the test still exercises the real external-URL code path.
The readyState >= 1 check with a pre-existing-error guard is a precise, well-commented wait condition that avoids both a busy-poll and an infinite hang.
Committing a minimal valid MP4 fixture (stub.mp4) rather than a URL or a huge media file is the right call for hermetic E2E tests.
The PR description clearly explains both the root cause (CDN unreachable in CI) and the two-part fix, making it easy to verify intent against the diff.
CI checks: could not be fetched from this environment — manual CI verification recommended.
Findings
⚠️ Low — Missing page.waitForLoadState("networkidle") after page.goto
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js line 121 Note: The page.goto("/p/external") call doesn't wait for networkidle before interacting with the page. Other beforeEach blocks in this same file all use waitForLoadState("networkidle") (implied by the shared test infrastructure). While the waitForFunction polling below effectively guards against a race in this specific test, adding waitForLoadState here aligns the test with the rest of the file's patterns and makes the intent more explicit. Fix:
⚠️ Low — testInfo.file.replace(...) is fragile if the test file is renamed
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js line 113 Note: The path to stub.mp4 is derived by string-replacing the spec filename in testInfo.file. This works today but breaks silently if the spec file is ever renamed or if the test is moved to a different describe/file. Using path.join(path.dirname(testInfo.file), "fixtures", "stub.mp4") is more robust — it doesn't depend on the literal filename. Fix:
⚠️ Low — waitForFunction selector doesn't use .mx-name-* — minor but inconsistent
File:packages/pluggableWidgets/video-player-web/e2e/VideoPlayer.spec.js line 133 Note: The document.querySelector(".widget-video-player video") inside waitForFunction uses a widget CSS class rather than an .mx-name-* locator (the preferred stable selector per E2E guidelines). This is minor since it runs inside a page.evaluate-style context where Playwright locators aren't available, but worth noting if the widget name is accessible. Not a blocker.
Positives
The route interception approach is the correct Playwright pattern for preventing flaky tests caused by unreachable CDN dependencies — the widget still uses the real external URL, only the network call is replaced, which accurately reflects the production configuration.
Replacing the event-listener–based Image() promise with a waitForFunction poll is a meaningful reliability improvement. The old approach had a documented race; polling on readyState/networkState/error is the right model for <video> element state.
Committing both darwin and linux screenshot baselines is correct — toHaveScreenshot requires committed baselines to work in CI.
The el.error !== null fast-fail guard inside waitForFunction means the test will time out quickly with a clear signal rather than hanging for 8 seconds if route interception fails.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull request type
Test related change (New E2E test, test automation, etc.)
Description
The "renders a poster" screenshot test was flaky in CI because it depended on a third-party CDN (file-examples-com.github.io) that is unreachable from the runner. When the video fails to load, the widget shows an error overlay and hides native controls, producing a screenshot that doesn't match the baseline.
Two fixes: