|
| 1 | +--- |
| 2 | +title: Vitest component testing |
| 3 | +category: Testing |
| 4 | +order: 2 |
| 5 | +--- |
| 6 | + |
| 7 | +## Vitest component testing |
| 8 | + |
| 9 | +[Vitest](https://vitest.dev/guide/) is our fastest tool for in-memory testing of components and logic in a Node.js environment. We pair it with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) to validate behavior, rendering, and edge cases—all without requiring a real browser. |
| 10 | + |
| 11 | +### Running Vitest |
| 12 | + |
| 13 | +Vitest can be run from the project root with the following command. It's configured in our CI pipeline so pushing a branch to remote runs these tests automatically. |
| 14 | + |
| 15 | +``` |
| 16 | +npm run test:vitest |
| 17 | +``` |
| 18 | + |
| 19 | +### Creating new tests |
| 20 | + |
| 21 | +Current tests can be found next to the component source code in the `__tests__` subfolder. New tests should be added there. |
| 22 | + |
| 23 | +Vitest tests usually have a structure like this: |
| 24 | + |
| 25 | +```js |
| 26 | +--- |
| 27 | +type: code |
| 28 | +--- |
| 29 | +import { render, screen } from '@testing-library/react' |
| 30 | +import { vi } from 'vitest' |
| 31 | + |
| 32 | +import '@testing-library/jest-dom' |
| 33 | +import ComponentToTest from '../index' |
| 34 | + |
| 35 | +describe('<ComponentToTest/>', () => { |
| 36 | + it('works as intended...', () => { |
| 37 | + const onClickMock = vi.fn() |
| 38 | + render(<ComponentToTest onClick={onClickMock}/>) |
| 39 | + // rest of the test comes here |
| 40 | + }) |
| 41 | +}) |
| 42 | +``` |
| 43 | + |
| 44 | +### Example |
| 45 | + |
| 46 | +The `ui-avatar` tests can be found [here](https://github.com/instructure/instructure-ui/tree/master/packages/ui-avatar/src/Avatar/__tests__). |
| 47 | + |
| 48 | +### Debugging tests |
| 49 | + |
| 50 | +If you need to debug a test in your IDE or print extra info, you can use: |
| 51 | + |
| 52 | +``` |
| 53 | +console.log('Debug info') |
| 54 | +``` |
| 55 | + |
| 56 | +To inspect the rendered DOM and current test state, you can also use: |
| 57 | + |
| 58 | +``` |
| 59 | +screen.debug() |
| 60 | +``` |
| 61 | + |
| 62 | +### Simulating Real User Interactions |
| 63 | + |
| 64 | +While fireEvent from React Testing Library works for basic interaction simulation, we use @testing-library/user-event for more realistic and accessible user interaction testing. |
| 65 | +[userEvent](https://testing-library.com/docs/user-event/intro/) is a companion library for Testing Library that provides more advanced simulation of browser interactions than the built-in fireEvent method. |
| 66 | +While fireEvent dispatches single DOM events, userEvent can fire multiple events and do additional checks along the way, making your tests closer to actual user experience. |
| 67 | + |
| 68 | +Use it in the following way: |
| 69 | + |
| 70 | +```js |
| 71 | +--- |
| 72 | +type: code |
| 73 | +--- |
| 74 | +import { render, screen } from '@testing-library/react' |
| 75 | +import { vi } from 'vitest' |
| 76 | + |
| 77 | +import '@testing-library/jest-dom' |
| 78 | +import userEvent from '@testing-library/user-event' |
| 79 | +import ComponentToTest from '../index' |
| 80 | + |
| 81 | +describe('<ComponentToTest/>', () => { |
| 82 | + it('works as intended...', async () => { |
| 83 | + const onKeyDownMock = vi.fn() |
| 84 | + render(<ComponentToTest onKeyDown={onKeyDownMock}/>) |
| 85 | + |
| 86 | + const input = screen.getByTestId('input') |
| 87 | + await userEvent.type(input, 'foo bar{enter}') |
| 88 | + // rest of the test comes here |
| 89 | + }) |
| 90 | +}) |
| 91 | +``` |
0 commit comments