Files
prop-ai-hr/mobile-uni/tests/customer-feedback-closure.test.mjs
T
admin bb8b2dde7e fix(exam): replace unfounded 4-char title rule with explicit validation messages
- 考试名称仅要求非空,移除无依据的至少 4 字限制;保留及格分 1-100、
  至少一题、总分 100、题干/选项/答案完整、至少一名员工的发布校验
- 发布坞展示具体校验失败原因,不再静默禁用按钮
- CHANGELOG/README 同步 2026-07-25 组织姓名定向补齐与生产复核记录
2026-07-25 18:15:32 +08:00

92 lines
4.3 KiB
JavaScript

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\)\)/);
});