import { beforeEach, describe, expect, it, vi } from 'vitest'; import { ImageViewer } from './image-viewer'; import { IMAGE_VIEWER_ZOOM_EVENT } from './image-viewer.types'; const MARKUP = `
Test
`; function setup(opts = {}): { root: HTMLElement; ctrl: ImageViewer } { document.body.innerHTML = MARKUP; const root = document.body.firstElementChild as HTMLElement; return { root, ctrl: new ImageViewer(root, opts) }; } describe('ImageViewer', () => { beforeEach(() => { document.body.innerHTML = ''; }); it('throws without content element', () => { document.body.innerHTML = '
'; expect(() => new ImageViewer(document.body.firstElementChild as HTMLElement)).toThrow(/Missing/); }); it('starts at zoom 0 with 100% indicator', () => { const { root, ctrl } = setup(); expect(ctrl.currentZoom).toBe(0); expect(root.querySelector('[data-c42-viewer-indicator]')!.textContent).toBe('100%'); }); it('zooms in via button and emits event', () => { const { root, ctrl } = setup(); const spy = vi.fn(); root.addEventListener(IMAGE_VIEWER_ZOOM_EVENT, spy); root.querySelector('[data-c42-viewer-zoom-in]')!.click(); expect(ctrl.currentZoom).toBe(1); expect(spy).toHaveBeenCalledOnce(); expect((spy.mock.calls[0][0] as CustomEvent).detail.zoom).toBe(1); }); it('zooms out via button', () => { const { ctrl } = setup(); ctrl.zoomIn(); ctrl.zoomIn(); ctrl.zoomOut(); expect(ctrl.currentZoom).toBe(1); }); it('respects maxZoom', () => { const { ctrl } = setup({ maxZoom: 2 }); ctrl.zoomIn(); ctrl.zoomIn(); ctrl.zoomIn(); expect(ctrl.currentZoom).toBe(2); }); it('does not go below minZoom', () => { const { ctrl } = setup(); ctrl.zoomOut(); expect(ctrl.currentZoom).toBe(0); }); it('resets view', () => { const { root, ctrl } = setup(); ctrl.zoomIn(); ctrl.zoomIn(); ctrl.resetView(); expect(ctrl.currentZoom).toBe(0); expect(root.querySelector('[data-c42-viewer-indicator]')!.textContent).toBe('100%'); }); it('toggles expanded state', () => { const { root, ctrl } = setup(); expect(ctrl.isExpanded).toBe(false); expect(root.dataset.state).toBe('normal'); root.querySelector('[data-c42-viewer-expand]')!.click(); expect(ctrl.isExpanded).toBe(true); expect(root.dataset.state).toBe('expanded'); }); it('sets cursor to grab when zoomed', () => { const { root, ctrl } = setup(); const content = root.querySelector('[data-c42-viewer-content]')!; expect(content.style.cursor).toBe('default'); ctrl.zoomIn(); expect(content.style.cursor).toBe('grab'); }); it('destroy removes listeners', () => { const { root, ctrl } = setup(); ctrl.destroy(); root.querySelector('[data-c42-viewer-zoom-in]')!.click(); expect(ctrl.currentZoom).toBe(0); }); });