返回 oh-my-ppt
page-management-service.test.ts
根目录 / tests / unit / session / page-management-service.test.ts
1 import { afterEach, describe, expect, it, vi } from 'vitest'
2 import fs from 'fs'
3 import os from 'os'
4 import path from 'path'
5 import type { IpcContext } from '../../../src/main/ipc/context'
6 import { persistManagedPages, type ManagedPage } from '../../../src/main/session/page-management-service'
7
8 const mocks = vi.hoisted(() => ({
9 ensureSessionRuntimeCompatible: vi.fn(),
10 buildProjectIndexHtml: vi.fn(() => '<html><body>new index</body></html>'),
11 carryIndexTransitionConfig: vi.fn((_previous: string, next: string) => next)
12 }))
13
14 vi.mock('../../../src/main/session/runtime-assets', () => ({
15 ensureSessionRuntimeCompatible: mocks.ensureSessionRuntimeCompatible
16 }))
17
18 vi.mock('../../../src/main/session/template-builder', () => ({
19 buildProjectIndexHtml: mocks.buildProjectIndexHtml
20 }))
21
22 vi.mock('../../../src/main/session/index-transition', () => ({
23 carryIndexTransitionConfig: mocks.carryIndexTransitionConfig
24 }))
25
26 const createdDirectories: string[] = []
27
28 const createProjectDirectory = async (): Promise<string> => {
29 const projectDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'ohmyppt-page-management-'))
30 createdDirectories.push(projectDir)
31 return projectDir
32 }
33
34 afterEach(async () => {
35 await Promise.all(createdDirectories.splice(0).map((directory) => fs.promises.rm(directory, { recursive: true, force: true })))
36 vi.clearAllMocks()
37 })
38
39 describe('persistManagedPages', () => {
40 it('restores page HTML when page-order persistence fails', async () => {
41 const projectDir = await createProjectDirectory()
42 const firstPath = path.join(projectDir, 'page-first.html')
43 const secondPath = path.join(projectDir, 'page-second.html')
44 const firstHtml = '<html><head></head><body><main class="ppt-page-root" data-ppt-guard-root="1"></main></body></html>'
45 const secondHtml = '<html><head></head><body><main class="ppt-page-root" data-ppt-guard-root="1"></main></body></html>'
46 await Promise.all([
47 fs.promises.writeFile(firstPath, firstHtml, 'utf-8'),
48 fs.promises.writeFile(secondPath, secondHtml, 'utf-8')
49 ])
50 const context = {
51 db: {
52 getSession: vi.fn().mockResolvedValue({
53 slideSizeId: 'wide-16-9',
54 slideWidth: 1600,
55 slideHeight: 900,
56 metadata: '{}'
57 }),
58 persistSessionPageState: vi.fn().mockRejectedValue(new Error('database unavailable'))
59 }
60 } as unknown as IpcContext
61 const pages: ManagedPage[] = [
62 { id: 'second', pageId: 'page-second', pageNumber: 2, title: 'Second', htmlPath: secondPath },
63 { id: 'first', pageId: 'page-first', pageNumber: 1, title: 'First', htmlPath: firstPath }
64 ]
65
66 await expect(
67 persistManagedPages(context, {
68 sessionId: 'session-1',
69 projectDir,
70 indexPath: path.join(projectDir, 'index.html'),
71 deckTitle: 'Deck',
72 pages,
73 operation: 'reorder',
74 prompt: 'reorder'
75 })
76 ).rejects.toThrow('database unavailable')
77
78 await expect(fs.promises.readFile(firstPath, 'utf-8')).resolves.toBe(firstHtml)
79 await expect(fs.promises.readFile(secondPath, 'utf-8')).resolves.toBe(secondHtml)
80 await expect(fs.promises.access(path.join(projectDir, 'index.html.tmp'))).rejects.toThrow()
81 })
82 })
83
83 lines TYPESCRIPT