getByRole("progressbar") is pretty slow
See original GitHub issueReact Testing Library
version: 10.0.4 (I’m using/react
not/dom
but I’m posting here asgetByRole
is implemented here)node
version: 🤷 (codesandbox)npm
(oryarn
) version: 🤷 (codesandbox)
I’ve noticed that some of my tests were pretty slow to run (more than 2 seconds). After investigating, I’ve noticed that the following pattern was to source of the slowness:
await waitForElementToBeRemoved(() => screen.getByRole('progressbar'))
If I add a data-testid
to my loader and switch to:
await waitForElementToBeRemoved(() => screen.getByTestId('loader'))
it’s much faster.
Relevant code or config:
I’m sometimes displayed a CircularProgress
from material-ui
while fetching some data and I use this pattern to wait for it to be removed.
await waitForElementToBeRemoved(() => screen.getByRole('progressbar'))
example of implementation
if(isLoading) {
return <CircularProgress className={classes.loader} data-testid="loader" />
}
What happened:
Here are 2 tests outputs where I only change the pattern mentioned above.
getByRole
getByTestId:
Reproduction:
I’ve create the following Sandbox: https://codesandbox.io/s/musing-gauss-e1ynf?file=/src/Demo.js
The numbers are much smaller but when running the tests several times we can see that the getByRole
is slower when used on the CircularProgress
.
Problem description:
I think that
await waitForElementToBeRemoved(() => screen.getByRole('progressbar'))
is the best pattern to test that a loader is displayed on screen. However, the slowness prevents us from using in all our tests as it quickly gets slow.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:58 (20 by maintainers)
getByRole
can get quite expensive in large trees since it currently checks every element whileByTestId
is a simplequerySelector
. It also includes a lot more a11y related checks. For example it won’t return inaccessible elements.Since you actually remove the element from the DOM you can ignore the additional a11y tree checks and go with
getByRole('progressbar', { hidden: false })
.On slow machines these additional checks can starve your CPU and you should increase the polling interval with
waitForElementToBeRemoved(() => {}, { interval: 200 })
(try out which interval works best).And last but not least: What version of
jest
or, more specifically,jsdom
are you using? In laterjsdom
versions (or actual browsers)getByRole
should be a lot faster.For us: I think we should make the perf impact of
hidden
inByRole
clearer in the docs. Also mention too low polling rate on slow machines.For those who use
styled-components
a lot, such wrapper could improvegetByRole
performance by leaving only a few css rules used by@testing-library
and thus significantly reducing<style>
size