| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- import test from 'node:test';
- import assert from 'node:assert/strict';
- import { COURSE_DELIVERABLES, courseModuleOf } from '../skills/ksf-workshop-runtime/scripts/course-deliverables.mjs';
- import { DELIVERY_SCHEMA } from '../skills/ksf-workshop-runtime/scripts/report-contract.mjs';
- import { workshopReview } from '../src/core/workshop-outputs.js';
- import { REPORT_TYPES } from '../src/core/library/types.js';
- const chapter = text => ({ id: 'analysis', title: '实际正文', sections: [{ kind: 'para', text }] });
- const row = (moduleId, overrides = {}) => ({ id: moduleId, type: 'assessment_report', memberId: 'employee-a',
- workshopKey: 'topic-a', dataMode: 'live', version: 1, reportSeriesKey: `topic-a:${moduleId}:report`,
- report: { chapters: [chapter('该环节已保存的实质内容')] }, ...overrides });
- const view = artifacts => workshopReview({ artifacts, members: [{ id: 'employee-a', name: '甲' }, { id: 'employee-b', name: '乙' }] },
- { groups: [], assignments: {} }, { mode: 'all' });
- const topics = result => result.hierarchy.flatMap(group => group.members.flatMap(member => member.topics));
- test('13 个环节覆盖完整课程,11 个阅读分类和七类内容索引不能代替课程清单', () => {
- assert.deepEqual(COURSE_DELIVERABLES.map(output => output.moduleId), [
- 'D1-01', 'D1-02', 'D1-03', 'D1-04', 'D1-N', 'D2-01', 'D2-02', 'D2-03', 'D2-04', 'D2-05', 'D2-06', 'D2-07', 'D2-08',
- ]);
- assert.equal(REPORT_TYPES.length, 11);
- const topic = topics(view(COURSE_DELIVERABLES.map(output => row(output.moduleId))))[0];
- assert.equal(topic.courseOutputs.length, 13);
- assert.equal(topic.courseOutputs.filter(output => output.state === 'has-body').length, 13);
- assert.equal(topic.outputs.length, 7, '旧内容索引保留兼容,不影响13项环节导航');
- });
- test('同一环节多报告或附件不增加环节份数,配置卡、任务卡、验收与指标各有位置', () => {
- const artifacts = ['D1-02', 'D1-04', 'D2-01', 'D2-03', 'D2-04'].map(moduleId => row(moduleId));
- artifacts.push(row('D2-04', { id: 'card-two', reportSeriesKey: 'topic-a:D2-04:card-two',
- report: { chapters: [chapter('第二张候选卡')], attachments: [{ name: 'report.html' }] } }));
- const ledger = topics(view(artifacts))[0].courseOutputs;
- assert.equal(ledger.filter(output => output.state === 'has-body').length, 5);
- assert.equal(ledger.find(output => output.moduleId === 'D2-04').reports.length, 2);
- });
- test('旧系列接受冒号或斜线,标题猜测、非法交付标记和互相矛盾的环节不计数', () => {
- assert.equal(courseModuleOf(row('D1-01', { reportSeriesKey: 'topic-a/D1-01' })), 'D1-01');
- assert.equal(courseModuleOf(row('D1-01', { reportSeriesKey: '', title: 'D1-01 品类全景图谱' })), '');
- const delivery = { schema: DELIVERY_SCHEMA, moduleId: 'D1-02', kind: 'method', outputs: [], contentStatus: 'ready' };
- assert.equal(courseModuleOf(row('D1-01', { report: { delivery, chapters: [chapter('冲突内容')] } })), '');
- assert.equal(courseModuleOf(row('D1-02', { report: { delivery: { ...delivery, schema: 'invalid' }, chapters: [chapter('正文')] } })), '');
- const topic = topics(view([row('D1-01', { reportSeriesKey: '', title: 'D1-01 品类全景图谱' })]))[0];
- assert.equal(topic.courseUnlocatedCount, 1);
- assert.equal(topic.courseOutputs.every(output => output.state === 'missing'), true);
- });
- test('仅原文、草稿、空章节、未保存分别显示,有正文不被称为质量通过或员工确认', () => {
- const artifacts = [row('D1-01', { report: null, rawText: '只有旧原文' }),
- row('D1-02', { report: { delivery: { schema: DELIVERY_SCHEMA, moduleId: 'D1-02', kind: 'method', contentStatus: 'draft', outputs: [] }, chapters: [chapter('配置草稿')] } }),
- row('D1-03', { report: { chapters: [chapter('')] } })];
- const ledger = topics(view(artifacts))[0].courseOutputs;
- assert.deepEqual(ledger.slice(0, 4).map(output => output.state), ['text-only', 'draft', 'missing-body', 'missing']);
- assert.equal(ledger.some(output => output.state === 'completed' || output.state === 'accepted'), false);
- });
- test('最新版缺正文不能借用历史版补齐,作者、课题与模式的报告不能互相补足', () => {
- const artifacts = [row('D1-01'), row('D1-01', { id: 'v2', version: 2, report: { chapters: [chapter('')] } }),
- row('D1-02', { memberId: 'employee-b' }), row('D1-03', { workshopKey: 'topic-b' }), row('D1-04', { dataMode: 'sample' })];
- const result = view(artifacts);
- const employee = result.hierarchy.flatMap(group => group.members).find(member => member.id === 'employee-a');
- const current = employee.topics.find(topic => topic.workshopKey === 'topic-a' && topic.mode === 'live');
- assert.deepEqual(current.courseOutputs.slice(0, 4).map(output => output.state), ['missing-body', 'missing', 'missing', 'missing']);
- assert.equal(current.courseOutputs[0].reports.length, 1);
- assert.equal(current.courseOutputs[0].reports[0].id, 'v2');
- });
|