返回 oh-my-ppt
style-preview-generator.test.ts
根目录 / tests / unit / styles / style-preview-generator.test.ts
1 import { mkdtemp, readFile, writeFile } from 'fs/promises'
2 import os from 'os'
3 import path from 'path'
4 import { beforeEach, describe, expect, it, vi } from 'vitest'
5 import { writeStylePackage } from '../../../src/main/styles/style-package'
6
7 vi.mock('../../../src/main/agent-runtime/model', () => ({
8 resolveModel: vi.fn()
9 }))
10
11 vi.mock('deepagents', () => ({
12 FilesystemBackend: class FilesystemBackend {},
13 createDeepAgent: vi.fn()
14 }))
15
16 const modelArgs = {
17 provider: 'openai',
18 apiKey: 'test-key',
19 model: 'test-model',
20 baseUrl: '',
21 maxTokens: 4096,
22 modelTimeoutMs: 600000
23 }
24
25 async function makeStylePackage(): Promise<string> {
26 const root = await mkdtemp(path.join(os.tmpdir(), 'ohmyppt-style-preview-test-'))
27 const dir = path.join(root, 'paper-story')
28 await writeStylePackage({
29 dir,
30 json: {
31 style: 'paper-story',
32 name: { zh: '纸上故事', en: 'Paper Story' },
33 description: '温暖、有手作感的叙事风格',
34 category: '叙事',
35 aliases: [],
36 styleCase: '品牌故事',
37 version: '1.0.0',
38 source: 'custom'
39 },
40 skillMarkdown: '# Paper Story\nUse warm paper textures and expressive editorial type.\n'
41 })
42 return dir
43 }
44
45 describe('generateStylePreview', () => {
46 beforeEach(() => {
47 vi.resetModules()
48 })
49
50 it('generates in a temporary package and saves a validated preview.html', async () => {
51 const stylePackageDir = await makeStylePackage()
52 const { generateStylePreviewHtml } = await import('../../../src/main/styles/preview/generator')
53 const runAgent = vi.fn(async ({ workspaceDir, prompt }) => {
54 expect(prompt).toContain('original, presentation-ready copy')
55 expect(prompt).toContain('copy language consistent')
56 expect(await readFile(path.join(workspaceDir, 'SKILL.md'), 'utf8')).toContain('Paper Story')
57 await writeFile(
58 path.join(workspaceDir, 'preview.html'),
59 '<!doctype html><html><head><style>html,body{width:1600px;height:900px}</style></head><body>把灵感写在纸上</body></html>',
60 'utf8'
61 )
62 })
63
64 const result = await generateStylePreviewHtml(
65 { ...modelArgs, styleId: 'paper-story', stylePackageDir },
66 { runAgent }
67 )
68
69 expect(result).toContain('把灵感写在纸上')
70 await expect(readFile(path.join(stylePackageDir, 'preview.html'), 'utf8')).rejects.toThrow()
71 expect(runAgent).toHaveBeenCalledOnce()
72 })
73
74 it('does not leave an invalid generated preview in the style package', async () => {
75 const stylePackageDir = await makeStylePackage()
76 const { generateStylePreviewHtml } = await import('../../../src/main/styles/preview/generator')
77
78 await expect(
79 generateStylePreviewHtml(
80 { ...modelArgs, styleId: 'paper-story', stylePackageDir },
81 {
82 runAgent: async ({ workspaceDir }) => {
83 await writeFile(
84 path.join(workspaceDir, 'preview.html'),
85 '<div>incomplete</div>',
86 'utf8'
87 )
88 }
89 }
90 )
91 ).rejects.toThrow(/complete HTML/)
92
93 await expect(readFile(path.join(stylePackageDir, 'preview.html'), 'utf8')).rejects.toThrow()
94 })
95
96 it('does not regenerate a style that already has preview.html', async () => {
97 const stylePackageDir = await makeStylePackage()
98 await writeFile(
99 path.join(stylePackageDir, 'preview.html'),
100 '<!doctype html><html><body>existing preview</body></html>',
101 'utf8'
102 )
103 const { generateStylePreviewHtml } = await import(
104 '../../../src/main/styles/preview/generator'
105 )
106 const runAgent = vi.fn()
107
108 await expect(
109 generateStylePreviewHtml(
110 { ...modelArgs, styleId: 'paper-story', stylePackageDir },
111 { runAgent }
112 )
113 ).rejects.toThrow('该风格已有预览,无需重复生成。')
114 expect(runAgent).not.toHaveBeenCalled()
115 })
116 })
117
117 lines TYPESCRIPT