diff --git a/packages/ui/package.json b/packages/ui/package.json index 05b4754f..0a63b966 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -47,6 +47,7 @@ "@rollup/plugin-typescript": "11.1.6", "@testing-library/react": "15.0.7", "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", "@types/lodash.kebabcase": "4.1.9", "@types/jest": "29.5.12", "@types/react-dom": "18.2.19", diff --git a/packages/ui/src/components/Markdown/Markdown.test.tsx b/packages/ui/src/components/Markdown/Markdown.test.tsx index 29ecf879..5912c594 100644 --- a/packages/ui/src/components/Markdown/Markdown.test.tsx +++ b/packages/ui/src/components/Markdown/Markdown.test.tsx @@ -12,7 +12,7 @@ describe('Markdown', () => { }); it('should render the Markdown component with richtext class', () => { const { container } = render(Hello World!); - const text = container.querySelector('.utrecht-rich-text'); + const text = container.querySelector(':only-child'); expect(text).toBeInTheDocument(); }); it('should render custom component', () => { diff --git a/packages/ui/src/components/Navigation/NavigationIcon/index.test.tsx b/packages/ui/src/components/Navigation/NavigationIcon/index.test.tsx new file mode 100644 index 00000000..f255288a --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationIcon/index.test.tsx @@ -0,0 +1,29 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { createRef } from 'react'; +import { NavigationIcon } from './index'; + +describe('NavigationIcon', () => { + it('renders the hamburger icon', () => { + const { container } = render(); + expect(container.querySelector('svg')).toHaveAttribute('aria-hidden', 'true'); + expect(container.querySelectorAll('line')).toHaveLength(3); + }); + + it('renders the close icon', () => { + const { container } = render(); + expect(container.querySelector('svg')).toHaveAttribute('aria-hidden', 'true'); + expect(container.querySelectorAll('line')).toHaveLength(2); + }); + + it('renders the icon with the provided ref', () => { + const ref = createRef(); + const { container } = render(); + expect(ref.current).toBe(container.querySelector('svg')); + }); + + it('renders a design system BEM class name', () => { + const { container } = render(); + expect(container.querySelector('svg')).toHaveClass('utrecht-topnav__icon'); + }); +}); diff --git a/packages/ui/src/components/Navigation/NavigationItem/index.test.tsx b/packages/ui/src/components/Navigation/NavigationItem/index.test.tsx new file mode 100644 index 00000000..0e645e36 --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationItem/index.test.tsx @@ -0,0 +1,31 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { createRef } from 'react'; +import { NavigationItem } from './index'; + +describe('NavigationItem', () => { + it('renders NavigationItem component', () => { + const { container } = render(Test); + const navItem = container.querySelector(':only-child'); + expect(navItem).toBeInTheDocument(); + }); + + it('renders a design system BEM class name', () => { + const { container } = render(Test); + const navItem = container.querySelector(':only-child'); + expect(navItem).toHaveClass('utrecht-navigation__item'); + }); + + it('should render a list item with the appropriate class name when mobile', () => { + const { container } = render(Test); + const navItem = container.querySelector(':only-child'); + expect(navItem).toHaveClass('utrecht-navigation__item--mobile'); + expect(navItem).toHaveClass('utrecht-navigation__item-icon'); + }); + + it('should forward the ref to the list item', () => { + const ref = createRef(); + const { container } = render(Test); + expect(container.firstChild).toBe(ref.current); + }); +}); diff --git a/packages/ui/src/components/Navigation/NavigationLink/index.test.tsx b/packages/ui/src/components/Navigation/NavigationLink/index.test.tsx new file mode 100644 index 00000000..4eb2047b --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationLink/index.test.tsx @@ -0,0 +1,85 @@ +import { fireEvent, render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { createRef } from 'react'; +import { NavigationLink } from './index'; + +describe('NavigationLink', () => { + it('renders the NavigationLink component', () => { + const { container } = render(Home); + const link = container.querySelector(':only-child'); + expect(link).toBeInTheDocument(); + }); + it('applies the correct class when the link is current', () => { + const { container } = render( + + Home + , + ); + const link = container.querySelector(':only-child'); + expect(link).toHaveClass('utrecht-navigation__link--is-current'); + }); + it('calls the onClick handler when clicked', () => { + const onClick = jest.fn(); + const { container } = render( + + Home + , + ); + const link = container.querySelector(':only-child'); + fireEvent.click(link as HTMLAnchorElement); + expect(onClick).toHaveBeenCalled(); + }); + it('renders the marker when provided', () => { + const { container } = render( + Marker}> + Home + , + ); + const marker = container.querySelector('span'); + expect(marker).toBeInTheDocument(); + }); + it('renders the children when provided', () => { + const { container } = render(Home); + const link = container.querySelector(':only-child'); + expect(link).toHaveTextContent('Home'); + }); + it('applies the correct class when the link is mobile', () => { + const { container } = render( + + Home + , + ); + const link = container.querySelector(':only-child'); + expect(link).toHaveClass('utrecht-navigation__link--mobile'); + }); + it('sets the correct href attribute', () => { + const { container } = render(Home); + const link = container.querySelector(':only-child'); + expect(link).toHaveAttribute('href', '/'); + }); + it('sets the correct aria-current attribute', () => { + const { container } = render( + + Home + , + ); + const link = container.querySelector(':only-child'); + expect(link).toHaveAttribute('aria-current', 'page'); + }); + it('renders the correct role attribute', () => { + const { getByRole } = render(Home); + const link = getByRole('link'); + expect(link).toBeInTheDocument(); + }); + it('supports ForwardRef in React', () => { + const ref = createRef(); + + const { container } = render( + + Home + , + ); + const link = container.querySelector(':only-child'); + expect(ref.current).toBe(link); + }); +}); diff --git a/packages/ui/src/components/Navigation/NavigationLink/index.tsx b/packages/ui/src/components/Navigation/NavigationLink/index.tsx index 12cdefb1..1ae879e0 100644 --- a/packages/ui/src/components/Navigation/NavigationLink/index.tsx +++ b/packages/ui/src/components/Navigation/NavigationLink/index.tsx @@ -4,7 +4,6 @@ import { AnchorHTMLAttributes, ForwardedRef, forwardRef, PropsWithChildren, Reac import styles from './index.module.scss'; interface NavigationLinkProps extends Omit, 'placeholder'> { - placeholder?: boolean; mobile?: boolean; isCurrent?: boolean; marker?: ReactNode; diff --git a/packages/ui/src/components/Navigation/NavigationList/index.test.tsx b/packages/ui/src/components/Navigation/NavigationList/index.test.tsx new file mode 100644 index 00000000..70bd3096 --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationList/index.test.tsx @@ -0,0 +1,118 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { NavigationList } from './index'; +import { NavigationListType } from '../index'; + +const listData: NavigationListType[] = [ + { + href: '#', + textContent: 'Home', + children: [ + { + href: '#', + textContent: 'Sublink 1', + }, + { + href: '#', + textContent: 'Sublink 2', + }, + ], + }, + { + href: '#', + textContent: 'About', + }, +]; +describe('NavigationList', () => { + it('renders NavigationList component', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + expect(navigationList).toBeInTheDocument(); + }); + it('renders a design system BEM class name', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + expect(navigationList).toHaveClass('utrecht-navigation__list'); + }); + it('renders NavigationList component with children', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + const navListItem = container.querySelectorAll('li a'); + navListItem.forEach((item) => { + expect(item).toBeInTheDocument(); + expect(item).toHaveAttribute('href'); + expect(item).toHaveTextContent(/Home|About/); + }); + expect(navListItem.length).toBe(2); + expect(navigationList).toBeInTheDocument(); + }); + describe('Mobile', () => { + it('renders NavigationList component with children and mobile prop', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + const navListItem = container.querySelectorAll('li'); + navListItem.forEach((item) => { + expect(item).toBeInTheDocument(); + expect(item).toHaveClass('utrecht-navigation__item--mobile'); + }); + expect(navigationList).toBeInTheDocument(); + expect(navigationList).toHaveClass('utrecht-navigation__list--mobile'); + }); + it('renders NavigationList component with children and filled marker prop by default', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + const navListItem = navigationList?.querySelectorAll('li a')[0]; + const marker = navListItem?.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + expect(marker).toHaveClass('utrecht-navigation__marker'); + expect(marker).toHaveClass('utrecht-navigation__marker--fill'); + expect(navListItem).toHaveClass('utrecht-navigation__link--mobile'); + expect(navListItem).toBeInTheDocument(); + expect(navigationList).toBeInTheDocument(); + }); + it('renders NavigationList component with children and outlined marker prop', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + const navListItem = navigationList?.querySelectorAll('li a')[1]; + const marker = navListItem?.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + expect(marker).toHaveClass('utrecht-navigation__marker'); + expect(marker).toHaveClass('utrecht-navigation__marker--outline'); + expect(navListItem).toHaveClass('utrecht-navigation__link--mobile'); + expect(navListItem).toBeInTheDocument(); + expect(navigationList).toBeInTheDocument(); + }); + }); + + it('renders NavigationList component with children and sideNav prop', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + expect(navigationList).toBeInTheDocument(); + expect(navigationList).toHaveClass('utrecht-navigation__list--side-nav'); + }); + it('renders NavigationList component with children and subList prop', () => { + const { container } = render(); + const navigationList = container.querySelector(':only-child'); + const navListItem = navigationList?.querySelectorAll('li'); + navListItem?.forEach((item) => { + const subList = item.querySelectorAll('li ul'); + subList?.forEach((subItem) => { + expect(subItem).toBeInTheDocument(); + expect(subItem).toHaveClass('utrecht-navigation__list--sub-list'); + }); + expect(item).toBeInTheDocument(); + expect(item).toHaveClass('utrecht-navigation__item'); + }); + expect(navigationList).toBeInTheDocument(); + expect(navigationList).toHaveClass('utrecht-navigation__list--sub-list'); + }); + test('focuses on the first link when the list receives focus', () => { + render(); + const firstLink = screen.getByText('Home'); + const navList = firstLink.closest('ul'); + expect(navList).toHaveAttribute('tabIndex', '-1'); + + fireEvent.focus(navList as HTMLUListElement); + expect(firstLink).toHaveFocus(); + }); +}); diff --git a/packages/ui/src/components/Navigation/NavigationMarker/index.test.tsx b/packages/ui/src/components/Navigation/NavigationMarker/index.test.tsx new file mode 100644 index 00000000..fe25a372 --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationMarker/index.test.tsx @@ -0,0 +1,49 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +// import { createRef } from 'react'; +import { NavigationMarker } from './index'; + +describe('NavigationMarker', () => { + it('renders a NavigationMarker', () => { + const { container } = render(); + const marker = container.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + }); + it('renders a design system BEM class name', () => { + const { container } = render(); + const marker = container.querySelector(':only-child'); + expect(marker).toHaveClass('utrecht-navigation__marker'); + }); + it('renders a fill marker by default', () => { + const { container } = render(); + const marker = container.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + expect(marker).toHaveClass('utrecht-navigation__marker--fill'); + expect(marker).not.toHaveClass('utrecht-navigation__marker--outline'); + }); + + it('renders an outline marker when appearance is set to outline', () => { + const { container } = render(); + const marker = container.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + expect(marker).toHaveClass('utrecht-navigation__marker--outline'); + expect(marker).not.toHaveClass('utrecht-navigation__marker--fill'); + }); + + it('renders a current marker when isCurrent is true', () => { + const { container } = render(); + const marker = container.querySelector(':only-child'); + expect(marker).toBeInTheDocument(); + expect(marker).toHaveClass('utrecht-navigation__marker--current'); + }); + // TODO add ForwardRef support to the component + // it('supports ForwardRef in React', () => { + // const ref = createRef(); + + // const { container } = render(); + + // const drawer = container.querySelector(':only-child'); + + // expect(ref.current).toBe(drawer); + // }); +}); diff --git a/packages/ui/src/components/Navigation/NavigationToggleButton/index.test.tsx b/packages/ui/src/components/Navigation/NavigationToggleButton/index.test.tsx new file mode 100644 index 00000000..d59a6682 --- /dev/null +++ b/packages/ui/src/components/Navigation/NavigationToggleButton/index.test.tsx @@ -0,0 +1,58 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { createRef } from 'react'; +import React from 'react'; +import { NavToggleButton } from './index'; + +describe('NavToggleButton', () => { + it('renders NavToggleButton component', () => { + const { container } = render(); + const navToggleButton = container.querySelector(':only-child'); + expect(navToggleButton).toBeInTheDocument(); + }); + it('renders a design system BEM class name', () => { + const { container } = render(); + const navToggleButton = container.querySelector(':only-child'); + expect(navToggleButton).toHaveClass('utrecht-navigation__toggle-button'); + }); + describe('aria attributes', () => { + it('renders with aria-haspopup="menu"', () => { + const { container } = render(); + const navToggleButton = container.querySelector('button[aria-haspopup="menu"]'); + expect(navToggleButton).toBeInTheDocument(); + }); + it('renders with aria-controls="menu"', () => { + const { container } = render(); + const navToggleButton = container.querySelector('button[aria-haspopup="menu"]'); + expect(navToggleButton).toBeInTheDocument(); + }); + }); + it('renders a button with the hamburger icon and text', () => { + const { container } = render(); + const button = container.querySelector(':only-child'); + expect(button).toHaveTextContent('Open menu'); + const svg = button?.querySelector('svg'); + expect(svg?.querySelectorAll('line')).toHaveLength(3); + }); + it('renders a button with the close icon and text', () => { + const { container } = render(); + const button = container.querySelector(':only-child'); + expect(button).toHaveTextContent('Close menu'); + const svg = button?.querySelector('svg'); + expect(svg?.querySelectorAll('line')).toHaveLength(2); + }); + it('supports ForwardRef in React', () => { + const ref = createRef(); + const { container } = render(); + const button = container.querySelector('button'); + expect(ref.current).toBe(button); + expect(button).toBeInTheDocument(); + }); + it('renders a button with the subtle-button appearance', () => { + const { container } = render(); + const element = container.querySelector(':only-child'); + const button = element?.querySelector(':only-child'); + expect(button).toHaveClass('utrecht-button'); + expect(button).toHaveClass('utrecht-button--subtle'); + }); +}); diff --git a/packages/ui/src/components/Navigation/index.test.tsx b/packages/ui/src/components/Navigation/index.test.tsx new file mode 100644 index 00000000..20b01d63 --- /dev/null +++ b/packages/ui/src/components/Navigation/index.test.tsx @@ -0,0 +1,204 @@ +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { Navigation } from './index'; +import { useScreenSize } from '../../hooks'; +import { useClickOutside } from '../../hooks'; +import { useLockBody } from '../../hooks/useLockBody'; +jest.mock('../../hooks/useClickOutside.ts', () => ({ + useClickOutside: jest.fn(), +})); + +jest.mock('../../hooks/useLockBody', () => ({ + useLockBody: jest.fn(), +})); + +jest.mock('../../hooks/useScreenSize.ts'); + +const mockList = [ + { textContent: 'Home', href: '/' }, + { textContent: 'About', href: '/about' }, +]; +const mockToggleButton = { + openText: 'Open Menu', + closeText: 'Close Menu', +}; +describe('Navigation Component', () => { + beforeEach(() => { + (useScreenSize as jest.Mock).mockReturnValue(1024); // default desktop size + HTMLDialogElement.prototype.show = jest.fn(function () { + // eslint-disable-next-line no-invalid-this + this.open = true; + }); + + HTMLDialogElement.prototype.showModal = jest.fn(function () { + // eslint-disable-next-line no-invalid-this + this.open = true; + }); + + HTMLDialogElement.prototype.close = jest.fn(function () { + // eslint-disable-next-line no-invalid-this + this.open = false; + }); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('renders Navigation component', () => { + const { container } = render(); + const nav = container.querySelector(':only-child'); + expect(nav).toBeInTheDocument(); + }); + test('should render the Navigation list on desktop view', () => { + const { container } = render(); + const nav = container.querySelector('nav'); + const navList = nav?.querySelector(':only-child'); + const navListItems = navList?.querySelectorAll('li a'); + + expect(navListItems?.length).toBe(2); + navListItems?.forEach((item) => { + expect(item).toBeInTheDocument(); + expect(item).toHaveAttribute('href'); + expect(item).toHaveTextContent(/Home|About/); + }); + expect(navList).toBeInTheDocument(); + expect(nav).toBeInTheDocument(); + }); + + test('should render the hamburger button in mobile view', () => { + (useScreenSize as jest.Mock).mockReturnValue(500); // mobile size + const { container } = render(); + const nav = container.querySelector('nav'); + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + + expect(hamburgerButton).toBeInTheDocument(); + expect(nav).toBeInTheDocument(); + }); + + test('should toggle the dialog when hamburger button is clicked', () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // mobile size + const { container } = render(); + const nav = container.querySelector('nav'); + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + + fireEvent.click(hamburgerButton as HTMLButtonElement); + const dialog = container.querySelector('dialog[open]'); + expect(nav).toBeInTheDocument(); + expect(dialog).toBeInTheDocument(); + }); + + test('should close the dialog when close button is clicked', async () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // mobile size + const user = userEvent.setup(); + const { container } = render(); + const nav = container.querySelector('nav'); + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + + await user.click(hamburgerButton as HTMLButtonElement); + + const dialog = container.querySelector('dialog[open]'); + const closeButton = screen.getByRole('button', { name: 'Close Menu' }); + expect(dialog).toHaveAttribute('open'); + await user.click(closeButton as HTMLButtonElement); + + expect(nav).toBeInTheDocument(); + expect(dialog).toBeInTheDocument(); + await waitFor(() => { + expect(container.querySelector('dialog[open]')).not.toBeInTheDocument(); + }); + }); + + test('should close the drawer when clicking outside', () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // mobile size + const clickOutsideHandler = jest.fn(); + (useClickOutside as jest.Mock).mockImplementation((ref, handler) => { + clickOutsideHandler.mockImplementation(handler); + }); + + const { container } = render(); + const dialog = container.querySelector('dialog[open]'); + clickOutsideHandler(); + expect(dialog).not.toBeInTheDocument(); + }); + test('should lock body scroll when drawer is open', () => { + (useScreenSize as jest.Mock).mockReturnValue(500); // Mobile view + render(); + + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + fireEvent.click(hamburgerButton); + + expect(useLockBody).toHaveBeenCalledWith(true, expect.anything()); + }); + test('FocusTrap traps focus within the drawer when it is open', async () => { + const user = userEvent.setup(); + (useScreenSize as jest.Mock).mockReturnValue(450); // Mobile view + const { container } = render(); + + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + fireEvent.click(hamburgerButton); + + await waitFor(() => { + const dialog = container.querySelector('dialog'); + expect(dialog).toBeInTheDocument(); + const focusableElement = screen.getByText('Close Menu'); + expect(focusableElement).toHaveFocus(); + }); + await user.tab(); + await waitFor(() => { + const closeButton = screen.getByText('Home'); + expect(closeButton).toHaveFocus(); + }); + await user.tab(); + await waitFor(() => { + const closeButton = screen.getByText('About'); + expect(closeButton).toHaveFocus(); + }); + // Navigating backward through the focus trap and looping back to the start + await user.tab(); + await waitFor(() => { + const closeButton = screen.getByText('Close Menu'); + expect(closeButton).toHaveFocus(); + }); + }); + test('FocusTrap should deactivate when the drawer is closed', async () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // Mobile view + const user = userEvent.setup(); + render(); + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + await user.click(hamburgerButton); + const closeButton = screen.getByText('Close Menu'); + await user.click(closeButton); + await waitFor(() => { + expect(screen.getByText('Open Menu')).toHaveFocus(); + }); + }); + test('Pressing Escape should close the drawer and deactivate FocusTrap', async () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // Mobile view + const user = userEvent.setup(); + render(); + + const hamburgerButton = screen.getByRole('button', { name: 'Open Menu' }); + await user.click(hamburgerButton); + + fireEvent.keyDown(document, { key: 'Escape', code: 'Escape' }); + await waitFor(() => { + expect(screen.getByRole('button', { name: 'Open Menu' })).toHaveFocus(); + }); + }); + test('should render the Navigation list on mobile view', () => { + (useScreenSize as jest.Mock).mockReturnValue(450); // mobile size + const { container } = render(); + const nav = container.querySelector('nav'); + const navList = nav?.querySelector(':only-child'); + const navListItems = navList?.querySelectorAll('li a'); + + navListItems?.forEach((item) => { + expect(item).toBeInTheDocument(); + expect(item).toHaveAttribute('href'); + expect(item).toHaveTextContent(/Home|About/); + }); + expect(navList).toBeInTheDocument(); + expect(nav).toBeInTheDocument(); + }); +}); diff --git a/packages/ui/tests/__mocks__/tabbable.js b/packages/ui/tests/__mocks__/tabbable.js new file mode 100644 index 00000000..96eb49eb --- /dev/null +++ b/packages/ui/tests/__mocks__/tabbable.js @@ -0,0 +1,11 @@ +// https://github.com/focus-trap/tabbable?tab=readme-ov-file#testing-in-jsdom +const lib = jest.requireActual('tabbable'); +const tabbable = { + ...lib, + tabbable: (node, options) => lib.tabbable(node, { ...options, displayCheck: 'none' }), + focusable: (node, options) => lib.focusable(node, { ...options, displayCheck: 'none' }), + isFocusable: (node, options) => lib.isFocusable(node, { ...options, displayCheck: 'none' }), + isTabbable: (node, options) => lib.isTabbable(node, { ...options, displayCheck: 'none' }), +}; +// eslint-disable-next-line no-undef +module.exports = tabbable; diff --git a/packages/ui/tsconfig.test.json b/packages/ui/tsconfig.test.json index 2393929b..f86f7646 100644 --- a/packages/ui/tsconfig.test.json +++ b/packages/ui/tsconfig.test.json @@ -1,5 +1,5 @@ { "extends": "./tsconfig.json", - "include": ["./jest.config.ts", "**/*.test.ts", "**/*.test.tsx"], + "include": ["./jest.config.ts", "**/*.test.ts", "**/*.test.tsx", "./tests/__mocks__/tabbable.js"], "exclude": ["**/node_modules/*"] } diff --git a/yarn.lock b/yarn.lock index fcdd704c..9f373616 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6673,6 +6673,11 @@ "@testing-library/dom" "^10.0.0" "@types/react-dom" "^18.0.0" +"@testing-library/user-event@14.5.2": + version "14.5.2" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" + integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ== + "@tiptap/core@2.2.4": version "2.2.4" resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.2.4.tgz#6f957678eb733e70b9282fb5098d284a77bd09a3"