question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

getByRole("progressbar") is pretty slow

See original GitHub issue
  • React Testing Library version: 10.0.4 (I’m using /react not /dom but I’m posting here as getByRole is implemented here)
  • node version: 🤷 (codesandbox)
  • npm (or yarn) 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 image

getByTestId: image

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.

image

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:closed
  • Created 3 years ago
  • Reactions:5
  • Comments:58 (20 by maintainers)

github_iconTop GitHub Comments

8reactions
eps1loncommented, May 7, 2020

getByRole can get quite expensive in large trees since it currently checks every element while ByTestId is a simple querySelector. 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 later jsdom versions (or actual browsers) getByRole should be a lot faster.

For us: I think we should make the perf impact of hidden in ByRole clearer in the docs. Also mention too low polling rate on slow machines.

4reactions
atsikovcommented, Jan 19, 2022

For those who use styled-components a lot, such wrapper could improve getByRole performance by leaving only a few css rules used by @testing-library and thus significantly reducing <style> size

import { ReactNode } from 'react'
import { StyleSheetManager, StylisPlugin } from 'styled-components'

const ALLOWED_RULES = ['display', 'visibility', 'pointer-events']

const simplifiedStylesPlugin: StylisPlugin = (context, content) => {
  if (context === 1) {
    if (!ALLOWED_RULES.some(rule => content.toString().startsWith(`${rule}:`))) {
      return ''
    }
  }

  return undefined
}

export const withSimplifiedStyles = (component: ReactNode) => (
  <StyleSheetManager stylisPlugins={[simplifiedStylesPlugin]} disableVendorPrefixes>
    {component}
  </StyleSheetManager>
)
Read more comments on GitHub >

github_iconTop Results From Across the Web

React-testing-library getByRole is performing extremely slowly
We have noticed that our unit tests are performing very slowly and the culprit seems to be getByRole for querying for button elements...
Read more >
Kent C. Dodds on Twitter: "This should help those of you who ...
getByRole("progressbar") is pretty slow · Issue #552 · testing-library/dom-testing-library. React Testing Library version: 10.0.4 (I'm using /react not /dom ...
Read more >
Using RTL: getByRole is quite slow on simple tests - Reddit
I've been trying to expand my testing coverage on one of my React apps, and I'm running into an issue using React Testing...
Read more >
Testing React Component - Malcolm Kee
const { getByRole } = render(<Spinner delayShow={200} />);. expect(getByRole('progressbar')) ...
Read more >
react testing library - Anton Arbus
It is not good idea to make tests with real http requests, because it may cost money, slow and dependent on 3rd party...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found