import { act, renderHook, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { useMenuEvents, type MenuEventHandlers } from './useMenuEvents' const isTauriMock = vi.fn(() => false) const listenMock = vi.fn() const invokeMock = vi.fn().mockResolvedValue(undefined) vi.mock('../mock-tauri', () => ({ isTauri: () => isTauriMock(), })) vi.mock('@tauri-apps/api/event', () => ({ listen: (...args: unknown[]) => listenMock(...args), })) vi.mock('@tauri-apps/api/core', () => ({ invoke: (...args: unknown[]) => invokeMock(...args), })) function makeHandlers(): MenuEventHandlers { return { activeTabPath: '/vault/a.md', activeTabPathRef: { current: '/vault/a.md' }, hasNoRemote: false, hasRestorableDeletedNote: false, multiSelectionCommandRef: { current: null }, onArchiveNote: vi.fn(), onCommandPalette: vi.fn(), onCreateNote: vi.fn(), onDeleteNote: vi.fn(), onFindInNote: vi.fn(), onOpenSettings: vi.fn(), onPastePlainText: vi.fn(), onQuickOpen: vi.fn(), onReplaceInNote: vi.fn(), onSave: vi.fn(), onSearch: vi.fn(), onSetViewMode: vi.fn(), onToggleInspector: vi.fn(), onZoomIn: vi.fn(), onZoomOut: vi.fn(), onZoomReset: vi.fn(), } } describe('useMenuEvents editor find state', () => { beforeEach(() => { vi.clearAllMocks() isTauriMock.mockReturnValue(true) listenMock.mockResolvedValue(vi.fn()) }) it('syncs editor find availability into the native menu state', async () => { renderHook(() => useMenuEvents(makeHandlers())) await vi.dynamicImportSettled() expect(invokeMock).toHaveBeenCalledWith('update_menu_state', expect.objectContaining({ state: expect.objectContaining({ editorFindEnabled: false }), })) act(() => { window.dispatchEvent(new CustomEvent('laputa:editor-find-availability', { detail: { enabled: true }, })) }) await waitFor(() => { expect(invokeMock).toHaveBeenLastCalledWith('update_menu_state', expect.objectContaining({ state: expect.objectContaining({ editorFindEnabled: true }), })) }) }) it('does not resync native menu state for equivalent rerenders', async () => { const { rerender } = renderHook( ({ handlers }: { handlers: MenuEventHandlers }) => useMenuEvents(handlers), { initialProps: { handlers: makeHandlers() } }, ) await vi.dynamicImportSettled() expect(invokeMock).toHaveBeenCalledTimes(1) invokeMock.mockClear() rerender({ handlers: makeHandlers() }) rerender({ handlers: makeHandlers() }) await vi.dynamicImportSettled() expect(invokeMock).not.toHaveBeenCalled() }) })