UNPKG

@amsterdam/design-system-react

Version:

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

102 lines (101 loc) 5.64 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * @license EUPL-1.2+ * Copyright Gemeente Amsterdam */ import { fireEvent, render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { createRef } from 'react'; import { describe, expect, it, vi } from 'vitest'; import { ProgressList, progressListHeadingLevels } from './ProgressList'; describe('ProgressList', () => { it('renders', () => { render(_jsx(ProgressList, { headingLevel: 3 })); const list = screen.getByRole('list'); expect(list).toBeInTheDocument(); expect(list).toBeVisible(); expect(list.tagName).toBe('OL'); }); it('renders a design system BEM class name', () => { render(_jsx(ProgressList, { headingLevel: 3 })); const list = screen.getByRole('list'); expect(list).toHaveClass('ams-progress-list'); }); progressListHeadingLevels.forEach((level) => { it(`adds the class for heading level ${level}`, () => { render(_jsx(ProgressList, { headingLevel: level })); const list = screen.getByRole('list'); expect(list).toHaveClass(`ams-progress-list--heading-${level}`); }); it(`renders the heading with level ${level}`, () => { render(_jsx(ProgressList, { headingLevel: level, children: _jsx(ProgressList.Step, { heading: `Heading ${level}` }) })); const heading = screen.getByRole('heading', { level, name: `Heading ${level}` }); expect(heading).toBeInTheDocument(); }); }); it('renders an extra class name', () => { render(_jsx(ProgressList, { className: "extra", headingLevel: 3 })); const list = screen.getByRole('list'); expect(list).toHaveClass('ams-progress-list extra'); }); it('supports ForwardRef in React', () => { const ref = createRef(); render(_jsx(ProgressList, { headingLevel: 3, ref: ref })); const list = screen.getByRole('list'); expect(ref.current).toBe(list); }); it('supports composition using subcomponents', () => { render(_jsx(ProgressList, { headingLevel: 3, children: _jsx(ProgressList.Step, { hasSubsteps: true, heading: "Step", children: _jsx(ProgressList.Substeps, { children: _jsx(ProgressList.Substep, { children: "Substep" }) }) }) })); const [mainList, subStepsList] = screen.getAllByRole('list'); expect(mainList).toHaveClass('ams-progress-list'); expect(subStepsList).toHaveClass('ams-progress-list-substeps'); // Main step is the only list item directly under the main list. const [mainStep] = within(mainList).getAllByRole('listitem'); expect(mainStep).toHaveClass('ams-progress-list__step ams-progress-list__step--has-substeps'); // Substeps are listitems under the substeps list. const [subStep] = within(subStepsList).getAllByRole('listitem'); expect(subStep).toHaveClass('ams-progress-list-substeps__step'); }); it('renders no buttons by default', () => { render(_jsxs(ProgressList, { headingLevel: 3, children: [_jsx(ProgressList.Step, { heading: "one", children: "Content" }), _jsx(ProgressList.Step, { heading: "two", children: "Content" })] })); expect(screen.queryByRole('button')).not.toBeInTheDocument(); }); it('does not handle keyboard navigation by default', () => { render(_jsxs(ProgressList, { headingLevel: 3, children: [_jsx(ProgressList.Step, { heading: "one", children: "Content" }), _jsx(ProgressList.Step, { heading: "two", children: "Content" })] })); const list = screen.getByRole('list'); const onKeyDown = vi.fn(); list.addEventListener('keydown', onKeyDown); for (const key of ['ArrowDown', 'ArrowUp', 'Home', 'End']) { fireEvent.keyDown(list, { key }); } // Events fire on the element, but none are intercepted (no preventDefault called) expect(onKeyDown).toHaveBeenCalledTimes(4); for (const call of onKeyDown.mock.calls) { expect(call[0].defaultPrevented).toBe(false); } }); it('passes additional props', () => { render(_jsx(ProgressList, { "aria-hidden": "false", "data-test": "data-test", headingLevel: 2, id: "id" })); const component = screen.getByRole('list'); expect(component).toHaveAttribute('aria-hidden', 'false'); expect(component).toHaveAttribute('id', 'id'); expect(component).toHaveAttribute('data-test', 'data-test'); }); describe('when collapsible', () => { it('sets focus on step buttons when using arrow keys', async () => { const user = userEvent.setup(); render(_jsxs(ProgressList, { collapsible: true, headingLevel: 3, children: [_jsx(ProgressList.Step, { heading: "one", children: "Content" }), _jsx(ProgressList.Step, { heading: "two", children: "Content" }), _jsx(ProgressList.Step, { heading: "three", children: "Content" })] })); const firstButton = screen.getByRole('button', { name: /one/ }); const thirdButton = screen.getByRole('button', { name: /three/ }); await user.click(firstButton); expect(firstButton).toHaveFocus(); await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowDown}'); expect(thirdButton).toHaveFocus(); expect(firstButton).not.toHaveFocus(); // Rotating: wraps from last to first await user.keyboard('{ArrowDown}'); expect(firstButton).toHaveFocus(); }); }); });