import {fireEvent, render, screen} from 'sentry-test/reactTestingLibrary'; import {useTimelineZoom} from './timelineZoom'; interface TestProps { onSelect?: (startX: number, endX: number) => void; } function TestComponent({onSelect}: TestProps) { const {isActive, timelineSelector, selectionContainerRef} = useTimelineZoom({enabled: true, onSelect}); return (
{isActive &&
Selection Active
}
{timelineSelector}
); } beforeEach(() => { jest .spyOn(window, 'requestAnimationFrame') .mockImplementation((callback: FrameRequestCallback): number => { callback(0); return 0; }); }); afterEach(() => { jest.mocked(window.requestAnimationFrame).mockRestore(); }); function setupTestComponent() { const handleSelect = jest.fn(); render(); const body = screen.getByTestId('body'); const container = screen.getByTestId('container'); container.getBoundingClientRect = jest.fn(() => ({ x: 10, y: 10, width: 100, height: 100, left: 10, top: 10, right: 110, bottom: 110, toJSON: jest.fn(), })); return {handleSelect, body, container}; } describe('TimelineZoom', function () { it('triggers onSelect', function () { const {handleSelect, body, container} = setupTestComponent(); // Selector has not appeared expect(screen.queryByRole('presentation')).not.toBeInTheDocument(); // Selection does not start when clicking outside the container fireEvent.mouseDown(body, {button: 0, clientX: 0, clientY: 0}); expect(screen.queryByRole('presentation')).not.toBeInTheDocument(); // Move cursor into the container, selection still not present fireEvent.mouseMove(body, {clientX: 20, clientY: 20}); expect(screen.queryByRole('presentation')).not.toBeInTheDocument(); // Left click starts selection fireEvent.mouseDown(body, {button: 0, clientX: 20, clientY: 20}); const selection = screen.getByRole('presentation'); expect(selection).toBeInTheDocument(); expect(screen.getByText('Selection Active')).toBeInTheDocument(); expect(container.style.getPropertyValue('--selectionStart')).toBe('10px'); expect(container.style.getPropertyValue('--selectionWidth')).toBe('0px'); // Body has disabled text selection expect(document.body).toHaveStyle({userSelect: 'none'}); // Move right 15px fireEvent.mouseMove(body, {clientX: 35, clientY: 20}); expect(container.style.getPropertyValue('--selectionWidth')).toBe('15px'); // Move left 25px, at the edge of the container fireEvent.mouseMove(body, {clientX: 10, clientY: 20}); expect(container.style.getPropertyValue('--selectionStart')).toBe('0px'); expect(container.style.getPropertyValue('--selectionWidth')).toBe('10px'); // Move left 5px more, selection does not move out of the container fireEvent.mouseMove(body, {clientX: 5, clientY: 20}); expect(container.style.getPropertyValue('--selectionStart')).toBe('0px'); expect(container.style.getPropertyValue('--selectionWidth')).toBe('10px'); // Release to make selection fireEvent.mouseUp(body, {clientX: 5, clientY: 20}); expect(handleSelect).toHaveBeenCalledWith(0, 10); }); it('does not start selection with right click', function () { const {body} = setupTestComponent(); // Move cursor into the container, selection still not present fireEvent.mouseMove(body, {clientX: 20, clientY: 20}); // Right click does nothing fireEvent.mouseDown(body, {button: 1, clientX: 20, clientY: 20}); expect(screen.queryByRole('presentation')).not.toBeInTheDocument(); }); it('does not select for very small regions', function () { const {handleSelect, body, container} = setupTestComponent(); // Left click starts selection fireEvent.mouseMove(body, {clientX: 20, clientY: 20}); fireEvent.mouseDown(body, {button: 0, clientX: 20, clientY: 20}); fireEvent.mouseMove(body, {clientX: 22, clientY: 20}); const selection = screen.getByRole('presentation'); expect(selection).toBeInTheDocument(); expect(screen.getByText('Selection Active')).toBeInTheDocument(); expect(container.style.getPropertyValue('--selectionStart')).toBe('10px'); expect(container.style.getPropertyValue('--selectionWidth')).toBe('2px'); // Relase does not make selection for such a small range fireEvent.mouseUp(body, {clientX: 22, clientY: 20}); expect(handleSelect).not.toHaveBeenCalledWith(0, 10); }); });