131 lines
6.0 KiB
JavaScript
131 lines
6.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
||
import { readFile } from 'node:fs/promises';
|
||
import test from 'node:test';
|
||
|
||
const source = (path) => readFile(new URL(path, import.meta.url), 'utf8');
|
||
const idHelpers = await import('../src/services/personal-assistant-id.ts');
|
||
|
||
test('Snowflake ID 全程保留字符串精度并安全生成详情路径', () => {
|
||
const hugeId = '1990000000000000000';
|
||
assert.equal(idHelpers.normalizeBackendId(hugeId), hugeId);
|
||
assert.equal(idHelpers.personalItemRoute(hugeId), `/pages/user/assistant/item?id=${hugeId}`);
|
||
assert.equal(idHelpers.personalItemApiPath(hugeId), `/api/aihr/personal-assistant/items/${hugeId}`);
|
||
assert.equal(idHelpers.personalSessionApiPath(hugeId), `/api/aihr/personal-assistant/sessions/${hugeId}`);
|
||
});
|
||
|
||
test('个人助理 API 固定使用登录态且不接收 owner 参数', async () => {
|
||
const [client, api] = await Promise.all([
|
||
source('../src/services/personal-assistant.ts'),
|
||
source('../src/services/api.ts')
|
||
]);
|
||
assert.match(client, /apiRequest/);
|
||
assert.match(client, /\/api\/aihr\/personal-assistant\/ask/);
|
||
assert.match(client, /\/api\/aihr\/personal-assistant\/items\/file/);
|
||
assert.match(client, /uni\.uploadFile/);
|
||
assert.match(client, /sessionId\?: string/);
|
||
assert.match(client, /itemIds\?: string\[\]/);
|
||
assert.match(client, /loadPersonalItem = \(id: string\)/);
|
||
assert.match(client, /loadPersonalSession = \(id: string\)/);
|
||
assert.doesNotMatch(client, /ownerUserId|tenantId/);
|
||
assert.doesNotMatch(client, /clearAuthOnUnauthorized:\s*false/);
|
||
assert.doesNotMatch(api, /statusCode === 401 \|\| statusCode === 403/);
|
||
assert.match(api, /statusCode === 401 \|\| code === 401/);
|
||
});
|
||
|
||
test('问答首页默认只查询个人资料并展示真实引用域', async () => {
|
||
const page = await source('../src/pages/user/assistant/index.vue');
|
||
assert.match(page, /ref<KnowledgeScope\[\]>\(\['PERSONAL'\]\)/);
|
||
assert.match(page, /我的资料/);
|
||
assert.match(page, /企业知识按岗位权限/);
|
||
assert.match(page, /企业 SOP/);
|
||
assert.match(page, /外部网页/);
|
||
assert.match(page, /citation\.domain/);
|
||
assert.match(page, /citation\.itemId/);
|
||
assert.match(page, /citation\.sourceType/);
|
||
assert.doesNotMatch(page, /loadPersonalItem/);
|
||
assert.match(page, /answer\.value = undefined/);
|
||
assert.match(page, /requestGeneration/);
|
||
assert.match(page, /:disabled="asking"/);
|
||
assert.match(page, /if \(asking\.value\) return/);
|
||
assert.match(page, /scopeSnapshot/);
|
||
assert.match(page, /scopeKey\(scopes\.value\)/);
|
||
assert.match(page, /收藏资料/);
|
||
assert.doesNotMatch(page, /ownerUserId|tenantId/);
|
||
});
|
||
|
||
test('资料库和收藏页覆盖分页筛选以及三种真实收藏方式', async () => {
|
||
const [library, capture] = await Promise.all([
|
||
source('../src/pages/user/assistant/library.vue'),
|
||
source('../src/pages/user/assistant/capture.vue')
|
||
]);
|
||
assert.match(library, /pageNum/);
|
||
assert.match(library, /sourceType/);
|
||
assert.match(library, /status/);
|
||
assert.match(library, /dateFrom/);
|
||
assert.match(library, /dateTo/);
|
||
assert.match(library, /mode="date"/);
|
||
assert.match(library, /dateFrom: dateFrom\.value/);
|
||
assert.match(library, /dateTo: dateTo\.value/);
|
||
assert.match(library, /loadPersonalItems/);
|
||
assert.match(library, /requestGeneration/);
|
||
assert.match(library, /pageSnapshot/);
|
||
assert.match(library, /mergePersonalRows/);
|
||
assert.match(library, /pageNum\.value = Math\.max/);
|
||
assert.match(capture, /TEXT/);
|
||
assert.match(capture, /FILE/);
|
||
assert.match(capture, /URL/);
|
||
assert.match(capture, /createTextItem/);
|
||
assert.match(capture, /uploadPersonalFile/);
|
||
assert.match(capture, /createUrlItem/);
|
||
});
|
||
|
||
test('个人资料详情包含全部状态、重试、下载和明确删除提示', async () => {
|
||
const page = await source('../src/pages/user/assistant/item.vue');
|
||
assert.match(page, /QUEUED/);
|
||
assert.match(page, /PARSING/);
|
||
assert.match(page, /READY/);
|
||
assert.match(page, /FAILED/);
|
||
assert.match(page, /DELETING/);
|
||
assert.match(page, /DELETED/);
|
||
assert.match(page, /retryPersonalItem/);
|
||
assert.match(page, /deletePersonalItem/);
|
||
assert.match(page, /downloadPersonalItem/);
|
||
assert.match(page, /附件、解析正文和搜索索引/);
|
||
assert.match(page, /normalizeBackendId\(String\(options\?\.id/);
|
||
assert.doesNotMatch(page, /Number\(options\?\.id|parseInt\(options\?\.id|Number\.isSafeInteger/);
|
||
});
|
||
|
||
test('扫描 PDF 详情展示识别进度、部分失败和失败页重试', async () => {
|
||
const ocr = await import('../src/services/personal-assistant-ocr.ts');
|
||
const page = await source('../src/pages/user/assistant/item.vue');
|
||
assert.equal(ocr.ocrProgressText({ required: true, status: 'RUNNING', totalPages: 86, processedPages: 20, successPages: 20, failedPages: 0, failedPageNumbers: [] }), '正在识别扫描 PDF:20/86 页');
|
||
assert.equal(ocr.ocrProgressText({ required: true, status: 'PARTIAL', totalPages: 8, processedPages: 8, successPages: 6, failedPages: 2, failedPageNumbers: [3, 7] }), '已收录,2 页识别失败');
|
||
assert.match(page, /retryPersonalOcrPages/);
|
||
assert.match(page, /识别失败页/);
|
||
assert.match(page, /ocrProgressPercent/);
|
||
assert.match(page, /setTimeout/);
|
||
});
|
||
|
||
test('会话页覆盖列表、详情和删除且不伪造会话', async () => {
|
||
const page = await source('../src/pages/user/assistant/sessions.vue');
|
||
assert.match(page, /loadPersonalSessions/);
|
||
assert.match(page, /loadPersonalSession/);
|
||
assert.match(page, /deletePersonalSession/);
|
||
assert.match(page, /暂无历史会话/);
|
||
assert.match(page, /chat\.role\.toLowerCase\(\) === 'user'/);
|
||
});
|
||
|
||
test('个人助理路由已注册且企业 SOP 问答保留独立入口', async () => {
|
||
const [pages, sop] = await Promise.all([
|
||
source('../src/pages.json'),
|
||
source('../src/pages/user/sop/index.vue')
|
||
]);
|
||
for (const route of ['index', 'library', 'capture', 'item', 'sessions']) {
|
||
assert.match(pages, new RegExp(`pages/user/assistant/${route}`));
|
||
}
|
||
assert.match(sop, /个人助理/);
|
||
assert.match(sop, /我的资料/);
|
||
assert.match(sop, /企业 SOP/);
|
||
assert.match(sop, /\/pages\/user\/assistant\/index/);
|
||
});
|