Unexpected behavior of `getNodeText`
-
@testing-library/domversion: 7.28.1 - Testing Framework and version: Jest 26.6.3
- DOM Environment: jsdom 16.4.0
Relevant code or config:
const div = document.createElement('div');
div.innerHTML = 'Hello, <span>world</span>!';
expect(getNodeText(div)).toBe('Hello, world!');
What you did:
See above
What happened:
Expected: "Hello, world!"
Received: "Hello, !"
Problem description:
The docs for the getNodeText helper function state (emphasis added):
Returns the complete text content of an HTML element, removing any extra whitespace. The intention is to treat text in nodes exactly as how it is perceived by users in a browser, where any extra whitespace within words in the html code is not meaningful when the text is rendered.
That intention is in-line with the library's overall design goals, but it doesn't seem to match the current implementation.
Based on the description, I expected the function to return all text content of the node and its descendants (a la innerText). Given the following markup:
<div>Hello, <span>world</span>!</div>
A user would likely perceive the text "Hello, world!"
However, the current implementation only considers text nodes which are children of the input node. For the example markup, it returns "Hello, !"
Suggested solution:
As issues like gh-750 demonstrate, it's difficult to confidently say what a user will perceive when presented with text spread across many elements. It might be that this is too nuanced of a concept to expose as a general-purpose API, but I doubt it. For instance, we could observe screen reader semantics--that heuristic is probably imperfect, too, but its real-world usage makes the imperfection meaningful in a way that the current limitations of getNodeText is not.
In any event, thanks for the excellent library!
Would be also useful for debugging large elements if we could have a print of the text only. Currently I'm relying on jquery:
$('[data-testid="my-component"]').text()
@jugglinmike Check if the name option in queries is any helpful. It uses the computeAccessibleName from dom-accessibility-api.
Unfortunately it doesn't seem to be perfect either and it cannot be used for all elements:
const button = document.createElement('button');
button.innerHTML = 'Hello, <span>world</span>!';
expect(computeAccessibleName(button)).toBe('Hello, world!');
Expected: "Hello, world!"
Received: "Hello, world !"
I just stumbled upon this issue myself. I created the following sandbox to show case the issue. The test fail, because the text content returned is an empty string ("") instead of the expected text, "Click me!".
It looks like this is because we only look at nodes having a node type of 3, which buttons don't have.
The same issue is here:
The code looks like:
const text = getNodeText(el);
const dom = prettyDOM(el);
console.log('TEST LOG text', text);
console.log('TEST LOG dom', dom);
The output:
console.log
TEST LOG text
console.log
TEST LOG dom
<td>
<span>
0
<br />
<b>
100%
</b>
</span>
</td>