import assert from 'node:assert/strict' import { spawnSync } from 'node:child_process' import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' /** * 小程序界面语种契约守卫 * ============================ * 复用 scripts/audit-miniapp-language.mjs 的全量扫描(A 文本节点 / B 属性 / * C picker 选项 / D JS 文案字段 / E 繁体字 / F 窗口标题),断言「0 命中」。 * * 为什么必须独立成守卫:2026-09 真机事故——后端枚举码(never_married / bachelor / * any / accept / reject)直接当展示值上屏,静态类型检查 / WXML·WXSS 编译 / 结构 * 守卫全都抓不到,只有人眼在真机才看得见。这是「界面必须全中文简体」唯一的自动化兜底。 * * 单一事实源:本守卫不重复实现扫描逻辑,而是直接派生 audit 脚本——改扫描规则只改一处。 */ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..') const auditScript = resolve(root, 'scripts/audit-miniapp-language.mjs') const r = spawnSync(process.execPath, [auditScript, '--json'], { cwd: root, encoding: 'utf8', env: { ...process.env, NO_COLOR: '1' }, }) let findings = [] if (r.status === 3) { // 审计脚本自身崩溃(异常分支),绝不能当成「通过」默默绿掉 throw new Error( '语种审计脚本执行失败(exit 3),请先修复 scripts/audit-miniapp-language.mjs:\n' + (r.stderr || r.stdout || '(无输出)'), ) } if (r.stdout && r.stdout.trim()) { try { findings = JSON.parse(r.stdout) } catch { // 理论上 --json 只输出 JSON;解析失败则交给下面的长度断言兜底 } } assert.equal( findings.length, 0, `小程序仍存在英文/非中文简体上屏(${findings.length} 处)。示例:\n` + findings .slice(0, 8) .map((f) => ` ${f.file}:${f.line} [${f.kind}] ${f.detail}`) .join('\n'), ) console.log(`Miniapp language contracts passed(语种审计 0 命中)`)