返回 oh-my-ppt
edit-html-list-import.test.ts
根目录 / tests / unit / html-editor / edit-html-list-import.test.ts
1 /**
2 * @vitest-environment happy-dom
3 */
4 import React, { act } from 'react'
5 import { createRoot, type Root } from 'react-dom/client'
6 import { MemoryRouter, useLocation } from 'react-router-dom'
7 import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
8
9 const state = vi.hoisted(() => ({
10 importHtmlFile: vi.fn(),
11 listHtmlDocuments: vi.fn(),
12 documents: [] as Array<{
13 id: string
14 title: string
15 sourcePath: string | null
16 htmlPath: string
17 designWidth: number
18 updatedAt: number
19 thumbnailPath: string | null
20 }>
21 }))
22
23 vi.mock('../../../src/renderer/src/lib/ipc', () => ({
24 ipc: {
25 importHtmlFile: state.importHtmlFile,
26 listHtmlDocuments: state.listHtmlDocuments,
27 onHtmlThumbnailChanged: vi.fn(() => () => {})
28 }
29 }))
30 vi.mock('../../../src/renderer/src/i18n', () => ({
31 useT: () => (key: string) => key
32 }))
33
34 import { EditHtmlListPage } from '../../../src/renderer/src/pages/edit-html-list'
35 import { useHtmlEditorStore } from '../../../src/renderer/src/store/htmlEditorStore'
36
37 function LocationProbe(): React.JSX.Element {
38 const location = useLocation()
39 return React.createElement('output', { 'data-current-path': location.pathname })
40 }
41
42 async function renderPage(): Promise<{ container: HTMLDivElement; root: Root }> {
43 const container = document.createElement('div')
44 document.body.appendChild(container)
45 const root = createRoot(container)
46 await act(async () => {
47 root.render(
48 React.createElement(
49 MemoryRouter,
50 { initialEntries: ['/edit-html'] },
51 React.createElement(
52 React.Fragment,
53 null,
54 React.createElement(LocationProbe),
55 React.createElement(EditHtmlListPage)
56 )
57 )
58 )
59 })
60 return { container, root }
61 }
62
63 describe('EditHtmlListPage import', () => {
64 beforeEach(() => {
65 state.documents = []
66 state.importHtmlFile.mockReset()
67 state.listHtmlDocuments.mockReset()
68 state.listHtmlDocuments.mockImplementation(async () => ({ documents: state.documents }))
69 useHtmlEditorStore.setState({
70 docId: null,
71 title: '',
72 htmlPath: null,
73 sourcePath: null,
74 designWidth: 1280,
75 html: '',
76 importing: false,
77 exporting: false,
78 error: null,
79 documents: []
80 })
81 })
82
83 afterEach(async () => {
84 document.body.innerHTML = ''
85 useHtmlEditorStore.getState().reset()
86 })
87
88 it('keeps the user on the document list after importing and refreshes the new card', async () => {
89 const imported = {
90 docId: 'hedit-1',
91 title: 'Imported page',
92 htmlPath: '/tmp/html-editor/hedit-1/current.html',
93 sourcePath: '/tmp/source.html',
94 designWidth: 1280,
95 html: '<html></html>'
96 }
97 state.importHtmlFile.mockImplementation(async () => {
98 state.documents = [
99 {
100 id: imported.docId,
101 title: imported.title,
102 sourcePath: imported.sourcePath,
103 htmlPath: imported.htmlPath,
104 designWidth: imported.designWidth,
105 updatedAt: Date.now(),
106 thumbnailPath: null
107 }
108 ]
109 return { cancelled: false, ...imported }
110 })
111
112 const { container, root } = await renderPage()
113 try {
114 await act(async () => {
115 await Promise.resolve()
116 })
117 const importButton = [...container.querySelectorAll('button')].find((button) =>
118 button.textContent?.includes('htmlEditor.import')
119 )
120 expect(importButton).toBeTruthy()
121
122 await act(async () => {
123 importButton?.click()
124 })
125
126 expect(state.importHtmlFile).toHaveBeenCalledOnce()
127 expect(state.listHtmlDocuments).toHaveBeenCalledTimes(2)
128 expect(container.textContent).toContain('Imported page')
129 expect(
130 container.querySelector('[data-current-path]')?.getAttribute('data-current-path')
131 ).toBe('/edit-html')
132 } finally {
133 await act(async () => {
134 root.unmount()
135 })
136 container.remove()
137 }
138 })
139 })
140
140 lines TYPESCRIPT