返回 oh-my-ppt
source-plan.test.ts
根目录 / tests / unit / generation / source-plan.test.ts
1 import { describe, expect, it } from 'vitest'
2 import {
3 canUseSourcePlanDirectly,
4 mapSourcePlanToOutlineItems,
5 sourcePlanFromSkeletonRows
6 } from '../../../src/main/generation/source-plan'
7
8 describe('source page skeleton planning', () => {
9 it('normalizes database rows into a source plan', () => {
10 const sourcePlan = sourcePlanFromSkeletonRows([
11 {
12 page_number: 1,
13 title: '第一篇:认知篇',
14 role: 'chapter-divider',
15 source_document_path: '/docs/source.md',
16 source_document_name: 'source.md',
17 source_heading: '# 第一篇:认知篇',
18 heading_level: 1,
19 line_start: 10,
20 line_end: 28,
21 reason: 'major # heading after the topic',
22 confidence: 'high'
23 }
24 ])
25
26 expect(sourcePlan).toMatchObject({
27 confidence: 'high',
28 sourceDocumentPath: '/docs/source.md',
29 pageSkeleton: [
30 {
31 pageNumber: 1,
32 title: '第一篇:认知篇',
33 role: 'chapter-divider',
34 sourceHeading: '# 第一篇:认知篇',
35 lineStart: 10,
36 lineEnd: 28,
37 reason: ''
38 }
39 ]
40 })
41 })
42
43 it('uses only high-confidence matching skeletons without restructure requests', () => {
44 const sourcePlan = sourcePlanFromSkeletonRows([
45 {
46 page_number: 1,
47 title: 'Market',
48 role: 'content',
49 source_document_path: '/docs/source.md',
50 source_heading: '## Market',
51 heading_level: 2,
52 line_start: 3,
53 line_end: 20,
54 confidence: 'high'
55 }
56 ])
57
58 expect(canUseSourcePlanDirectly({ sourcePlan, totalPages: 1, userMessage: '按文档生成' })).toBe(true)
59 expect(canUseSourcePlanDirectly({ sourcePlan, totalPages: 2, userMessage: '按文档生成' })).toBe(false)
60 expect(canUseSourcePlanDirectly({ sourcePlan, totalPages: 1, userMessage: '压缩成 1 页' })).toBe(false)
61 })
62
63 it('maps skeleton rows into range-bound outline items', () => {
64 const sourcePlan = sourcePlanFromSkeletonRows([
65 {
66 page_number: 1,
67 title: '收入增长',
68 role: 'content',
69 source_document_path: '/docs/source.md',
70 source_heading: '## 收入增长',
71 heading_level: 2,
72 line_start: 30,
73 line_end: 48,
74 reason: 'leaf ## section without standalone child sections',
75 confidence: 'high'
76 }
77 ])
78 expect(sourcePlan).not.toBeNull()
79
80 const [item] = mapSourcePlanToOutlineItems(sourcePlan!)
81
82 expect(item).toMatchObject({
83 title: '收入增长',
84 layoutIntent: 'data-focus'
85 })
86 expect(item.contentOutline).toContain('Source heading: ## 收入增长')
87 expect(item.contentOutline).toContain('Source range: lines 30-48')
88 expect(item.contentOutline).not.toContain('Page purpose:')
89 expect(item.contentOutline).not.toContain('leaf ## section')
90 })
91
92 it('maps section agenda rows without source headings or ranges', () => {
93 const sourcePlan = sourcePlanFromSkeletonRows([
94 {
95 page_number: 1,
96 title: '二、技术参数与技术效率明细',
97 role: 'content',
98 source_document_path: '/docs/source.md',
99 source_heading: '## 二、技术参数与技术效率明细',
100 heading_level: 2,
101 line_start: 18,
102 line_end: 19,
103 reason:
104 '章节目录页:概览本章下的子主题,包括:2.1 主流AI动漫工具性能对比、2.2 训练数据规模、2.3 效率实证。',
105 confidence: 'high'
106 }
107 ])
108 expect(sourcePlan).not.toBeNull()
109
110 const [item] = mapSourcePlanToOutlineItems(sourcePlan!)
111
112 expect(item).toMatchObject({
113 title: '二、技术参数与技术效率明细',
114 layoutIntent: 'summary'
115 })
116 expect(item.contentOutline).toContain('Page role: section-agenda')
117 expect(item.contentOutline).toContain('2.1 主流AI动漫工具性能对比')
118 expect(item.contentOutline).not.toContain('Source heading:')
119 expect(item.contentOutline).not.toContain('Source range:')
120 })
121 })
122
122 lines TYPESCRIPT