返回 oh-my-ppt
session-toolbar-titlebar-drag.test.ts
根目录 / tests / unit / session / session-toolbar-titlebar-drag.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, type Root } from 'react-dom/client'
7 import { TooltipProvider } from '../../../src/renderer/src/components/ui/Tooltip'
8 import { SessionToolbar } from '../../../src/renderer/src/components/session-detail/toolbar/SessionToolbar'
9 import { useSessionDetailRuntimeStore } from '../../../src/renderer/src/store'
10
11 vi.mock('../../../src/renderer/src/i18n', () => ({
12 useT: () => (key: string) => key
13 }))
14
15 vi.mock('../../../src/renderer/src/components/session-detail/toolbar/useSessionToolbarController', () => ({
16 useSessionToolbarController: () => ({
17 hasPages: true,
18 isGenerating: false,
19 historyDisabled: false,
20 selectedPageHasPendingEdits: false,
21 canPreview: true,
22 canRevealFile: true,
23 sessionTitle: 'Quarterly Plan',
24 saveTemplateOpen: false,
25 savingTemplate: false,
26 saveAsNewSessionOpen: false,
27 savingAsNewSession: false,
28 saveAsNewSessionDisabled: false,
29 defaultTemplateName: 'Quarterly Plan',
30 defaultSaveAsNewSessionName: 'Quarterly Plan copy',
31 setSaveTemplateOpen: vi.fn(),
32 setSaveAsNewSessionOpen: vi.fn(),
33 handleSaveTemplate: vi.fn(),
34 handleSaveAsNewSession: vi.fn(),
35 exportActions: {
36 canExportPptx: true,
37 exportPptx: vi.fn(),
38 exportPng: vi.fn(),
39 exportVideo: vi.fn(),
40 exportPdf: vi.fn(),
41 exportSlidePack: vi.fn(),
42 exportSessionZip: vi.fn(),
43 openProjectPreview: vi.fn(),
44 openPresentation: vi.fn(),
45 revealSelectedPageFile: vi.fn()
46 },
47 openHistory: vi.fn()
48 })
49 }))
50
51 async function renderToolbar(): Promise<{ container: HTMLDivElement; root: Root }> {
52 const container = document.createElement('div')
53 document.body.appendChild(container)
54 const root = createRoot(container)
55
56 await act(async () => {
57 root.render(
58 React.createElement(
59 TooltipProvider,
60 { delayDuration: 0 },
61 React.createElement(
62 'header',
63 { className: 'app-drag-region app-titlebar' },
64 React.createElement(
65 'div',
66 { className: 'flex-1' },
67 React.createElement(SessionToolbar, { sessionId: 'session-1' })
68 )
69 )
70 )
71 )
72 })
73
74 return { container, root }
75 }
76
77 async function cleanupRoot(root: Root, container: HTMLDivElement): Promise<void> {
78 await act(async () => {
79 root.unmount()
80 })
81 container.remove()
82 }
83
84 describe('SessionToolbar titlebar drag region', () => {
85 afterEach(() => {
86 useSessionDetailRuntimeStore.getState().setWorkspaceRibbonActions(null)
87 document.body.innerHTML = ''
88 })
89
90 it('keeps title and empty toolbar space draggable while controls opt out', async () => {
91 useSessionDetailRuntimeStore.getState().setWorkspaceRibbonActions({
92 onUndo: vi.fn(),
93 onRedo: vi.fn(),
94 onSaveCurrentPage: vi.fn(),
95 onDiscardAllEdits: vi.fn(),
96 onBackToSessions: vi.fn(),
97 onAddFromLibrary: vi.fn(),
98 onAddFromLocal: vi.fn(),
99 onAddText: vi.fn(),
100 onAddArtText: vi.fn()
101 })
102 const { container, root } = await renderToolbar()
103
104 try {
105 const title = container.querySelector('.truncate')
106 expect(title?.textContent).toBe('Quarterly Plan')
107 expect(title?.closest('.app-no-drag')).toBeNull()
108
109 const toolbarHost = title?.closest('.flex-1')
110 expect(toolbarHost).toBeTruthy()
111 expect(toolbarHost?.classList.contains('app-no-drag')).toBe(false)
112
113 const buttons = container.querySelectorAll('button')
114 expect(buttons.length).toBeGreaterThan(0)
115 for (const button of buttons) {
116 expect(button.classList.contains('app-no-drag')).toBe(true)
117 }
118 } finally {
119 await cleanupRoot(root, container)
120 }
121 })
122 })
123
123 lines TYPESCRIPT