react-testing-library icon indicating copy to clipboard operation
react-testing-library copied to clipboard

getByText not working for multiline text

Open sbland opened this issue 2 years ago • 2 comments

Using multiline text in getByText fails. Is there a workaround for this?

Failing test

const exampleText = `
hello

world
`

const textElement = screen.getByText(
  exampleText.slice(0, 10),
  { exact: false }
);
console.info(textElement.textContent === exampleText); // == True
expect(screen.getByText(exampleText)).toBeInTheDocument(); // == Fail

Passing test

const exampleText = `hello world`

const textElement = screen.getByText(
  exampleText.slice(0, 10),
  { exact: false }
);
console.info(textElement.textContent === exampleText); // == True
expect(screen.getByText(exampleText)).toBeInTheDocument(); // == Pass

sbland avatar Dec 07 '22 09:12 sbland

I found a workaround here: https://stackoverflow.com/questions/55509875/how-to-query-by-text-string-which-contains-html-tags-using-react-testing-library/56859650#56859650 Not sure if this is a bug or by design though.

sbland avatar Dec 07 '22 09:12 sbland

I realise I'm commenting on an old issue here but given the test would pass if provided the MatcherOptions to the getByText query I think this issue can be closed. This is documented here - https://testing-library.com/docs/queries/about#normalization

By default, normalization consists of trimming whitespace from the start and end of text, and collapsing multiple adjacent whitespace characters within the string into a single space.

and also mentioned in the test failure log for the test

Failed test code
test('can get text', () => {
  const exampleText = `
    hello

    world
  `

  render(exampleText)

  expect(screen.getByText(exampleText)).toBeInTheDocument()
})

Failed test output
    TestingLibraryElementError: Unable to find an element with the text: hello world (normalized from '
          hello

          world
        '). This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

    Ignored nodes: comments, script, style
    <body>
      <div>

          hello

          world

      </div>
    </body>

      11 |     render(exampleText)
      12 |
    > 13 |     expect(screen.getByText(exampleText)).toBeInTheDocument()
         |                   ^
      14 | })
Example passing test
test('can get text', () => {
  const exampleText = `
    hello

    world
  `

  render(exampleText)

  expect(screen.getByText(exampleText, { trim: false, collapseWhitespace: false })).toBeInTheDocument()
})

agentdylan avatar Dec 05 '23 21:12 agentdylan