feat: add AirShelf core implementation
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user