返回 oh-my-ppt
style-preview-handlers.test.ts
根目录 / tests / unit / ipc / style-preview-handlers.test.ts
1 import { beforeEach, describe, expect, it, vi } from 'vitest'
2
3 const state = vi.hoisted(() => {
4 const handlers = new Map<string, (...args: unknown[]) => Promise<unknown>>()
5 return {
6 handlers,
7 generateStylePreviewHtml: vi.fn(),
8 getStylePackageDirectory: vi.fn(),
9 saveGeneratedStylePreview: vi.fn(),
10 enqueueHtmlThumbnail: vi.fn(),
11 waitForHtmlThumbnailTask: vi.fn(),
12 resolveGlobalModelTimeouts: vi.fn(),
13 resolveModelConfigForTask: vi.fn(),
14 ipcMain: {
15 handle: vi.fn((channel: string, handler: (...args: unknown[]) => Promise<unknown>) => {
16 handlers.set(channel, handler)
17 })
18 }
19 }
20 })
21
22 vi.mock('electron', () => ({ ipcMain: state.ipcMain }))
23 vi.mock('electron-log/main.js', () => ({ default: { info: vi.fn() } }))
24 vi.mock('../../../src/main/styles/catalog', () => ({
25 getStylePackageDirectory: state.getStylePackageDirectory,
26 saveGeneratedStylePreview: state.saveGeneratedStylePreview
27 }))
28 vi.mock('../../../src/main/styles/preview/generator', () => ({
29 generateStylePreviewHtml: state.generateStylePreviewHtml
30 }))
31 vi.mock('../../../src/main/io/thumbnails/html-thumbnail-service', () => ({
32 enqueueHtmlThumbnail: state.enqueueHtmlThumbnail,
33 waitForHtmlThumbnailTask: state.waitForHtmlThumbnailTask
34 }))
35 vi.mock('../../../src/main/config/model-config-utils', () => ({
36 resolveGlobalModelTimeouts: state.resolveGlobalModelTimeouts,
37 resolveModelConfigForTask: state.resolveModelConfigForTask
38 }))
39
40 describe('registerStylePreviewHandlers', () => {
41 beforeEach(() => {
42 vi.resetModules()
43 state.handlers.clear()
44 state.ipcMain.handle.mockClear()
45 state.generateStylePreviewHtml.mockReset()
46 state.getStylePackageDirectory.mockReset()
47 state.saveGeneratedStylePreview.mockReset()
48 state.enqueueHtmlThumbnail.mockReset()
49 state.waitForHtmlThumbnailTask.mockReset()
50 state.resolveGlobalModelTimeouts.mockReset()
51 state.resolveModelConfigForTask.mockReset()
52 })
53
54 it('registers an independent IPC channel and generates the requested style preview', async () => {
55 state.getStylePackageDirectory.mockReturnValue('/styles/user/paper-story')
56 state.resolveModelConfigForTask.mockResolvedValue({
57 provider: 'openai',
58 apiKey: 'key',
59 model: 'model',
60 baseUrl: '',
61 maxTokens: 4096
62 })
63 state.resolveGlobalModelTimeouts.mockResolvedValue({ document: 600000 })
64 state.generateStylePreviewHtml.mockResolvedValue('<!doctype html><html></html>')
65 state.saveGeneratedStylePreview.mockResolvedValue({
66 previewPath: '/styles/user/paper-story/preview.html'
67 })
68 state.enqueueHtmlThumbnail.mockResolvedValue({
69 resourceType: 'style',
70 resourceId: 'paper-story',
71 variant: 'default',
72 status: 'queued',
73 thumbnailPath: null
74 })
75 state.waitForHtmlThumbnailTask.mockResolvedValue({
76 resourceType: 'style',
77 resourceId: 'paper-story',
78 variant: 'default',
79 status: 'completed',
80 thumbnailPath: '/thumbnail-cache/paper-story.png'
81 })
82
83 const { registerStylePreviewHandlers } =
84 await import('../../../src/main/styles/preview/handlers')
85 registerStylePreviewHandlers({ db: {}, decryptApiKey: vi.fn() } as never)
86
87 const handler = state.handlers.get('styles:generatePreview')
88 const result = await handler?.({}, { styleId: 'paper-story' })
89
90 expect(result).toEqual({
91 success: true,
92 previewPath: '/styles/user/paper-story/preview.html',
93 thumbnailPath: '/thumbnail-cache/paper-story.png'
94 })
95 expect(state.resolveModelConfigForTask).toHaveBeenCalledWith(
96 expect.anything(),
97 expect.objectContaining({ purpose: 'styles:generatePreview' })
98 )
99 expect(state.generateStylePreviewHtml).toHaveBeenCalledWith(
100 expect.objectContaining({
101 styleId: 'paper-story',
102 stylePackageDir: '/styles/user/paper-story',
103 modelTimeoutMs: 600000
104 })
105 )
106 expect(state.saveGeneratedStylePreview).toHaveBeenCalledWith(
107 'paper-story',
108 '<!doctype html><html></html>'
109 )
110 expect(state.enqueueHtmlThumbnail).toHaveBeenCalledWith(
111 {
112 resourceType: 'style',
113 resourceId: 'paper-story',
114 sourcePath: '/styles/user/paper-story/preview.html'
115 },
116 { force: true }
117 )
118 expect(state.waitForHtmlThumbnailTask).toHaveBeenCalledWith('style', 'paper-story')
119 })
120 })
121
121 lines TYPESCRIPT