import { describe, expect, test } from 'vitest'; import type { PersistedClassroomData } from '@/lib/server/classroom-storage'; import { buildCourseModuleOutputDigest, formatPreviousModuleContext, } from '@/lib/course-framework/module-digest'; function classroomFixture(): PersistedClassroomData { return { id: 'classroom-actual-1', createdAt: '2026-08-15T09:00:00.000Z', stage: { id: 'stage-1', name: '实际生成的机器学习基础' } as never, scenes: [ { id: 'scene-slide', stageId: 'stage-1', order: 1, title: '监督学习基础', type: 'slide', content: { type: 'slide', canvas: { id: 'slide-1', viewportSize: 1000, viewportRatio: 0.5625, theme: {}, elements: [ { id: 'text-1', type: 'text', content: '

特征、标签与训练样本

', }, ], }, }, actions: [{ id: 'speech-1', type: 'speech', text: '比较监督学习和无监督学习。' }], }, { id: 'scene-interactive', stageId: 'stage-1', order: 2, title: '分类边界实验室', type: 'interactive', content: { type: 'interactive', widgetType: 'simulation', widgetConfig: { type: 'simulation', concept: '决策边界', challenge: '调整样本分布' }, html: '

拖动数据点观察边界变化

', }, }, { id: 'scene-quiz', stageId: 'stage-1', order: 3, title: '概念检查', type: 'quiz', content: { type: 'quiz', questions: [ { id: 'q-1', type: 'single', question: '标签在监督学习中承担什么作用?', }, ], }, }, { id: 'scene-pbl', stageId: 'stage-1', order: 4, title: '识别真实业务问题', type: 'pbl', content: { type: 'pbl', projectV2: { title: '业务问题分类项目', description: '判断问题适合监督学习还是无监督学习。', learningObjective: '能够把业务目标转成学习任务。', milestones: [{ title: '提交问题定义' }], }, }, }, ] as never, }; } describe('course module output digest', () => { test('extracts bounded evidence from all four actual scene types', () => { const digest = buildCourseModuleOutputDigest(classroomFixture()); expect(digest.sceneTypeCounts).toEqual({ slide: 1, quiz: 1, interactive: 1, pbl: 1 }); expect(digest.sceneCount).toBe(4); expect(digest.coveredConcepts).toContain('监督学习基础'); expect(digest.coveredConcepts).toContain('特征、标签与训练样本'); expect(digest.coveredConcepts).toContain('拖动数据点观察边界变化'); expect(digest.coveredConcepts.join(' ')).not.toContain('ignore()'); expect(digest.assessments).toContain('标签在监督学习中承担什么作用?'); expect(digest.assessments).toContain('提交问题定义'); expect(digest.interactiveExperiences).toEqual([ '分类边界实验室(simulation, interactive-html)', '识别真实业务问题(PBL)', ]); expect(digest.semanticHash).toMatch(/^sha256:[a-f0-9]{64}$/); expect(buildCourseModuleOutputDigest(classroomFixture()).semanticHash).toBe( digest.semanticHash, ); }); test('formats actual prior outputs as bounded continuity context', () => { const digest = buildCourseModuleOutputDigest(classroomFixture()); const context = formatPreviousModuleContext([ { index: 1, title: '基础模块', outputDigest: digest }, { index: 2, title: '练习模块', outputDigest: { ...digest, classroomId: 'classroom-2' } }, ]); expect(context).toContain('模块 1《基础模块》'); expect(context).toContain('实际摘要'); expect(context).toContain('实际覆盖'); expect(context).toContain('实际语义哈希'); expect(context).toContain('分类边界实验室(simulation, interactive-html)'); expect(context.length).toBeLessThanOrEqual(12_000); }); });