// @vitest-environment jsdom import { fireEvent } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { handlePreviewZoomKeyDown, type PreviewZoomKeyboardActions, type PreviewZoomKeyboardContext, previewZoomUsesMetaModifier, } from '../src/view/ui-editor/components/preview/previewZoomKeyboard'; function createActions(): PreviewZoomKeyboardActions { return { resetToActualSize: vi.fn(), zoomIn: vi.fn(), zoomOut: vi.fn(), }; } function dispatchShortcut({ actions = createActions(), context = {}, event, target, }: { actions?: PreviewZoomKeyboardActions; context?: Partial; event: KeyboardEventInit; target?: HTMLElement; }) { const resolvedTarget = target ?? document.createElement('div'); document.body.append(resolvedTarget); const handler = vi.fn((keyboardEvent: KeyboardEvent) => handlePreviewZoomKeyDown( keyboardEvent, { hasZoomableViewport: true, isFocused: false, isHovered: true, usesMetaModifier: false, ...context, }, actions, ), ); resolvedTarget.addEventListener('keydown', handler); fireEvent.keyDown(resolvedTarget, event); const keyboardEvent = handler.mock.calls[0]?.[0]; return { actions, handler, keyboardEvent }; } afterEach(() => { document.body.replaceChildren(); }); describe('preview zoom keyboard shortcuts', () => { it.each([ { key: '+', code: 'Equal' }, { key: '=', code: 'Equal' }, { key: '+', code: 'NumpadAdd' }, ])('zooms in for the supported main and numpad keys (%o)', (event) => { const { actions, keyboardEvent } = dispatchShortcut({ event: { ...event, ctrlKey: true, cancelable: true, repeat: true }, }); expect(actions.zoomIn).toHaveBeenCalledTimes(1); expect(keyboardEvent?.defaultPrevented).toBe(true); }); it.each([ { key: '-', code: 'Minus' }, { key: '-', code: 'NumpadSubtract' }, ])('zooms out for the supported main and numpad keys (%o)', (event) => { const { actions, keyboardEvent } = dispatchShortcut({ event: { ...event, ctrlKey: true, cancelable: true }, }); expect(actions.zoomOut).toHaveBeenCalledTimes(1); expect(keyboardEvent?.defaultPrevented).toBe(true); }); it('does not treat underscore as zoom out', () => { const { actions, keyboardEvent } = dispatchShortcut({ event: { key: '_', code: 'Minus', ctrlKey: true, shiftKey: true, cancelable: true, }, }); expect(actions.zoomOut).not.toHaveBeenCalled(); expect(keyboardEvent?.defaultPrevented).toBe(false); }); it('keeps the existing actual-size shortcut', () => { const { actions } = dispatchShortcut({ event: { key: '1', ctrlKey: true, cancelable: true }, }); expect(actions.resetToActualSize).toHaveBeenCalledTimes(1); }); it('uses Cmd on Apple platforms and Ctrl elsewhere', () => { expect(previewZoomUsesMetaModifier('MacIntel')).toBe(true); expect(previewZoomUsesMetaModifier('iPad')).toBe(true); expect(previewZoomUsesMetaModifier('Win32')).toBe(false); const appleActions = createActions(); dispatchShortcut({ actions: appleActions, context: { usesMetaModifier: true }, event: { key: '=', ctrlKey: true, cancelable: true }, }); expect(appleActions.zoomIn).not.toHaveBeenCalled(); dispatchShortcut({ actions: appleActions, context: { usesMetaModifier: true }, event: { key: '=', metaKey: true, cancelable: true }, }); expect(appleActions.zoomIn).toHaveBeenCalledTimes(1); }); it.each([ { isHovered: false, isFocused: false, hasZoomableViewport: true }, { isHovered: true, isFocused: false, hasZoomableViewport: false }, ])('leaves inactive preview shortcuts to the host (%o)', (context) => { const { actions, keyboardEvent } = dispatchShortcut({ context, event: { key: '=', ctrlKey: true, cancelable: true }, }); expect(actions.zoomIn).not.toHaveBeenCalled(); expect(keyboardEvent?.defaultPrevented).toBe(false); }); it('works while the preview is focused without being hovered', () => { const { actions } = dispatchShortcut({ context: { isFocused: true, isHovered: false }, event: { key: '=', ctrlKey: true, cancelable: true }, }); expect(actions.zoomIn).toHaveBeenCalledTimes(1); }); it.each(['input', 'button', 'a'])('ignores interactive %s targets', (tag) => { const target = document.createElement(tag); if (target instanceof HTMLAnchorElement) target.href = '#preview'; const { actions, keyboardEvent } = dispatchShortcut({ target, event: { key: '=', ctrlKey: true, cancelable: true }, }); expect(actions.zoomIn).not.toHaveBeenCalled(); expect(keyboardEvent?.defaultPrevented).toBe(false); }); it('does not override an event already handled by another control', () => { const target = document.createElement('div'); target.addEventListener('keydown', (event) => event.preventDefault(), { once: true, }); const { actions } = dispatchShortcut({ target, event: { key: '=', ctrlKey: true, cancelable: true }, }); expect(actions.zoomIn).not.toHaveBeenCalled(); }); });