| 1 | /** |
| 2 | * @vitest-environment happy-dom |
| 3 | */ |
| 4 | import React, { act } from 'react' |
| 5 | import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' |
| 6 | import { createRoot, type Root } from 'react-dom/client' |
| 7 | |
| 8 | const state = vi.hoisted(() => ({ |
| 9 | revealHtmlFile: vi.fn(async () => ({ ok: true })), |
| 10 | saveHtmlEdits: vi.fn(async () => ({ saved: false })), |
| 11 | navigate: vi.fn() |
| 12 | })) |
| 13 | |
| 14 | vi.mock('../../../src/renderer/src/lib/ipc', () => ({ |
| 15 | ipc: { |
| 16 | revealHtmlFile: state.revealHtmlFile, |
| 17 | openHtmlInBrowser: vi.fn(async () => ({ ok: true })) |
| 18 | } |
| 19 | })) |
| 20 | |
| 21 | vi.mock('react-router-dom', () => ({ |
| 22 | useNavigate: () => state.navigate |
| 23 | })) |
| 24 | |
| 25 | vi.mock('../../../src/renderer/src/i18n', () => ({ |
| 26 | useT: () => (key: string) => key |
| 27 | })) |
| 28 | |
| 29 | import { TooltipProvider } from '../../../src/renderer/src/components/ui/Tooltip' |
| 30 | import { HtmlEditorToolbar } from '../../../src/renderer/src/components/html-editor/HtmlEditorToolbar' |
| 31 | import { useHtmlEditorStore } from '../../../src/renderer/src/store/htmlEditorStore' |
| 32 | import { useHtmlEditStore } from '../../../src/renderer/src/store/htmlEditStore' |
| 33 | |
| 34 | const originalSaveHtmlEdits = useHtmlEditStore.getState().save |
| 35 | |
| 36 | async function renderToolbar(): Promise<{ container: HTMLDivElement; root: Root }> { |
| 37 | const container = document.createElement('div') |
| 38 | document.body.appendChild(container) |
| 39 | const root = createRoot(container) |
| 40 | await act(async () => { |
| 41 | root.render( |
| 42 | React.createElement( |
| 43 | TooltipProvider, |
| 44 | { delayDuration: 0 }, |
| 45 | React.createElement(HtmlEditorToolbar, { onOpenHistory: vi.fn() }) |
| 46 | ) |
| 47 | ) |
| 48 | }) |
| 49 | return { container, root } |
| 50 | } |
| 51 | |
| 52 | describe('HtmlEditorToolbar', () => { |
| 53 | beforeEach(() => { |
| 54 | state.revealHtmlFile.mockClear() |
| 55 | state.saveHtmlEdits.mockClear() |
| 56 | state.navigate.mockClear() |
| 57 | useHtmlEditStore.getState().reset() |
| 58 | useHtmlEditStore.setState({ save: state.saveHtmlEdits }) |
| 59 | useHtmlEditorStore.setState({ |
| 60 | docId: 'hedit-1', |
| 61 | title: 'Landing page', |
| 62 | sourcePath: '/tmp/landing.html', |
| 63 | exporting: false |
| 64 | }) |
| 65 | }) |
| 66 | |
| 67 | afterEach(async () => { |
| 68 | document.body.innerHTML = '' |
| 69 | useHtmlEditStore.getState().reset() |
| 70 | useHtmlEditStore.setState({ save: originalSaveHtmlEdits }) |
| 71 | useHtmlEditorStore.getState().reset() |
| 72 | }) |
| 73 | |
| 74 | it('reveals the current HTML working file from the toolbar', async () => { |
| 75 | const { container, root } = await renderToolbar() |
| 76 | try { |
| 77 | const revealButton = container.querySelector<HTMLButtonElement>( |
| 78 | '[aria-label="htmlEditor.revealFile"]' |
| 79 | ) |
| 80 | expect(revealButton).toBeTruthy() |
| 81 | |
| 82 | await act(async () => { |
| 83 | revealButton?.click() |
| 84 | }) |
| 85 | |
| 86 | expect(state.revealHtmlFile).toHaveBeenCalledWith({ docId: 'hedit-1' }) |
| 87 | expect(state.saveHtmlEdits).not.toHaveBeenCalled() |
| 88 | } finally { |
| 89 | await act(async () => { |
| 90 | root.unmount() |
| 91 | }) |
| 92 | container.remove() |
| 93 | } |
| 94 | }) |
| 95 | }) |
| 96 |