Skip to content

Create a specification for getNodeText used by queries #473

Open
@NicholasBoll

Description

@NicholasBoll

Describe the feature you'd like:

I've seen churn on what "text" means for a given element. The pendulum has swung from innerText to textContent based off unexpected use-cases. I think we should create a specification for what getNodeText returns for the queries that rely on it.

Effected queries:

  • *ByTitle
  • *ByText
  • *ByDisplayValue

I think *ByLabelText used to use it, but it is no longer.

Some examples that aren't working as expected.

Nested inline elements

This example is probably more common for Cypress, Puppeteer, etc. For example, Cypress implicitly waits for actionability. If a button is disabled and the test calls cy.findByText('Hello').click(), Cypress will not wait for the disabled to be removed from the button element. There is no workaround other than not using findByText at all. Adding a selector should define what element we want to return, but getNodeText won't be able to find anything.

<button><span>Hello</span></button>
<script>
  getByText('Hello') // returns span
  getByText('Hello', { selector: 'button' }) // error - not found
  // expected: `button` element
</script>
<th>
  Country
  <!-- Country Filter for the table header -->
  <select>
    <option>Colombia</option>
  </select>
</th>
<script>
  getByText('Country') // returns th
  // expected: `th` element
</script>

Inconsistencies with *ByLabelText

<label for="1234">My Label<abbr>*</abbr></label>
<input id="1234">
<script>
  getByText('My Label'); // returns <label>
  getByLabelText('My Label'); // Error: Unable to find a label with the text of: My Label
  getByText('My Label*'); // Error: Unable to find an element with the text: My Label*. This could be because the text is broken up by multiple elements. In ...
  getByLabelText('My Label*'); // returns <input>
</script>

There are probably other edge cases we can build a specification around.

This would be a breaking change for existing implementations that rely on the current functionality. For example:

<button><span>Hello</span></button>
<script>
  getByText('Hello') // error, 2 elements found. Before, only span was returned
  getAllByText('Hello') // [button, span]. Before, only [span] was returned
  getByText('Hello', { selector: 'span' }) // span
  getByText('Hello', { selector: 'button' }) // button
</script>

Suggested implementation:

Write specifications for what should be returned given a few different DOM structures.

Describe alternatives you've considered:

I've looked through some of the history around the implementation of the getNodeText function. It seems edge cases have driven the implementation, but there isn't much conditional coding to handle multiple edge cases at once.

Teachability, Documentation, Adoption, Migration Strategy:

Hopefully this feature doesn't require much documentation as it will mostly do what one would expect. Edge cases could be enumerated in the documentation, however. Something like:

getByText tries to grab elements by most likely text of an element. For example, a button element with nested span elements will return the whole text of the button, spans included. getByText also tries to filter out unintended text. For example, a table header that contains a select element will remove the text of the select element itself as that is most likely the intent of selecting the table's header text.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions