Skip to content

Commit 4c94b6f

Browse files
matthewlipskinperez0111
authored andcommitted
Fixed static rendering screenshots
1 parent a129537 commit 4c94b6f

5 files changed

Lines changed: 41 additions & 19 deletions

File tree

-28.6 KB
Loading
-28.2 KB
Loading
-27.8 KB
Loading

tests/src/end-to-end/static/static.test.tsx

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import BasicBlocksStaticApp from "@examples/05-interoperability/10-static-html-r
33
import StaticApp from "@examples/02-backend/04-rendering-static-documents/src/App";
44
import { describe, test } from "vite-plus/test";
55
import { render } from "vitest-browser-react";
6+
import { page } from "../../utils/context.js";
67
import { EDITOR_SELECTOR } from "../../utils/const.js";
78
import { expectElement, sleep, waitForSelector } from "../../utils/editor.js";
89

@@ -16,39 +17,37 @@ describe("Check static rendering", () => {
1617

1718
// Renders two editors back-to-back and screenshots each against the same
1819
// baseline, asserting the static HTML export looks like the live editor.
19-
// Heavy enough that even the suite-wide 30s testTimeout is tight when 3
20-
// browsers contend in one Docker container — bump to 60s to absorb that.
20+
// Heavy (two full editors + two full-page screenshots), and Firefox is slow,
21+
// so under 3-browser-in-one-container contention even 60s is tight — 90s.
2122
test(
2223
"Check static rendering visually matches live editor",
23-
{ timeout: 60000 },
24+
{ timeout: 90000 },
2425
async () => {
25-
// Screenshots the page body against the shared baseline. Mirrors the
26+
// Screenshots the whole page against the shared baseline. Mirrors the
2627
// options the original Playwright test used:
2728
// - Mask the regions that legitimately differ between the live editor and
2829
// the static export, or that aren't deterministic across runs. <video>/
2930
// <audio> render differently as they load (and the amount loaded varies
30-
// per run) — unmasked, their per-frame changes also keep the page from
31-
// ever stabilising, which hangs the screenshot matcher. Checkboxes and
32-
// toggle buttons are interactive widgets in the live editor but plain
33-
// markup in the export. Masks are resolved at call time so they pick up
34-
// whichever of these elements the current render produced.
31+
// per run); checkboxes and toggle buttons are interactive widgets in the
32+
// live editor but plain markup in the export. The `mask` option only
33+
// accepts vitest Locators (NOT raw DOM elements — passing elements
34+
// silently masks nothing), so each matched element is wrapped with
35+
// `page.elementLocator`. Resolved at call time to pick up whichever of
36+
// these elements the current render produced.
37+
// https://vitest.dev/guide/browser/visual-regression-testing.html#handle-dynamic-content
3538
// - `allowedMismatchedPixels` is vite-plus's pixelmatch equivalent of
3639
// Playwright's `maxDiffPixels`: a small allowance for the image caption
3740
// text, which renders slightly differently (e.g. '×' vs 'x').
41+
const masks = () =>
42+
["video", "audio", 'input[type="checkbox"]', ".bn-toggle-button"]
43+
.flatMap((sel) => [...document.querySelectorAll(sel)])
44+
.map((el) => page.elementLocator(el));
3845
const matchEquality = () =>
3946
expectElement(document.body).toMatchScreenshot(
4047
"static-rendering-equality",
4148
{
4249
comparatorOptions: { allowedMismatchedPixels: 200 },
43-
screenshotOptions: {
44-
scale: "css",
45-
mask: [
46-
...document.querySelectorAll("video"),
47-
...document.querySelectorAll("audio"),
48-
...document.querySelectorAll('input[type="checkbox"]'),
49-
...document.querySelectorAll(".bn-toggle-button"),
50-
],
51-
},
50+
screenshotOptions: { scale: "css", mask: masks() },
5251
},
5352
);
5453

@@ -61,6 +60,27 @@ describe("Check static rendering", () => {
6160
document.head.appendChild(style);
6261
await sleep(500);
6362

63+
// This document is taller than the suite-wide 1280x720 iframe. The matcher
64+
// captures the `document.body` element box (it can't `fullPage`
65+
// scroll-and-stitch), and a fixed-height iframe never paints what's below
66+
// its fold — so grow the iframe past the whole document first. No restore
67+
// is needed: every test file's `beforeAll` resets the iframe to 1280x720.
68+
//
69+
// The height is a FIXED constant (comfortably taller than the document),
70+
// NOT the measured `scrollHeight`: the latter drifts a few px between
71+
// runs/renders on Firefox, and since the capture is downscaled (below)
72+
// that drift changes the output dimensions and fails the dimension check.
73+
//
74+
// NB: the browser *window* stays 1280x720 (a taller window breaks
75+
// Firefox's native `<select>` handling — see customblocks), so the capture
76+
// of the now-taller iframe is downscaled to fit the window. The whole page
77+
// is captured, but the baseline is smaller than 1280xH (not 1:1).
78+
// Full-resolution would require running these tests in a separate
79+
// tall-window browser project.
80+
const PAGE_HEIGHT = 1800;
81+
await page.viewport(1280, PAGE_HEIGHT);
82+
await sleep(200);
83+
6484
await matchEquality();
6585

6686
// Await the unmount: `render`/`unmount` run inside `act()`, and starting
@@ -72,6 +92,7 @@ describe("Check static rendering", () => {
7292

7393
await render(<BasicBlocksStaticApp />);
7494
await waitForSelector(EDITOR_SELECTOR);
95+
await page.viewport(1280, PAGE_HEIGHT);
7596
await sleep(500);
7697
await matchEquality();
7798
},

tests/src/utils/editor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { expect, vi } from "vite-plus/test";
2+
import type { Locator } from "vite-plus/test/browser/context";
23
import { userEvent } from "./context.js";
34
import { EDITOR_SELECTOR } from "./const.js";
45

@@ -100,7 +101,7 @@ type ElementMatchers = {
100101
options?: {
101102
timeout?: number;
102103
screenshotOptions?: {
103-
mask?: ReadonlyArray<Element>;
104+
mask?: ReadonlyArray<Element | Locator>;
104105
maskColor?: string;
105106
scale?: "css" | "device";
106107
};

0 commit comments

Comments
 (0)