UNPKG

@amsterdam/design-system-react

Version:

All React components from the Amsterdam Design System. Use it to compose pages in your website or application.

109 lines (108 loc) 5.19 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * @license EUPL-1.2+ * Copyright Gemeente Amsterdam */ import { fireEvent, render, screen } from '@testing-library/react'; import { useRef } from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { KeyboardKeys, useKeyboardFocus } from './useKeyboardFocus'; describe('useKeyboardFocus', () => { const onFocusOneMock = vi.fn(); const onFocusTwoMock = vi.fn(); const onFocusThreeMock = vi.fn(); const Component = ({ rotate = undefined }) => { const ref = useRef(null); const { keyDown } = useKeyboardFocus(ref, { rotating: rotate, }); return (_jsxs("div", { onKeyDown: keyDown, ref: ref, role: "menu", tabIndex: 0, children: [_jsx("button", { onFocus: onFocusOneMock, type: "button", children: "One" }), _jsx("button", { onFocus: onFocusTwoMock, type: "button", children: "Two" }), _jsx("button", { onFocus: onFocusThreeMock, type: "button", children: "Three" })] })); }; afterEach(() => { onFocusOneMock.mockReset(); onFocusTwoMock.mockReset(); onFocusThreeMock.mockReset(); }); it('sets focus when using arrow keys', () => { const { container } = render(_jsx(Component, {})); const firstChild = container.firstChild; expect(onFocusOneMock).not.toHaveBeenCalled(); // 4 times, so we can check if there are no other elements focused after reaching the last one Array.from(Array(4).keys()).forEach(() => { fireEvent.keyDown(firstChild, { key: KeyboardKeys.ArrowDown, }); }); expect(onFocusOneMock).toHaveBeenCalledTimes(1); expect(onFocusTwoMock).toHaveBeenCalledTimes(1); expect(onFocusThreeMock).toHaveBeenCalledTimes(1); // Same here Array.from(Array(4).keys()).forEach(() => { fireEvent.keyDown(firstChild, { key: KeyboardKeys.ArrowUp, }); }); expect(onFocusTwoMock).toHaveBeenCalledTimes(2); expect(onFocusOneMock).toHaveBeenCalledTimes(2); }); it('rotates focused elements', () => { const { container } = render(_jsx(Component, { rotate: true })); const firstChild = container.firstChild; Array.from(Array(9).keys()).forEach(() => { fireEvent.keyDown(firstChild, { key: KeyboardKeys.ArrowDown, }); }); expect(onFocusOneMock).toHaveBeenCalledTimes(3); Array.from(Array(9).keys()).forEach(() => { fireEvent.keyDown(firstChild, { key: KeyboardKeys.ArrowUp, }); }); expect(onFocusOneMock).toHaveBeenCalledTimes(6); }); it('only navigates direct children when directChildrenOnly is true', () => { const onFocusNestedMock = vi.fn(); const DirectChildComponent = () => { const ref = useRef(null); const { keyDown } = useKeyboardFocus(ref, { directChildrenOnly: true }); return (_jsxs("div", { onKeyDown: keyDown, ref: ref, role: "menu", tabIndex: 0, children: [_jsx("button", { onFocus: onFocusOneMock, type: "button", children: "One" }), _jsx("div", { children: _jsx("button", { onFocus: onFocusNestedMock, type: "button", children: "Nested" }) }), _jsx("button", { onFocus: onFocusTwoMock, type: "button", children: "Two" })] })); }; render(_jsx(DirectChildComponent, {})); const component = screen.getByRole('menu'); fireEvent.keyDown(component, { key: KeyboardKeys.ArrowDown }); expect(onFocusOneMock).toHaveBeenCalledTimes(1); fireEvent.keyDown(component, { key: KeyboardKeys.ArrowDown }); expect(onFocusTwoMock).toHaveBeenCalledTimes(1); expect(onFocusNestedMock).not.toHaveBeenCalled(); }); it('sets focus to first element when using "Home" key', () => { const { container } = render(_jsx(Component, {})); const firstChild = container.firstChild; fireEvent.keyDown(firstChild, { key: KeyboardKeys.Home, }); expect(onFocusOneMock).toHaveBeenCalledTimes(1); }); it('does nothing when ref.current is null', () => { const NullRefComponent = () => { const ref = useRef(null); const { keyDown } = useKeyboardFocus(ref, {}); // ref is intentionally not attached to any element so ref.current stays null return _jsx("div", { onKeyDown: keyDown, role: "menu", tabIndex: 0 }); }; render(_jsx(NullRefComponent, {})); const component = screen.getByRole('menu'); fireEvent.keyDown(component, { key: KeyboardKeys.ArrowDown }); // Should return early without focusing anything expect(onFocusOneMock).not.toHaveBeenCalled(); }); it('sets focus to last element when using "End" key', () => { const { container } = render(_jsx(Component, {})); const firstChild = container.firstChild; fireEvent.keyDown(firstChild, { key: KeyboardKeys.End, }); expect(onFocusThreeMock).toHaveBeenCalledTimes(1); }); });