Skip to content

Commit

Permalink
use pixelteer for snapshot testing
Browse files Browse the repository at this point in the history
  • Loading branch information
narthur committed Jul 16, 2024
1 parent 39920ab commit 76f6be0
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 473 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@
"diffable-html": "^5.0.0",
"eslint": "^8.49.0",
"pixelmatch": "^5.3.0",
"pixelteer": "github:narthur/pixelteer",
"pngjs": "^7.0.0",
"prettier": "3.0.3",
"puppeteer": "^21.3.8",
"puppeteer": "22.6.5",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vitest": "^2.0.3"
Expand Down
327 changes: 187 additions & 140 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

73 changes: 0 additions & 73 deletions scripts/puppeteer.spec.ts

This file was deleted.

152 changes: 35 additions & 117 deletions scripts/puppeteer.ts
Original file line number Diff line number Diff line change
@@ -1,125 +1,43 @@
// usage:
// pnpm tsx ./scripts/puppeteer.ts
// pnpm puppeteer

import fs from "fs";
import { preview } from "astro";
import pixelmatch from "pixelmatch";
import { PNG } from "pngjs";
import takeScreenshot from "../src/lib/test/saveScreenshot";
import getSitemap from "../src/lib/test/getSitemap";
import readScreenshot from "../src/lib/test/readScreenshot";
import resizeImage from "../src/lib/test/resizeImage";
import puppeteer, { Browser } from "puppeteer";
import createReport from "../src/lib/test/createReport";
import url from "url";
import { compareUrls, createReport } from "pixelteer";

const port = 4321;
const base = `https://blog.beeminder.com`;
const compare = `http://localhost:${port}`;
const outPath = new URL("../shots/", import.meta.url);

function makeOutPath(url: string, suffix: string): URL {
const p = new URL(url).pathname.replaceAll("/", "_");
return new URL(`./${p}.${suffix}.png`, outPath);
}

async function snap(
browser: Browser,
url: string,
suffix: string,
): Promise<URL> {
const p = makeOutPath(url, suffix);

await takeScreenshot({
browser,
url,
path: p,
});

return p;
}

async function handleUrl(browser: Browser, url: string) {
const pathname = new URL(url).pathname;
console.time(pathname);

const path1 = await snap(browser, `${url}?snap`, "base");
const path2 = await snap(
browser,
`${url.replace(base, compare)}?snap`,
"compare",
);
const img1 = readScreenshot(path1);
const img2 = readScreenshot(path2);
const meta1 = await img1.metadata();
const meta2 = await img2.metadata();

if (!meta1.width || !meta1.height || !meta2.width || !meta2.height) {
throw new Error("Missing image size data");
}

const width = Math.max(meta1.width, meta2.width);
const height = Math.max(meta1.height, meta2.height);
const resized1 = await resizeImage({ image: img1, width, height });
const resized2 = await resizeImage({ image: img2, width, height });
const diff = new PNG({ width, height });

const c = pixelmatch(resized1, resized2, diff.data, width, height, {
threshold: 0.1,
});

fs.writeFileSync(makeOutPath(url, "diff"), PNG.sync.write(diff));

console.timeEnd(pathname);
console.log(c);
}

async function takeScreenshots() {
const root = new URL("..", import.meta.url);
const server = await preview({
root: url.fileURLToPath(root),
server: {
port,
},
});
const browser = await puppeteer.launch({
headless: "new",
});
const urls = await getSitemap();
console.log(urls);

console.time("Capturing screenshots");
for (const url of urls) {
await handleUrl(browser, url);
}
console.timeEnd("Capturing screenshots");

await browser.close();
await server.stop();
}

export async function run(argv: string[] = []) {
if (!fs.existsSync(outPath)) {
fs.mkdirSync(outPath);
}

const isEmpty = fs.readdirSync(outPath).length === 0;
const isForced = argv.includes("--force");

if (isEmpty || isForced) {
await takeScreenshots();
} else {
console.log(
"Skipping screenshots because shots is not empty. Use --force to override.",
);
}

createReport();
}
const a = new URL(import.meta.url).pathname;
const b = new URL(`file://${process.argv[1]}`).pathname;
if (a === b) {
console.log("Running puppeteer script");
await run(process.argv);
}
const root = new URL("..", import.meta.url);

const server = await preview({
root: url.fileURLToPath(root),
server: {
port,
},
});

const urls = await getSitemap();
const paths = urls.map((url) => new URL(url).pathname);

await compareUrls({
baseUrl1: base,
baseUrl2: compare,
paths,
outDir: url.fileURLToPath(outPath),
force: process.argv.includes("--force"),
onSuccess: (data) => {
console.log(data);
},
onError: (error) => {
console.error(error);
},
});

createReport({
baseUrl1: base,
baseUrl2: compare,
shotsDir: url.fileURLToPath(outPath),
outDir: url.fileURLToPath(root),
});

await server.stop();
79 changes: 0 additions & 79 deletions src/lib/test/createReport.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/lib/test/readScreenshot.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/lib/test/resizeImage.ts

This file was deleted.

26 changes: 0 additions & 26 deletions src/lib/test/saveScreenshot.ts

This file was deleted.

Loading

0 comments on commit 76f6be0

Please sign in to comment.