AirShelf/core/qa/visual-parity/compare-all.mjs

85 lines
2.7 KiB
JavaScript

import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const here = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(here, "../../..");
const designRoot = "file:///Users/maidong/Desktop/zyc/qiyuan_gitea/AirShelf/电商AI平台";
const targetRoot = "http://127.0.0.1:5173/exact";
const manifest = JSON.parse(fs.readFileSync(path.join(here, "pages.json"), "utf8"));
function arg(name, fallback = "") {
const index = process.argv.indexOf(`--${name}`);
return index >= 0 ? process.argv[index + 1] : fallback;
}
function asUrl(root, value) {
if (value.startsWith("http://") || value.startsWith("https://") || value.startsWith("file://")) return value;
return `${root}/${value}`;
}
const viewport = arg("viewport", "1440x900");
const only = arg("only", "");
const pages = only ? manifest.filter((item) => item.name.includes(only)) : manifest;
const results = [];
for (const item of pages) {
const source = asUrl(designRoot, item.source);
const target = item.target || asUrl(targetRoot, item.targetPath || item.source);
const args = [
path.join(here, "compare-page.mjs"),
"--name", item.name,
"--source", source,
"--target", target,
"--viewport", viewport,
"--clear-target-storage"
];
console.log(`\n[visual-parity] ${item.name}`);
const run = spawnSync(process.execPath, args, {
cwd: here,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"]
});
if (run.stdout) process.stdout.write(run.stdout);
if (run.stderr) process.stderr.write(run.stderr);
const reportFile = path.join(repoRoot, "core/qa/visual-parity/output", `${item.name}.report.json`);
let report = null;
if (fs.existsSync(reportFile)) {
report = JSON.parse(fs.readFileSync(reportFile, "utf8"));
}
results.push({
name: item.name,
ok: run.status === 0 && report?.pass === true,
status: run.status,
diffPixels: report?.diffPixels ?? null,
diffRatio: report?.diffRatio ?? null,
note: item.note || ""
});
}
const failed = results.filter((item) => !item.ok);
const summary = {
viewport,
total: results.length,
passed: results.length - failed.length,
failed: failed.length,
results
};
const summaryPath = path.join(repoRoot, "core/qa/visual-parity/output/all.report.json");
fs.mkdirSync(path.dirname(summaryPath), { recursive: true });
fs.writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`);
console.log("\n[visual-parity] summary");
console.table(results.map((item) => ({
page: item.name,
ok: item.ok,
diffPixels: item.diffPixels,
diffRatio: item.diffRatio
})));
if (failed.length) {
process.exitCode = 1;
}