I have the following test:
getByText(fixture.nativeElement, text);
I get the error:
node.matches is not a function
After debugging, I found that the problem is in the following line:
return Array.from([...baseArray, ...container.querySelectorAll(selector)])
.filter(node => !ignore || !node.matches(ignore))
.filter(node => matcher(getNodeText(node), node, text, matchNormalizer))
One of the nodes is a NodeList, and therefore we get the error.
Will be fixed by https://github.com/kentcdodds/dom-testing-library/pull/213
EDIT: Maybe? Waiting confirmation for that.
EDIT2: No, will not be fixed by #213. This is likely caused by #109 way further down in history where the node.matches line was first added
Oh wait, does the error come from node.matches? My error came from container.matches right above the code lines you pasted.
I'll see if #213 indeed fixes it or not. Can you try that branch to see if it resolves your issue?
Yes, node.matches don't exist on NodeList.
Ok, I'll see if I can amend #213 to fix this, too
Thanks.
I'm not actually sure what your fixture.nativeElement refers to. Can you tell a bit more about your test case that is breaking, and show a little bit more code?
Is it some kind of angular test? I found this by googling "fixture.nativeElement" https://angular.io/guide/testing#nativeelement
Could you try downloading this to your repository root: https://gist.github.com/valscion/c268bbc28f9605ae1366978341a2fcf5/raw/3906daac57118f38a9d4d49d2dbc9d075009eae9/dom-testing-library-3.16.6.tgz
And then change your package.json to refer to that package instead of a version for dom-testing-library:
"devDependencies": {
- "dom-testing-library": "^3.0.0",
+ "dom-testing-library": "file:dom-testing-library-3.16.6.tgz",
Then run npm install or yarn install, whichever you're using, and check if your issue is still there? If it is not, it means that #213 will fix your issue. If not, I'd like to know, as that would mean #213 is incomplete
Yes, it's Angular, but it's a standard DOM element.
No, it doesn't fix it. The problem is the node, not the container.
Did it work before version 3.16.6? Can you try 3.16.5?
It might be caused by https://github.com/kentcdodds/dom-testing-library/pull/109 that was first released in v3.7.0. Can you try 3.6.0, if possible, to see if your issue goes away?
I understand it might not be possible to downgrade that long back to history and make all your tests pass, but maybe this specific case would be fixed by that?
From the first look, it seems like it does solve the issue.
Leaving only the following line in the source code, solve the issue:
return Array.from(container.querySelectorAll(selector))
.filter(node => !ignore || !node.matches(ignore))
From the first look, it seems like it does solve the issue.
Which one of the versions fixes the issue? Version 3.16.5 or version 3.6.0? Or both?
Leaving only the following line in the source code, solve the issue:
So it seems that there is something inside baseArray which are not things you can call node.matches on?
So it does seem to be a regression caused by #209 after all.
3.6.0
So it seems that there is something inside
baseArraywhich are not things you can callnode.matcheson?
Correct. A NodeList type.
I'm confused... in v3.16.5, it only had the container.querySelectorAll line, and baseArray was added in v3.16.6 as part of #209.

So v3.16.5 should work for you, but for some reason it doesn't?
Sorry, my mistake. v3.16.5, the version without the baseArray.
Right.
Ok. That would mean #213 is indeed only half way there, and I will need to come up with a test case that shows it will break for some specific input. Hmm...
So in your case, the container.matches line works because the container is a real DOM element and not document, like it is in Cypress.
Hmm. So spreading the ...baseArray and ...container.querySelectorAll(selector) together somehow ends up passing NodeList to the filter step.
Yes.
Thanks :relaxed:. This should allow me to figure out a way to fix your use case, too.
I have a really hard time reproducing this with the existing Jest tests.
You said that:
Leaving only the following line in the source code, solve the issue:
return Array.from(container.querySelectorAll(selector)) .filter(node => !ignore || !node.matches(ignore))
I have a really hard time figuring out why this works for you. Basically the following would break for you:
return Array.from([...[container], ...container.querySelectorAll(selector)])
.filter(node => !ignore || !node.matches(ignore))
What's strange is that we have this situation _only if typeof container.matches is a function_. And if that method is a function, it should be perfectly fine to call node.matches for the container inside the .filter line!
In case typeof container.matches would _not_ be a function, the code would evaluate to this:
return Array.from([...[], ...container.querySelectorAll(selector)])
.filter(node => !ignore || !node.matches(ignore))
...which should be functionally equivalent to your working code:
return Array.from(container.querySelectorAll(selector)) .filter(node => !ignore || !node.matches(ignore))
Are you _really sure_ you tested the version built from #213 as I commented in https://github.com/kentcdodds/dom-testing-library/issues/215#issuecomment-463588264 ? @NetanelBasal
I didn't test the entire library version. I took from the version the specific code I needed.
I can tell you for sure that somehow one of the nodes is a NodeList. I will help to debug it on Sunday.
Try v3.16.7, it might work
I also ran into this issue today where one of the nodes was a NodeList and I was running v3.16.7 of this library. I have two environments where I run tests using react-testing-library and it works on one but not the other:
:heavy_check_mark: Jest 24.1.0
:x: In a storybook docs build using the specs addon running in Chrome (both 72.0.3626.109 stable and 72.0.3626.96 beta)
This might make it trickier to reproduce. Downgrading to v3.16.5 appears to fix the issue.
If you need any more details or want me to help test out any solutions in my environment let me know. Unfortunately I can't make my project public.
@lavigneer did you also test v3.16.7 or were you on v3.16.6?
@lavigneer did you also test v3.16.7 or were you on v3.16.6?
I was using v3.16.7 when I was seeing this issue
Ok thanks for the confirmation.
Can you check from the debugger whether
Array.from([...container.querySelectorAll(selector)])
has something which is a NodeList?
Or if the NodeList is in this array instead?
Array.from([...baseArray])
Set the debugger on the return line where it says return Array.from(
@valscion I added the debugger statement and checked the values and it looks like container.querySelectorAll(selector) returns a NodeList. The selector value is '*'.
Just as an fyi, my project resolves to using the dist/dom-testing-library.esm.js file. I also confirmed that the package.json of the module in my node_modules does in fact list v3.16.7 as the version just to make sure there wasn't some weird yarn resolution thing going on.
Yes I know container.querySelectorAll(selector) returns a NodeList, but is some element in this array a NodeList, too?
Array.from([...container.querySelectorAll(selector)])
[...container.querySelectorAll(selector)] should convert the NodeList to the actual elements, as that should be functionally equivalent to [...Array.from(container.querySelectorAll(selector))]. Unless I'm mistaken about how array spread operator works on an Iterable.
No, there aren't any elements in that NodeList that are also a NodeList
I just tested wrapping container.querySelectorAll(selector) explicitly in an Array.from call in the built .esm bundle and that appeared to resolve the issue.
The transpilation of
Array.from([...baseArray, ...container.querySelectorAll(selector)])
results in
Array.from([].concat(baseArray, container.querySelectorAll(selector)))
so it's not converting the NodeList to an array and is just trying to concat it directly
Oh! I wonder if kcd-scripts is transpiling in loose mode and causing the array spread to result in non-spec behavior? @kentcdodds here's the issue, I think
Why don't we just change it to:
[...baseArray, ...Array.from(container.querySelectorAll(selector))]
?
Yup it could work.
I wonder why I couldn't come up with a test case that would break. Maybe the transpilation is not happening with the tests?
I wonder if it would be useful to try to setup the tests to run against compiled output
I wonder if it would be useful to try to setup the tests to run against compiled output
I'm sure it could have caught this, but the risk of this happening is very low (rarely happens) and the cost of doing that would be pretty high so it's not worth it IMO.
Yeah true. Why are the compiled output running in loose mode, though? Does it help performance somehow?
Anyway. I'll create a fix for this
:tada: This issue has been resolved in version 3.16.8 :tada:
The release is available on:
npm package (@latest dist-tag)Your semantic-release bot :package::rocket: