112 lines
5.7 KiB
JavaScript
112 lines
5.7 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const { readFileSync } = require('node:fs');
|
|
const { test } = require('node:test');
|
|
const ts = require('typescript');
|
|
|
|
function loadSource(relativePath) {
|
|
return ts.createSourceFile(
|
|
relativePath,
|
|
readFileSync(`${__dirname}/../src/${relativePath}`, 'utf8'),
|
|
ts.ScriptTarget.Latest,
|
|
true,
|
|
ts.ScriptKind.TSX,
|
|
).getFullText();
|
|
}
|
|
|
|
const editPage = loadSource('pages/accounts/$id/edit.tsx');
|
|
const detailPage = loadSource('pages/accounts/$id/index.tsx');
|
|
const fingerprintFields = loadSource('components/accounts/FingerprintFields.tsx');
|
|
const createPage = loadSource('pages/accounts/new.tsx');
|
|
|
|
test('账号资料表单按三行分组:登录用户名/更新密码/业务状态、实名三项、账号备注', () => {
|
|
// 第一行:登录用户名、更新密码、业务状态在同一个 Row 中按序出现
|
|
const firstRow = editPage.indexOf('<Row gutter={16}>');
|
|
const businessStatus = editPage.indexOf('name="business_status"');
|
|
const secondRow = editPage.indexOf('<Row gutter={16}>', firstRow + 1);
|
|
assert.ok(firstRow > -1 && businessStatus > firstRow && businessStatus < secondRow, '登录用户名/更新密码/业务状态应同属第一行');
|
|
assert.ok(editPage.includes('name="login_username"') && editPage.includes('name="password"'), '第一行应包含登录用户名与更新密码');
|
|
|
|
// 第二行:实名状态、实名姓名、实名证件号
|
|
const noteItem = editPage.indexOf('name="note"');
|
|
assert.ok(secondRow > firstRow && secondRow < noteItem, '实名三项应与第一行分行');
|
|
assert.ok(
|
|
editPage.includes('name="real_name_status"') && editPage.includes('name="real_name"') && editPage.includes('name="identity_number"'),
|
|
'第二行应包含实名状态、实名姓名、实名证件号',
|
|
);
|
|
|
|
// 账号备注独占一行(不包在 Row/Col 中)
|
|
assert.ok(
|
|
!editPage.slice(editPage.lastIndexOf('<Row gutter={16}>', noteItem), noteItem).includes('name="note"'),
|
|
'账号备注不应在 Row 内',
|
|
);
|
|
});
|
|
|
|
test('指纹浏览器环境独立卡片单独保存,不混入账号资料保存', () => {
|
|
assert.ok(editPage.includes('title="指纹浏览器环境"'), '指纹环境应为独立卡片');
|
|
assert.ok(editPage.includes('>保存指纹<') || editPage.includes('保存指纹'), '指纹卡片应有独立保存按钮');
|
|
assert.match(editPage, /\/creator\/accounts\/\$\{encodeURIComponent\(selected\.id\)\}\/fingerprint/);
|
|
assert.ok(editPage.includes('<FingerprintFields />'), '指纹字段应复用共享组件');
|
|
assert.ok(editPage.includes('fpForm.validateFields()'), '指纹保存前应先校验表单');
|
|
});
|
|
|
|
test('指纹保存后按运行状态提示:运行中重启 / 未运行下次启动生效', () => {
|
|
assert.ok(editPage.includes("result?.runtime_id ? '指纹已保存,运行环境已用新配置重启。' : '指纹已保存,将在环境下次启动时生效。'"));
|
|
});
|
|
|
|
test('编辑页加载时从账号详情内联 environment.fingerprint 回显指纹', () => {
|
|
assert.ok(editPage.includes("getOne('accounts', selectedID)"), '编辑页应请求账号详情');
|
|
assert.match(editPage, /fingerprintFormValues\(detail\?\.environment\?\.fingerprint\)/);
|
|
});
|
|
|
|
test('账号资料保存保留现有冷却时间,不再发送 NaN', () => {
|
|
assert.ok(
|
|
editPage.includes('cooldown_seconds: selected.cooldown_seconds'),
|
|
'cooldown_seconds 应透传当前值,避免 Number(undefined)=NaN 被 400 拒绝',
|
|
);
|
|
assert.ok(!editPage.includes('Number(values.cooldown_seconds)'), '不得再从缺失的表单字段计算冷却时间');
|
|
});
|
|
|
|
test('共享指纹字段:载荷只含非空项,disable_spoofing 以逗号合并', () => {
|
|
assert.match(fingerprintFields, /fp\.disable_spoofing\?\.length\) payload\.disable_spoofing = fp\.disable_spoofing\.join\(','\)/);
|
|
assert.match(fingerprintFields, /if \(fp\.timezone\?\.trim\(\)\) payload\.timezone = fp\.timezone\.trim\(\)/);
|
|
assert.match(fingerprintFields, /payload\.hardware_concurrency = fp\.hardware_concurrency/);
|
|
});
|
|
|
|
test('共享指纹字段:回显把逗号字符串拆回多选数组', () => {
|
|
assert.match(fingerprintFields, /String\(fp\.disable_spoofing\)\.split\(','\)/);
|
|
});
|
|
|
|
for (const [pageName, page] of [['详情页', detailPage], ['编辑页', editPage]]) {
|
|
test(`${pageName}账号标题不保留上下外边距`, () => {
|
|
assert.match(page, /Typography\.Title level=\{5\} style=\{\{ margin: 0 \}\}/);
|
|
});
|
|
}
|
|
|
|
test('账号创建成功后回到账号列表,不自动进入编辑页', () => {
|
|
assert.match(createPage, /history\.replace\('\/accounts'\)/);
|
|
assert.doesNotMatch(createPage, /history\.replace\(`\/accounts\/\$\{encodeURIComponent\(id\)\}\/edit`\)/);
|
|
});
|
|
|
|
test('资料保存不承载独立登录弹窗的处理中状态', () => {
|
|
assert.match(editPage, /htmlType="submit" loading=\{busy\}/);
|
|
assert.match(editPage, /const \[loginOpen, setLoginOpen\] = useState\(false\)/);
|
|
assert.match(editPage, /onClick=\{\(\) => setLoginOpen\(true\)\}/);
|
|
assert.match(editPage, /<AccountLoginModal/);
|
|
assert.doesNotMatch(editPage, /async function (requestLoginQR|verifyLogin)\(/);
|
|
});
|
|
|
|
test('创建账号不填写 UID,UID 仅在详情和编辑页只读显示', () => {
|
|
assert.doesNotMatch(createPage, /platform_account_key/);
|
|
assert.match(editPage, /label="UID"/);
|
|
assert.match(editPage, /copyable>\{selected\.platform_account_key\}/);
|
|
assert.match(editPage, /首次登录核验后自动绑定/);
|
|
assert.doesNotMatch(editPage, /name="platform_account_key"/);
|
|
assert.match(detailPage, /label="UID"/);
|
|
});
|
|
|
|
test('创建页与编辑页共用同一指纹字段组件', () => {
|
|
assert.ok(createPage.includes("from '@/components/accounts/FingerprintFields'"));
|
|
assert.ok(createPage.includes('<FingerprintFields />'));
|
|
assert.match(createPage, /fingerprintPayload\(values\.fingerprint\)/);
|
|
});
|