92 lines
3.8 KiB
JavaScript
92 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
|
|
function parseArgs(argv) {
|
|
const args = { fixture: '', actual: '', field: '', expectedPath: '', actualPath: '', json: false, markdown: false };
|
|
for (let i = 2; i < argv.length; i++) {
|
|
const a = argv[i];
|
|
if (a === '--fixture') args.fixture = argv[++i] || '';
|
|
else if (a === '--actual') args.actual = argv[++i] || '';
|
|
else if (a === '--field') args.field = argv[++i] || '';
|
|
else if (a === '--expected-path') args.expectedPath = argv[++i] || '';
|
|
else if (a === '--actual-path') args.actualPath = argv[++i] || '';
|
|
else if (a === '--json') args.json = true;
|
|
else if (a === '--markdown') args.markdown = true;
|
|
else if (a === '--help' || a === '-h') args.help = true;
|
|
else throw new Error(`未知参数:${a}`);
|
|
}
|
|
if (!args.json && !args.markdown) args.markdown = true;
|
|
return args;
|
|
}
|
|
|
|
function usage() {
|
|
return `用法:
|
|
node scripts/compare_fixture.js --fixture sample.fixture.json --actual node-output.json --field sign --markdown
|
|
node scripts/compare_fixture.js --fixture sample.fixture.json --actual node-output.json --expected-path expected.sign --actual-path output.sign --json`;
|
|
}
|
|
|
|
function readJson(p, label) {
|
|
if (!p) throw new Error(`必须提供 ${label}`);
|
|
return JSON.parse(fs.readFileSync(p, 'utf8').replace(/^\uFEFF/, ''));
|
|
}
|
|
|
|
function getPath(obj, p) {
|
|
if (!p) return undefined;
|
|
let cur = obj;
|
|
for (const part of p.split('.').filter(Boolean)) {
|
|
if (cur == null) return undefined;
|
|
cur = cur[part];
|
|
}
|
|
return cur;
|
|
}
|
|
|
|
function firstDefined(values) {
|
|
for (const v of values) if (v !== undefined) return v;
|
|
return undefined;
|
|
}
|
|
|
|
function normalize(v) {
|
|
if (v === undefined) return undefined;
|
|
if (typeof v === 'string') return v;
|
|
return JSON.stringify(v);
|
|
}
|
|
|
|
function compare(args) {
|
|
const fixture = readJson(args.fixture, '--fixture');
|
|
const actual = readJson(args.actual, '--actual');
|
|
const field = args.field || fixture.param || '';
|
|
const expectedPath = args.expectedPath || (field ? `expected.${field}` : 'expected');
|
|
const actualPath = args.actualPath || '';
|
|
const expected = firstDefined([getPath(fixture, expectedPath), field ? getPath(fixture, `expected.${field}`) : undefined, fixture.expectedValue]);
|
|
const actualValue = actualPath ? getPath(actual, actualPath) : firstDefined([
|
|
field ? getPath(actual, `output.${field}`) : undefined,
|
|
field ? getPath(actual, field) : undefined,
|
|
getPath(actual, 'output'),
|
|
getPath(actual, 'result'),
|
|
]);
|
|
const expectedText = normalize(expected);
|
|
const actualText = normalize(actualValue);
|
|
const pass = expected !== undefined && actualValue !== undefined && expectedText === actualText;
|
|
return { pass, field, expectedPath, actualPath: actualPath || '(自动识别)', expected, actual: actualValue, expectedText, actualText, fixture: args.fixture, actualFile: args.actual };
|
|
}
|
|
|
|
function renderMarkdown(result) {
|
|
const lines = ['# fixtures 对比结果', '', `- 结果:${result.pass ? '通过' : '失败'}`, `- 字段:${result.field || '未指定'}`, `- 期望路径:${result.expectedPath}`, `- 实际路径:${result.actualPath}`, `- 浏览器期望值:${result.expectedText === undefined ? '未找到' : result.expectedText}`, `- Node.js 实际值:${result.actualText === undefined ? '未找到' : result.actualText}`];
|
|
return lines.join('\n') + '\n';
|
|
}
|
|
|
|
try {
|
|
const args = parseArgs(process.argv);
|
|
if (args.help) { console.log(usage()); process.exit(0); }
|
|
const result = compare(args);
|
|
if (args.json) console.log(JSON.stringify(result, null, 2));
|
|
if (args.markdown) process.stdout.write(renderMarkdown(result));
|
|
if (!result.pass) process.exit(2);
|
|
} catch (err) {
|
|
console.error(err.message || String(err));
|
|
console.error(usage());
|
|
process.exit(1);
|
|
}
|