import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import test from 'node:test'; const read = (path) => readFile(new URL(path, import.meta.url), 'utf8'); test('查全网与工作助手分入口分接口并持续显示外部来源提示', async () => { const [sop, webAi, webService] = await Promise.all([ read('../src/pages/user/sop/index.vue'), read('../src/pages/user/web-ai/index.vue'), read('../src/services/web-ai.ts') ]); assert.match(sop, /工作助手/); assert.match(sop, /查全网/); assert.match(webAi, /不与工作助手的内部资料混用/); assert.match(webAi, /答案来自互联网,不代表公司制度/); assert.match(webService, /\/api\/aihr\/web-ai\/query/); assert.doesNotMatch(webService, /\/api\/knowledge\/query/); }); test('问题榜、最佳答案、积分分账和无现金边界都有真实页面', async () => { const [routes, list, detail, points, service] = await Promise.all([ read('../src/pages.json'), read('../src/pages/user/questions/index.vue'), read('../src/pages/user/questions/detail.vue'), read('../src/pages/user/points/index.vue'), read('../src/services/questions.ts') ]); for (const route of ['pages/user/questions/index', 'pages/user/questions/detail', 'pages/user/questions/publish', 'pages/user/points/index']) { assert.match(routes, new RegExp(route.replaceAll('/', '\\/'))); } assert.match(list, /HOT/); assert.match(list, /UNANSWERED/); assert.match(list, /REWARDED/); assert.match(list, /MINE/); assert.match(detail, /最佳答案/); assert.match(points, /积分和学习学分,不是现金、不能提现/); assert.match(service, /\/api\/aihr\/community\/questions/); assert.match(service, /\/api\/aihr\/community\/points\/me/); }); test('员工考试与主管组卷路由、题目播报、真实人员多选和幂等发布齐全', async () => { const [routes, employee, edit, service] = await Promise.all([ read('../src/pages.json'), read('../src/pages/user/exam/index.vue'), read('../src/pages/supervisor/exams/edit.vue'), read('../src/services/exam.ts') ]); for (const route of ['pages/user/exam/index', 'pages/supervisor/exams/index', 'pages/supervisor/exams/edit', 'pages/supervisor/exams/results']) { assert.match(routes, new RegExp(route.replaceAll('/', '\\/'))); } assert.match(employee, /播报题目/); assert.match(employee, /submitMyExam/); assert.match(edit, /getPracticeTeamSnapshot/); assert.match(edit, /selectedMemberIds\.value\.length < 100/); assert.match(edit, /members\.value\.slice\(0, 100\)/); assert.match(edit, /requestId/); assert.doesNotMatch(edit, /title\.value\.trim\(\)\.length >= 4/); assert.match(edit, /请填写考试名称/); assert.match(edit, /publish-validation-message/); assert.match(service, /\/api\/aihr\/mobile\/exams\/supervisor/); }); test('每日题和专项可反馈,主管可按岗位筛选并对常见难题一键派专项', async () => { const [practice, assign, team, service] = await Promise.all([ read('../src/pages/user/practice/index.vue'), read('../src/pages/supervisor/assign/index.vue'), read('../src/pages/supervisor/team/index.vue'), read('../src/services/practice.ts') ]); assert.match(practice, /这道题对工作有帮助吗/); assert.match(practice, /这个专项对工作有帮助吗/); assert.match(assign, /场景、SOP 与题目按岗位版本加载/); for (const position of ['生活顾问', '客服', '保安', '保洁', '保修']) assert.match(assign, new RegExp(position)); assert.match(team, /一键派专项/); assert.match(team, /近30天 · 仅当前项目/); assert.match(service, /\/practice\/assignments\/\$\{assignmentId\}\/feedback/); assert.match(service, /\/practice\/difficulties\/assign/); }); test('老年用户可读性与窄屏布局保持最低字号、表单宽度和四栏标签完整', async () => { const [base, sop, questions] = await Promise.all([ read('../src/styles/base.css'), read('../src/pages/user/sop/index.vue'), read('../src/pages/user/questions/index.vue') ]); assert.match(base, /\.input\s*\{[\s\S]*?box-sizing:\s*border-box/); assert.match(base, /\.textarea\s*\{[\s\S]*?box-sizing:\s*border-box/); assert.doesNotMatch(sop, /font-size:\s*(?:[0-9]|1[01])px/); assert.match(questions, /grid-template-columns:\s*repeat\(4,\s*minmax\(0,\s*1fr\)\)/); });