Skip to content

Commit 09be065

Browse files
committed
add takeSnapshot
1 parent 9057bc3 commit 09be065

1 file changed

Lines changed: 54 additions & 2 deletions

File tree

src/bindings/playwright-shim.mjs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
* `@chromatic-com/playwright`.
2121
*/
2222

23-
import { test as _test, expect, takeSnapshot } from "@chromatic-com/playwright";
23+
import {
24+
test as _test,
25+
expect,
26+
takeSnapshot as _takeSnapshot,
27+
} from "@chromatic-com/playwright";
2428

2529
/** Wrap a ReScript fixtures-callback so Playwright sees destructuring syntax. */
2630
function wrapFn(fn) {
@@ -57,4 +61,52 @@ test.beforeAll = (fn) => _test.beforeAll(wrapFn(fn));
5761
/** `test.afterAll(fn)` — run once after all tests in the current scope. */
5862
test.afterAll = (fn) => _test.afterAll(wrapFn(fn));
5963

60-
export { expect, takeSnapshot };
64+
/**
65+
* `takeSnapshot(page, name)` — capture a Chromatic visual snapshot.
66+
*
67+
* `@chromatic-com/playwright`'s `takeSnapshot` requires a third `testInfo`
68+
* argument (added in v0.12+). We wrap it here so callers don't need to
69+
* pass it explicitly — `_test.info()` returns the current test's info object
70+
* when called from within a running test.
71+
*
72+
* Chromatic rejects snapshots exceeding 25,000,000 px. Long pages easily
73+
* blow past that limit (e.g. 1424 × 231 821 px). Before snapshotting we
74+
* therefore clip the document to the current viewport height by setting
75+
* `overflow: hidden` and an explicit `height` on both <html> and <body>,
76+
* then restore the original styles afterwards so nothing leaks between tests.
77+
*/
78+
export async function takeSnapshot(page, name) {
79+
// Clip document to viewport so rrweb only serialises what is visible.
80+
const viewportSize = page.viewportSize();
81+
const viewportHeight = viewportSize ? `${viewportSize.height}px` : "100vh";
82+
83+
const originalStyles = await page.evaluate((h) => {
84+
const html = document.documentElement;
85+
const body = document.body;
86+
const prev = {
87+
htmlOverflow: html.style.overflow,
88+
htmlHeight: html.style.height,
89+
bodyOverflow: body.style.overflow,
90+
bodyHeight: body.style.height,
91+
};
92+
html.style.overflow = "hidden";
93+
html.style.height = h;
94+
body.style.overflow = "hidden";
95+
body.style.height = h;
96+
return prev;
97+
}, viewportHeight);
98+
99+
try {
100+
await _takeSnapshot(page, name, _test.info());
101+
} finally {
102+
// Always restore original styles, even if takeSnapshot throws.
103+
await page.evaluate((prev) => {
104+
document.documentElement.style.overflow = prev.htmlOverflow;
105+
document.documentElement.style.height = prev.htmlHeight;
106+
document.body.style.overflow = prev.bodyOverflow;
107+
document.body.style.height = prev.bodyHeight;
108+
}, originalStyles);
109+
}
110+
}
111+
112+
export { expect };

0 commit comments

Comments
 (0)