Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I test the equality of two NodeLists?

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?

like image 978
ESR Avatar asked Dec 24 '22 04:12

ESR


2 Answers

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'))
like image 170
mauroc8 Avatar answered Dec 31 '22 14:12

mauroc8


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 ] );
}
like image 33
We Are All Monica Avatar answered Dec 31 '22 14:12

We Are All Monica