visual-acceptance-check.smoke.mjs
3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/usr/bin/env node
/**
* 冒烟检查(不进 vitest 套件):visual-acceptance-check.mjs 四个子命令各跑一次,
* 用真实 Chromium + 一份现造的最小 HTML fixture,断言输出形状与已知答案。
* 起真浏览器要几秒,故意不挂进 vitest 的快速单测循环——手动跑:
* node scripts/visual-acceptance-check.smoke.mjs
*/
import assert from 'assert';
import { execFileSync } from 'child_process';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { fileURLToPath } from 'url';
const CLI = fileURLToPath(new URL('./visual-acceptance-check.mjs', import.meta.url));
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'visual-check-smoke-'));
const htmlPath = path.join(tmpDir, 'index.html');
// 故意做成「小宽度会溢出、大宽度不会」,且带一个必定失败的图片请求,
// 已知答案才好断言,不是随手糊一份页面
fs.writeFileSync(htmlPath, `<!DOCTYPE html>
<html><head><style>
body { margin: 0; }
.wide { width: 500px; height: 10px; background: #000; }
.title { color: #1d1d1f; background: #ffffff; font-size: 40px; }
</style></head>
<body>
<div class="title">Hi</div>
<div class="wide"></div>
<img src="./does-not-exist.png">
<script>console.error('boom');</script>
</body></html>`);
function run(args) {
const out = execFileSync(process.execPath, [CLI, ...args], { encoding: 'utf8' });
return JSON.parse(out.trim().split('\n').pop());
}
// ① overflow:375 应该溢出(.wide 是 500px),1440 不该溢出
{
const r = run(['overflow', '--file', htmlPath, '--widths', '375,1440']);
const at375 = r.widths.find((w) => w.width === 375);
const at1440 = r.widths.find((w) => w.width === 1440);
assert.strictEqual(at375.overflow, true, '375px 视口下 500px 宽的 div 应该判定为溢出');
assert.strictEqual(at1440.overflow, false, '1440px 视口下不该溢出');
assert.strictEqual(r.overflow_any, true);
console.log('✓ overflow');
}
// ② style:真读到 .title 的 font-size 计算值
{
const r = run(['style', '--file', htmlPath, '--selector', '.title', '--prop', 'font-size']);
assert.strictEqual(r.value, '40px', `期望 40px,实得 ${r.value}`);
assert.strictEqual(r.found, true);
console.log('✓ style');
}
// ③ console:真捕获到 console.error 与失败的图片请求
{
const r = run(['console', '--file', htmlPath]);
assert.ok(r.console_errors.includes('boom'), 'console_errors 应包含页面里那条 console.error');
assert.ok(r.failed_requests.length >= 1, '应该捕获到 does-not-exist.png 的失败请求');
assert.strictEqual(r.clean, false);
console.log('✓ console');
}
// ④ contrast:#1d1d1f / #ffffff 是真实网站常用的高对比度组合,已知比值约 16.8:1
{
const r = run(['contrast', '--fg', '#1d1d1f', '--bg', '#ffffff']);
assert.ok(r.ratio > 16 && r.ratio < 17.5, `期望约 16.8:1,实得 ${r.ratio}`);
assert.strictEqual(r.wcag_aa_normal_text, true);
console.log('✓ contrast');
}
fs.rmSync(tmpDir, { recursive: true, force: true });
console.log('全部通过');