Skip to content

Instantly share code, notes, and snippets.

@dohooo
Last active December 29, 2022 04:09
Show Gist options
  • Save dohooo/efa053c6273b2a148c3a5f7319c1a9a5 to your computer and use it in GitHub Desktop.
Save dohooo/efa053c6273b2a148c3a5f7319c1a9a5 to your computer and use it in GitHub Desktop.
Visual testing with vitest
import { join } from "path";
import type { Meta, StoryFn } from "@storybook/react";
import { composeStories } from "@storybook/react";
import { render } from "@testing-library/react";
import glob from "glob";
import { toMatchImageSnapshot } from "jest-image-snapshot";
import { chromium, type Browser, type Page } from "playwright";
import { afterAll, beforeAll, expect, describe, it, vi } from "vitest";
interface StoryFile {
default: Meta
[name: string]: StoryFn | Meta
}
it.skipIf(process.env.IS_CI)("local only test", async () => {
expect.extend({ toMatchImageSnapshot });
const TEST_ID = "VISUAL_TESTING_TEST_ID";
const storyFiles = glob.sync(join(__dirname, "./components/**/*.stories.tsx"));
describe("should", async () => {
let page: Page;
let browser: Browser;
beforeAll(async () => {
browser = await chromium.launch();
page = await browser.newPage();
});
afterAll(async () => {
await browser.close();
});
const stories = (await Promise.all(
storyFiles.map(async (storyPath) => {
return Object.values(composeStories(await vi.importActual(storyPath) as StoryFile));
}),
)).reduce((acc, cur) => [...acc, ...cur], [] as StoryFn[]);
it.each(
stories.map(i => [String(i.parameters?.__id), i]),
)("%s", async (id, Story) => {
const { container } = render(<div id={TEST_ID}><Story /></div>);
expect(container).toMatchSnapshot();
const styles = document.querySelector("style")?.outerHTML || "";
const content = `<div style="display:inline-block;" id="${id}">${container.innerHTML}</div>`;
const html = `${styles}${content}`;
await page.setContent(html);
await page.waitForSelector(`#${id}`, { state: "visible" });
const target = (await page.$$(`#${id}`))[0];
const demission = await target.boundingBox();
const { x, y, width, height } = demission!;
const screenshot = await page.screenshot({ clip: { x, y, width, height } });
expect(screenshot).toMatchImageSnapshot({ customSnapshotIdentifier: id });
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment