返回 oh-my-ppt
session-store-messages.test.ts
根目录 / tests / unit / editor / session-store-messages.test.ts
1 import { beforeEach, describe, expect, it, vi } from 'vitest'
2
3 const ipcMocks = vi.hoisted(() => ({
4 getSession: vi.fn(),
5 getSessionMessages: vi.fn()
6 }))
7
8 vi.mock('@renderer/lib/ipc', () => ({
9 ipc: {
10 getSession: ipcMocks.getSession,
11 getSessionMessages: ipcMocks.getSessionMessages
12 }
13 }))
14
15 import { useSessionStore, type Message } from '@renderer/store/sessionStore'
16
17 const message: Message = {
18 id: 'message-1',
19 session_id: 'session-1',
20 chat_scope: 'page',
21 page_id: 'page-1',
22 role: 'user',
23 content: '保留这条消息',
24 type: 'text',
25 tool_name: null,
26 tool_call_id: null,
27 token_count: null,
28 created_at: 1
29 }
30
31 describe('session store messages', () => {
32 beforeEach(() => {
33 ipcMocks.getSession.mockReset()
34 ipcMocks.getSessionMessages.mockReset()
35 useSessionStore.setState({
36 currentSession: null,
37 currentMessages: [],
38 currentGeneratedPages: [],
39 loading: false,
40 error: null
41 })
42 })
43
44 it('preserves the active conversation when session data is refreshed after cancellation', async () => {
45 useSessionStore.getState().addMessage(message)
46 ipcMocks.getSession.mockResolvedValue({
47 session: {
48 id: 'session-1',
49 title: 'Session',
50 topic: null,
51 styleId: null,
52 page_count: 1,
53 status: 'completed',
54 provider: 'test',
55 model: 'test',
56 created_at: 1,
57 updated_at: 1,
58 metadata: null
59 },
60 generatedPages: []
61 })
62
63 await useSessionStore.getState().loadSession('session-1')
64
65 expect(useSessionStore.getState().currentMessages).toEqual([message])
66 })
67
68 it('keeps process and tool records out of the visible chat conversation', async () => {
69 ipcMocks.getSessionMessages.mockResolvedValue([
70 message,
71 { ...message, id: 'assistant-1', role: 'assistant', content: 'AI 最终回复' },
72 { ...message, id: 'system-1', role: 'system', content: '正在准备画布' },
73 { ...message, id: 'tool-1', role: 'tool', content: '已更新 page-1' }
74 ])
75
76 await useSessionStore.getState().loadMessages({
77 sessionId: 'session-1',
78 chatType: 'page',
79 pageId: 'page-1'
80 })
81
82 expect(useSessionStore.getState().currentMessages.map((item) => item.role)).toEqual([
83 'user',
84 'assistant'
85 ])
86 })
87
88 it('ignores a stale session response without clearing the active request loading state', async () => {
89 let resolveOld: ((value: unknown) => void) | undefined
90 let resolveNew: ((value: unknown) => void) | undefined
91 const oldRequest = new Promise((resolve) => {
92 resolveOld = resolve
93 })
94 const newRequest = new Promise((resolve) => {
95 resolveNew = resolve
96 })
97 ipcMocks.getSession.mockImplementation((sessionId: string) =>
98 sessionId === 'session-old' ? oldRequest : newRequest
99 )
100 let activeSessionId = 'session-old'
101 const oldLoad = useSessionStore
102 .getState()
103 .loadSession('session-old', () => activeSessionId === 'session-old')
104
105 activeSessionId = 'session-new'
106 const newLoad = useSessionStore
107 .getState()
108 .loadSession('session-new', () => activeSessionId === 'session-new')
109 resolveNew?.({
110 session: { id: 'session-new' },
111 generatedPages: [{ id: 'page-new' }]
112 })
113 await newLoad
114
115 resolveOld?.({
116 session: { id: 'session-old' },
117 generatedPages: [{ id: 'page-old' }]
118 })
119 await oldLoad
120
121 expect(useSessionStore.getState().currentSession?.id).toBe('session-new')
122 expect(useSessionStore.getState().currentGeneratedPages).toEqual([{ id: 'page-new' }])
123 expect(useSessionStore.getState().loading).toBe(false)
124 })
125 })
126
126 lines TYPESCRIPT