-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React 18 Migration: Refactor the React test suite to use React Testing Library #10184
Comments
High level steps
|
PatternsWhat should we test?
Including RTL importsimport { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
Find parts of a component to interact with
screen.getByRole('button', {name: /submit/i}); Avoid nesting while you're testing
Avoid using .toMatchSnapshot()
|
These are some helpful things I used a lot to refactor the tabs tests to RTL Examples of RTL tests in our components
Helpful docs
|
Renders as expectedAbout This is a common pattern in the codebase that uses What does it look like describe('ProgressIndicatorSkeleton', () => {
describe('Renders as expected', () => {
it('should have the expected classes', () => {
const wrapper = mount(<ProgressIndicatorSkeleton />);
expect(wrapper.hasClass(`${prefix}--skeleton`)).toEqual(true);
expect(wrapper.hasClass(`${prefix}--progress`)).toEqual(true);
});
});
}); What about this is problematic Tests that assert if a component renders are not needed as this would be caught by other tests that are asserting what happens as a user interacts with a component. For tests that assert on class names, these are not being tested in Jest and instead would be tested by appearance in VRT. What to do about it In most cases, you can remove these tests. If the test is for class names, replace it with a Visual Regression Test. Component is mounted in an outer scopeAbout In parts of our tests, you will see a component mounted outside of an What does it look like describe('SomeComponent', () => {
const wrapper = mount(/* ... */);
it('should do ...', () => {
// Interacts with wrapper
});
}); What about this is problematic This outermost wrapper is inherently stateful. This means that if your tests are interacting with it, reading data from it, etc that you could run into flaky tests that depend on a specific ordering in order to pass. Overall, this leads to tests that are harder to debug when things go wrong. What to do about it You can move the describe('SomeComponent', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(/* ... */);
});
it('should do ...', () => {
// Interacts with wrapper
});
}); This will ensure that the component is reset across test runs
|
We need to resurrect #4467 so that |
@tay1orjones PR for it over in: #10302 👍 |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Where to place component composition (children) integration tests
|
Testing pseudo elements
|
Test file archetypesSnapshot testsA snapshot test is a test file that only tests the structural output of a component. For example, Exampleimport React from 'react';
import { BreadcrumbSkeleton } from '../';
import { mount } from 'enzyme';
describe('BreadcrumbSkeleton', () => {
it('should render', () => {
const wrapper = mount(<BreadcrumbSkeleton />);
expect(wrapper).toMatchSnapshot();
});
}); This test should be refactored to test the following applicable parts of a component:
Refactorimport React from 'react';
import { BreadcrumbSkeleton } from '../';
import { render } from '@testing-library/react';
describe('BreadcrumbSkeleton', () => {
it('should support a custom `className` prop on the outermost element', () => {
const { container } = render(<BreadcrumbSkeleton className="test" />);
expect(container.firstChild).toHaveClass('test');
});
it('should spread additional props on the outermost element', () => {
const { container } = render(<BreadcrumbSkeleton data-testid="test" />);
expect(container.firstChild).toHaveAttribute('test');
});
}); TODO
Insights
Checklist
|
This issue is to track the refactoring of our React test suite to use React Testing Library.
Links and resources
How to find enzyme usages
The list below was generated by searching for
enzyme
within files having names containing our test suffix:finding.enzyme.usages.mov
Please use the script to scaffold out new test files
Tasks
DataTable/__tests__/DataTable-test.js
#12665DataTable/__tests__/TableExpandHeader-test.js
#12666DataTable/__tests__/TableExpandRow-test.js
#12667DataTable/__tests__/TableHeader-test.js
#12668DataTable/__tests__/TableSelectAll-test.js
#12669DataTable/__tests__/TableSelectRow-test.js
#12670DataTable/__tests__/TableToolbar-test.js
#12671DataTable/__tests__/TableToolbarContent-test.js
#12672DataTable/__tests__/TableToolbarMenu-test.js
#12673DataTable/__tests__/TableToolbarSearch-test.js
#12674DataTableSkeleton/DataTableSkeleton-test.js
#12675RadioButtonGroup/next/RadioButtonGroup-test.js
#11736Search/Search-test.js
#12153SearchFilterButton
#12155SecondaryButton/SecondaryButton-test.js
#12157Select/Select-test.js
#12158SelectItem/SelectItem-test.js
#12159SelectItemGroup/SelectItemGroup-test.js
#12160Slider/Slider-test.js
#12676StructuredList-test.js
#12663Switch/Switch-test.js
#12354TextArea/TextArea-test.js
#12677TextInput/PasswordInput-test.js
#12678Tile/Tile-test.js
#12679TileGroup/TileGroup-test.js
#12680ToggleSmall/ToggleSmall-test.js
#12681Tooltip/Tooltip-test.js
#12683TooltipDefinition/TooltipDefinition-test.js
#12682TooltipIcon/TooltipIcon-test.js
#12684TreeView/TreeView-test.js
#12685internal ClickListener-test.js
#12686internal InnerClickListener-test.js
#12687internal Selection-test.js
#12688Initial wave of refactor (complete)
Breadcrumb/__tests__/Breadcrumb-test.js
#10273CodeSnippet/tests/CodeSnippet-test.js
#10272ComboBox/ComboBox-test.js
#11706ComposedModal/ComposedModal-test.js
#11883ComposedModal/next/ComposedModal-test.js
#11886ComposedModal/next/ModalFooter-test.js
#11884ContentSwitcher/ContentSwitcher-test.js
#11885Copy/Copy-test.js
#11509CopyButton/CopyButton-test.js
#11510DangerButton/DangerButton-test.js
#11511DatePicker/DatePicker-test.js
#11512Dropdown/Dropdown-test.js
#11704FluidForm/FluidForm-test.js
#11956FluidTextInput/__tests__/FluidTextInput-test.js
#11994Form/Form-test.js
#11641FormGroup/FormGroup-test.js
#11642FormItem/FormItem-test.js
#11643FormLabel/FormLabel-test.js
#11644Icon/IconSkeleton-test.js
#11559InlineLoading/InlineLoading-test.js
#11560Link/Link-test.js
#11561ListItem/ListItem-test.js
#11824Loading/Loading-test.js
#11957Menu/Menu-test.js
#11710Modal/Modal-test.js
#11711Modal/next/Modal-test.js
#11712ModalWrapper/ModalWrapper-test.js
#11713MultiSelect/__tests__/FilterableMultiSelect-test.js
#11705MultiSelect/next/__tests__/FilterableMultiSelect-test.js
#11707Notification/Notification-test.js
#11714NumberInput/NumberInput-test.js
#11729OrderedList/OrderedList-test.js
#10277OverflowMenu/OverflowMenu-test.js
#11730OverflowMenu/next/OverflowMenu-test.js
#11731OverflowMenuItem/OverflowMenuItem-test.js
#11732Pagination/Pagination-test.js
#12021Pagination/next/__tests__/Pagination-test.js
#12022PaginationNav/PaginationNav-test.js
#12023PrimaryButton/PrimaryButton-test.js
#11958ProgressIndicator/ProgressIndicator-test.js
#12087RadioButton/RadioButton-test.js
#11733RadioButton/next/RadioButton-test.js
#11734RadioButtonGroup/RadioButtonGroup-test.js
#11735RadioTile/RadioTile-test.js
#12088Search/next/Search-test.js
#12154SearchLayoutButton
#12156SkeletonPlaceholder/SkeletonPlaceholder-test.js
#11630SkeletonText/SkeletonText-test.js
#11629Tab/Tab-test.js
#11709Tabs/Tabs-test.js
(note:Tabs/next/Tabs-test.js
was refactored to RTL so can copy from that) #11708Tag/Tag-test.js
#10274TextInput/TextInput-test.js
#11995Toggle/Toggle-test.js
#10275UnorderedList/UnorderedList-test.js
#10276The text was updated successfully, but these errors were encountered: