import { test } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { resolve, dirname } from 'node:path' const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..') const read = (rel: string) => readFileSync(resolve(repoRoot, rel), 'utf-8') /** 截取函数体:先按括号配平跳过参数列表,再按花括号配平取函数体(模板字面量里的 ${} 也是配对的,不影响计数)。 */ function functionBody(source: string, signature: string): string { const start = source.indexOf(signature) assert.ok(start >= 0, `未找到 ${signature}`) const openParen = source.indexOf('(', start) let parenDepth = 0 let cursor = openParen for (; cursor < source.length; cursor += 1) { if (source[cursor] === '(') parenDepth += 1 else if (source[cursor] === ')') { parenDepth -= 1 if (parenDepth === 0) break } } const openBrace = source.indexOf('{', cursor) let depth = 0 for (let i = openBrace; i < source.length; i += 1) { if (source[i] === '{') depth += 1 else if (source[i] === '}') { depth -= 1 if (depth === 0) return source.slice(openBrace, i + 1) } } throw new Error('函数体未闭合') } /** * 密钥卡片保存后必须清掉本地「检测输入值(未保存)」的结果: * 保存后输入框已清空,那份绿字不再代表当前配置,继续展示就会出现 * 「三项都显示检测通过、页面却提示尚未通过检测」的自相矛盾状态(2026-09-14 修复)。 */ test('密钥面板保存后清理过期检测结果', () => { const body = functionBody(read('src/shared/components/ApiSecretSettingsPanel.vue'), 'async function saveAll(') const saveIndex = body.indexOf('await saveApiSecret(') assert.ok(saveIndex >= 0, 'saveAll 应逐个保存模块输入值') const afterSave = body.slice(saveIndex) assert.match(afterSave, /state\.input = ''/, '保存后应清空输入框') assert.match(afterSave, /state\.result = null/, '保存后应清掉本地检测结果') assert.match(afterSave, /state\.lastCheckSource = ''/, '保存后应重置检测来源标记') }) /** * 门禁拦截提示必须带模块名:同一个密钥填进多个模块时, * 只列脱敏值会出现「sk-P****9BgQ、sk-P****9BgQ」这种分不清是哪个模块的提示。 */ test('密钥门禁提示按模块名列出未通过项', () => { const body = functionBody(read('src/pages/setup/DesktopSecretSetupPage.vue'), 'async function submit(') assert.match(body, /module\.moduleLabel/, '未通过提示应包含模块名') assert.match(body, /snapshot\.masked/, '未通过提示应包含脱敏值') })