UNPKG

wavesurfer.js

Version:
200 lines (199 loc) 8.66 kB
import { createDragStream } from '../drag-stream'; describe('createDragStream', () => { beforeAll(() => { // Mock matchMedia Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockReturnValue({ matches: false, addListener: jest.fn(), removeListener: jest.fn(), }), }); // Polyfill PointerEvent for jsdom if (typeof window.PointerEvent === 'undefined') { class FakePointerEvent extends MouseEvent { constructor(type, props) { super(type, props); } } // @ts-expect-error - Polyfill PointerEvent for jsdom test environment window.PointerEvent = FakePointerEvent; // @ts-expect-error - Polyfill PointerEvent for jsdom test environment global.PointerEvent = FakePointerEvent; } }); let element; let events; beforeEach(() => { element = document.createElement('div'); document.body.appendChild(element); element.getBoundingClientRect = jest.fn(() => ({ left: 0, top: 0, right: 100, bottom: 100, width: 100, height: 100, x: 0, y: 0, toJSON: () => ({}), })); events = []; }); afterEach(() => { document.body.removeChild(element); }); it('should create a drag signal', () => { const { signal, cleanup } = createDragStream(element); expect(signal).toBeDefined(); expect(signal.value).toBeNull(); cleanup(); }); it('should emit start event on drag', () => { var _a; const { signal, cleanup } = createDragStream(element, { threshold: 0 }); signal.subscribe((event) => { if (event) events.push(event); }); // Simulate drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerMove); expect(events.length).toBeGreaterThan(0); expect((_a = events[0]) === null || _a === void 0 ? void 0 : _a.type).toBe('start'); cleanup(); }); it('should emit move events with deltas', () => { const { signal, cleanup } = createDragStream(element, { threshold: 0 }); signal.subscribe((event) => { if (event) events.push(event); }); // Simulate drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 30 }); document.dispatchEvent(pointerMove); const moveEvent = events.find((e) => e.type === 'move'); expect(moveEvent).toBeDefined(); expect(moveEvent === null || moveEvent === void 0 ? void 0 : moveEvent.deltaX).toBe(10); expect(moveEvent === null || moveEvent === void 0 ? void 0 : moveEvent.deltaY).toBe(20); cleanup(); }); it('should emit end event on pointer up', () => { const { signal, cleanup } = createDragStream(element, { threshold: 0 }); signal.subscribe((event) => { if (event) events.push(event); }); // Simulate drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerMove); const pointerUp = new PointerEvent('pointerup', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerUp); expect(events.some((e) => e.type === 'end')).toBe(true); cleanup(); }); it('should respect threshold', () => { const { signal, cleanup } = createDragStream(element, { threshold: 10 }); signal.subscribe((event) => { if (event) events.push(event); }); // Simulate small drag (below threshold) const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); const pointerMove = new PointerEvent('pointermove', { clientX: 15, clientY: 15 }); document.dispatchEvent(pointerMove); // Should not emit events yet expect(events.length).toBe(0); // Simulate larger drag (above threshold) const pointerMove2 = new PointerEvent('pointermove', { clientX: 25, clientY: 25 }); document.dispatchEvent(pointerMove2); // Should now emit events expect(events.length).toBeGreaterThan(0); cleanup(); }); it('should cleanup event listeners', () => { const { cleanup } = createDragStream(element); const addEventListenerSpy = jest.spyOn(document, 'addEventListener'); const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener'); // Trigger drag to attach document listeners const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); expect(addEventListenerSpy).toHaveBeenCalled(); cleanup(); expect(removeEventListenerSpy).toHaveBeenCalled(); addEventListenerSpy.mockRestore(); removeEventListenerSpy.mockRestore(); }); it('should ignore non-primary mouse buttons', () => { const { signal, cleanup } = createDragStream(element); signal.subscribe((event) => { if (event) events.push(event); }); // Simulate right-click drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 2 }); element.dispatchEvent(pointerDown); const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerMove); // Should not emit any events expect(events.length).toBe(0); cleanup(); }); it('should stop propagation during drag', () => { const { signal, cleanup } = createDragStream(element, { threshold: 0 }); signal.subscribe((event) => { if (event) events.push(event); }); // Start drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0 }); element.dispatchEvent(pointerDown); // Move - should prevent click const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerMove); // End drag const pointerUp = new PointerEvent('pointerup', { clientX: 20, clientY: 20 }); document.dispatchEvent(pointerUp); // Simulate click after drag const clickHandler = jest.fn(); document.addEventListener('click', clickHandler, { capture: true }); const click = new MouseEvent('click', { bubbles: true }); Object.defineProperty(click, 'stopPropagation', { value: jest.fn() }); Object.defineProperty(click, 'preventDefault', { value: jest.fn() }); document.dispatchEvent(click); document.removeEventListener('click', clickHandler, { capture: true }); cleanup(); }); it('should handle pointer leave events', () => { const { signal, cleanup } = createDragStream(element, { threshold: 0 }); signal.subscribe((event) => { if (event) events.push(event); }); // Start drag const pointerDown = new PointerEvent('pointerdown', { clientX: 10, clientY: 10, button: 0, pointerId: 1 }); element.dispatchEvent(pointerDown); // Move to start dragging const pointerMove = new PointerEvent('pointermove', { clientX: 20, clientY: 20, pointerId: 1 }); document.dispatchEvent(pointerMove); // Pointer leaves document const pointerOut = new PointerEvent('pointerout', { clientX: 20, clientY: 20, pointerId: 1, relatedTarget: document.documentElement, }); document.dispatchEvent(pointerOut); // Should emit end event expect(events.some((e) => e.type === 'end')).toBe(true); cleanup(); }); });