返回 oh-my-ppt
template-card-rendering.test.ts
根目录 / tests / unit / templates / template-card-rendering.test.ts
1 /**
2 * @vitest-environment happy-dom
3 */
4 import React, { act } from 'react'
5 import { afterEach, describe, expect, it, vi } from 'vitest'
6 import { createRoot } from 'react-dom/client'
7 import { TemplateCard } from '../../../src/renderer/src/components/templates/TemplateCard'
8 import type { TemplateListItem } from '../../../src/renderer/src/lib/ipc'
9
10 vi.mock('@renderer/i18n', () => ({ useT: () => (key: string) => key }))
11
12 const createTemplate = (thumbnailPath: string | null): TemplateListItem => ({
13 id: 'template-1',
14 name: 'Quarterly Review',
15 description: 'Template description',
16 source: 'user',
17 pageCount: 3,
18 tags: [],
19 previewHtmlPath: '/templates/template-1/page-1.html',
20 thumbnailPath,
21 previewPages: [
22 {
23 pageNumber: 1,
24 pageId: 'page-1',
25 title: 'Cover',
26 htmlPath: '/templates/template-1/page-1.html'
27 }
28 ],
29 createdAt: 1,
30 updatedAt: 2
31 })
32
33 describe('TemplateCard rendering', () => {
34 afterEach(() => {
35 vi.restoreAllMocks()
36 document.body.innerHTML = ''
37 })
38
39 it('renders a cached PNG cover without mounting an iframe', async () => {
40 const container = document.createElement('div')
41 document.body.appendChild(container)
42 const root = createRoot(container)
43 await act(async () => {
44 root.render(
45 React.createElement(TemplateCard, {
46 template: createTemplate('/cache/template-1.png'),
47 onUseDirect: vi.fn(),
48 onUseGenerate: vi.fn(),
49 onEdit: vi.fn(),
50 onDelete: vi.fn(),
51 onPreview: vi.fn()
52 })
53 )
54 })
55
56 expect(container.querySelectorAll('img')).toHaveLength(1)
57 expect(container.querySelector('img')?.getAttribute('src')).toBe(
58 'local-asset://%2Fcache%2Ftemplate-1.png'
59 )
60 expect(container.querySelectorAll('iframe')).toHaveLength(0)
61 expect(container.textContent).not.toMatch(/\d{2}:\d{2}/)
62 await act(async () => root.unmount())
63 })
64
65 it('encodes a Windows thumbnail path for the local asset protocol', async () => {
66 const container = document.createElement('div')
67 document.body.appendChild(container)
68 const root = createRoot(container)
69 await act(async () => {
70 root.render(
71 React.createElement(TemplateCard, {
72 template: createTemplate('C:\\Users\\Chan\\AppData\\Roaming\\OhMyPPT\\cover.png'),
73 onUseDirect: vi.fn(),
74 onUseGenerate: vi.fn(),
75 onEdit: vi.fn(),
76 onDelete: vi.fn(),
77 onPreview: vi.fn()
78 })
79 )
80 })
81
82 expect(container.querySelector('img')?.getAttribute('src')).toBe(
83 'local-asset://C%3A%5CUsers%5CChan%5CAppData%5CRoaming%5COhMyPPT%5Ccover.png'
84 )
85 await act(async () => root.unmount())
86 })
87
88 it('shows a generating placeholder while the cover is queued', async () => {
89 const container = document.createElement('div')
90 document.body.appendChild(container)
91 const root = createRoot(container)
92 await act(async () => {
93 root.render(
94 React.createElement(TemplateCard, {
95 template: createTemplate(null),
96 onUseDirect: vi.fn(),
97 onUseGenerate: vi.fn(),
98 onEdit: vi.fn(),
99 onDelete: vi.fn(),
100 onPreview: vi.fn()
101 })
102 )
103 })
104
105 expect(container.textContent).toContain('templates.thumbnailGenerating')
106 expect(container.querySelectorAll('img')).toHaveLength(0)
107 expect(container.querySelectorAll('iframe')).toHaveLength(0)
108 await act(async () => root.unmount())
109 })
110 })
111
111 lines TYPESCRIPT