Let's say I have a custom function, that I expect will return a NodeList:
getNodeList('foo');
I expect this NodeList to be the same NodeList returned from:
document.querySelectorAll('.foo');
How can I check that my expectations are correct?
Doing this does not work:
getNodeList('foo') == document.querySelectorAll('.foo')
I'm sure there's a good technical reason why this doesn't work, since document.querySelectorAll('.foo') == document.querySelectorAll('.foo')
also does not work, I take it that this is expected.
How can I test whether two NodeLists contain the same HTML nodes?
Array equality is made by reference, not by contents.
let a = [1, 2, 3], b = [1, 2, 3]
let c = a
a == c // => true, since both refer to `a`
a == b // => false
If you want to compare two array-like objects you have to compare by index.
function eq(A, B) {
if (A.length !== B.length) return false;
for (let i = 0; i < A.length; i++) {
if (A[i] !== B[i]) return false;
}
return true;
}
Of course you could always use some functional programming magic:
let arrayEq = (A, B) => A.length === B.length && A.every((e, i) => e === B[i]);
But it will only work if A is an array (not a NodeList).
Then try
eq(getNodeList('foo'), document.querySelectorAll('.foo'))
or
arrayEq(Array.from(getNodeList('foo')), Array.from(document.querySelectorAll('.foo'))
What you have so far seems ok, but it is inefficient (you'll be recomputing document.querySelectorAll(...)
and indexOf
possibly many times).
There is also a bug: if the querySelectorAll
returns more elements than the first node list, but they are otherwise equal, your function will return true
.
You can also simplify the comparisons further:
function nodeListsAreEqual( list1, list2 ) {
if ( list1.length !== list2.length ) {
return false;
}
return Array.from( list1 ).every( ( node, index ) => node === list2[ index ] );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With