返回 oh-my-ppt
chat-send-utils.test.ts
根目录 / tests / unit / session / chat-send-utils.test.ts
1 import { describe, expect, it } from 'vitest'
2 import {
3 isChatSendBlocked,
4 isUnsupportedMainSessionPageStructureRequest,
5 resolveChatSendContext,
6 resolveMainSessionEdit
7 } from '../../../src/renderer/src/components/session-detail/hooks/chatSendUtils'
8 import type { SessionPreviewPage } from '../../../src/renderer/src/components/session-detail/shared/types'
9
10 const page = {
11 id: 'page-record-2',
12 pageId: 'page-2',
13 pageNumber: 2,
14 title: 'Second page',
15 html: '<html></html>',
16 htmlPath: '/tmp/page-2.html'
17 } satisfies SessionPreviewPage
18
19 describe('chat send utils', () => {
20 it('blocks empty, duplicate, and in-progress sends', () => {
21 expect(
22 isChatSendBlocked({
23 sessionId: 'session-1',
24 sending: false,
25 generating: false,
26 input: ' ',
27 pendingAssetCount: 0
28 })
29 ).toBe(true)
30 expect(
31 isChatSendBlocked({
32 sessionId: 'session-1',
33 sending: true,
34 generating: false,
35 input: 'Update this page',
36 pendingAssetCount: 0
37 })
38 ).toBe(true)
39 expect(
40 isChatSendBlocked({
41 sessionId: 'session-1',
42 sending: false,
43 generating: true,
44 input: 'Update this page',
45 pendingAssetCount: 0
46 })
47 ).toBe(true)
48 })
49
50 it('allows asset-only messages', () => {
51 expect(
52 isChatSendBlocked({
53 sessionId: 'session-1',
54 sending: false,
55 generating: false,
56 input: '',
57 pendingAssetCount: 1
58 })
59 ).toBe(false)
60 })
61
62 it('forces selector messages into the selected page context', () => {
63 expect(
64 resolveChatSendContext({
65 selectedSelector: ' [data-block-id="hero"] ',
66 chatType: 'main',
67 selectedPage: page,
68 firstPage: page
69 })
70 ).toEqual({
71 ready: true,
72 hasSelector: true,
73 selector: '[data-block-id="hero"]',
74 chatType: 'page',
75 targetPageId: 'page-record-2',
76 targetPagePath: '/tmp/page-2.html',
77 messagePageId: 'page-record-2'
78 })
79 })
80
81 it('rejects page chat when no page exists', () => {
82 expect(
83 resolveChatSendContext({
84 selectedSelector: null,
85 chatType: 'page',
86 selectedPage: null,
87 firstPage: null
88 })
89 ).toEqual({ ready: false })
90 })
91
92 it('infers explicit main-session page targets without editing the whole deck', () => {
93 const pages = [
94 { pageId: 'page-1', pageNumber: 1 },
95 { pageId: 'page-2', pageNumber: 2 },
96 { pageId: 'page-3', pageNumber: 3 }
97 ]
98
99 expect(resolveMainSessionEdit('只修改第 2 页的标题', pages, 'page-1')).toEqual({
100 ready: true,
101 selectPageIds: ['page-2']
102 })
103 expect(resolveMainSessionEdit('只修改第三页的标题', pages, 'page-1')).toEqual({
104 ready: true,
105 selectPageIds: ['page-3']
106 })
107 expect(resolveMainSessionEdit('不要改所有页面,只改第 2 页', pages, 'page-1')).toEqual({
108 ready: true,
109 selectPageIds: ['page-2']
110 })
111 expect(resolveMainSessionEdit('调整当前页和 P3 的配色', pages, 'page-2')).toEqual({
112 ready: true,
113 selectPageIds: ['page-2', 'page-3']
114 })
115 expect(resolveMainSessionEdit('统一第 1-3 页的字体', pages, 'page-1')).toEqual({
116 ready: true,
117 selectPageIds: ['page-1', 'page-2', 'page-3']
118 })
119 })
120
121 it('supports Chinese page ranges and hundred-level page numbers', () => {
122 const pages = Array.from({ length: 120 }, (_, index) => ({
123 pageId: `page-${index + 1}`,
124 pageNumber: index + 1
125 }))
126
127 expect(resolveMainSessionEdit('统一第十到第十二页的字体', pages, 'page-1')).toEqual({
128 ready: true,
129 selectPageIds: ['page-10', 'page-11', 'page-12']
130 })
131 expect(resolveMainSessionEdit('修改第一百零一页的标题', pages, 'page-1')).toEqual({
132 ready: true,
133 selectPageIds: ['page-101']
134 })
135 })
136
137 it('keeps an explicit all-pages request unscoped and rejects unknown pages', () => {
138 const pages = [
139 { pageId: 'intro', pageNumber: 1 },
140 { pageId: 'summary', pageNumber: 2 }
141 ]
142
143 expect(resolveMainSessionEdit('统一所有页面的标题颜色', pages, 'intro')).toEqual({
144 ready: true,
145 selectPageIds: []
146 })
147 expect(resolveMainSessionEdit('修改第 9 页', pages, 'intro')).toEqual({
148 ready: false,
149 reason: 'page-not-found'
150 })
151 })
152
153 it('blocks unsupported page structure operations without blocking edits inside a page', () => {
154 const pages = [{ pageId: 'page-2', pageNumber: 2 }]
155
156 expect(isUnsupportedMainSessionPageStructureRequest('删除第 2 页')).toBe(true)
157 expect(isUnsupportedMainSessionPageStructureRequest('新增一页总结')).toBe(true)
158 expect(isUnsupportedMainSessionPageStructureRequest('删除第 2 页的图表')).toBe(false)
159 expect(isUnsupportedMainSessionPageStructureRequest('添加页面标题')).toBe(false)
160 expect(isUnsupportedMainSessionPageStructureRequest('添加页面的标题')).toBe(false)
161 expect(isUnsupportedMainSessionPageStructureRequest('add page title')).toBe(false)
162 expect(isUnsupportedMainSessionPageStructureRequest("add page's title")).toBe(false)
163 expect(resolveMainSessionEdit('删除第 2 页的图表', pages, 'page-2')).toEqual({
164 ready: true,
165 selectPageIds: ['page-2']
166 })
167 })
168 })
169
169 lines TYPESCRIPT