返回 oh-my-ppt
useSessionReorderPages.test.ts
根目录 / tests / unit / session / useSessionReorderPages.test.ts
1 /**
2 * @vitest-environment happy-dom
3 */
4 import React, { act } from 'react'
5 import { beforeEach, describe, expect, it, vi } from 'vitest'
6 import { createRoot, type Root } from 'react-dom/client'
7 import { useSessionReorderPages } from '../../../src/renderer/src/components/session-detail/hooks/useSessionReorderPages'
8 import { useGenerateStore } from '../../../src/renderer/src/store/generateStore'
9 import { useSessionDetailUiStore } from '../../../src/renderer/src/store/sessionDetailStore'
10
11 const ipcMocks = vi.hoisted(() => ({
12 reorderSessionPages: vi.fn(),
13 clearSpeechScript: vi.fn()
14 }))
15
16 vi.mock('@renderer/lib/ipc', () => ({
17 ipc: {
18 reorderSessionPages: ipcMocks.reorderSessionPages,
19 clearSpeechScript: ipcMocks.clearSpeechScript
20 }
21 }))
22
23 vi.mock('@renderer/i18n', () => ({
24 useT: () => (key: string) => key
25 }))
26
27 type ReorderHook = ReturnType<typeof useSessionReorderPages>
28
29 let latest: ReorderHook | null = null
30
31 function Harness({ sessionId }: { sessionId: string }): null {
32 latest = useSessionReorderPages(sessionId)
33 return null
34 }
35
36 async function renderHarness(sessionId = 'session-1'): Promise<{
37 root: Root
38 container: HTMLDivElement
39 }> {
40 const container = document.createElement('div')
41 document.body.appendChild(container)
42 const root = createRoot(container)
43 await act(async () => {
44 root.render(React.createElement(Harness, { sessionId }))
45 })
46 return { root, container }
47 }
48
49 async function unmount(root: Root, container: HTMLDivElement): Promise<void> {
50 await act(async () => {
51 root.unmount()
52 })
53 container.remove()
54 }
55
56 describe('useSessionReorderPages', () => {
57 beforeEach(() => {
58 latest = null
59 ipcMocks.reorderSessionPages.mockReset()
60 ipcMocks.clearSpeechScript.mockReset()
61 ipcMocks.clearSpeechScript.mockResolvedValue(undefined)
62 useGenerateStore.getState().reset()
63 useSessionDetailUiStore.getState().resetForSessionChange()
64 })
65
66 it('commits a reordered page list and keeps the selected page', async () => {
67 ipcMocks.reorderSessionPages.mockResolvedValue({
68 ok: true,
69 generatedPages: [
70 {
71 id: 'page-b',
72 pageId: 'page-b',
73 pageNumber: 1,
74 title: 'Page B',
75 html: '',
76 htmlPath: '/page-b.html'
77 },
78 {
79 id: 'page-a',
80 pageId: 'page-a',
81 pageNumber: 2,
82 title: 'Page A',
83 html: '',
84 htmlPath: '/page-a.html'
85 }
86 ],
87 selectedPageId: 'page-b'
88 })
89
90 const { root, container } = await renderHarness()
91 try {
92 let ok = false
93 await act(async () => {
94 ok = (await latest?.reorder(['page-b', 'page-a'], 'page-b')) ?? false
95 })
96
97 expect(ok).toBe(true)
98 expect(ipcMocks.reorderSessionPages).toHaveBeenCalledWith({
99 sessionId: 'session-1',
100 orderedPageIds: ['page-b', 'page-a'],
101 selectedPageId: 'page-b'
102 })
103 expect(useGenerateStore.getState().currentPages.map((page) => page.id)).toEqual([
104 'page-b',
105 'page-a'
106 ])
107 expect(useSessionDetailUiStore.getState().selectedPageId).toBe('page-b')
108 expect(useSessionDetailUiStore.getState().previewKey).toBe(0)
109 expect(ipcMocks.clearSpeechScript).toHaveBeenCalledWith('session-1')
110 } finally {
111 await unmount(root, container)
112 }
113 })
114 })
115
115 lines TYPESCRIPT