1

I got a problem with my jest/chai unit test.

enter image description here

As you can see I received the same output but the test failed with message: "compared values have no visual difference". How can I fix this?

Tristan Trainer
  • 2,770
  • 2
  • 17
  • 33
  • Hi Hugo, how is the value in `arraySorted[0]` calculated? – Tristan Trainer Jan 15 '20 at 11:03
  • Can you post your actual test code? – SpoonMeiser Jan 15 '20 at 11:06
  • So parserUserData() just to sort the data. For example if i got ["lastName", "email", "phoneNumber", "adress", "XXX", "firstName"] I ll have ["firstName", "lastName", "email", "phoneNumber", "adress", "XXX"] like that it("Test", () => { let arraySorted:[string, string, string, string, string, string] = JSON.parse(parserUserData(UserData)[0]); let arrayTmp:[string, string, string, string, string, string,] = JSON.parse(["firstName", "lastName", "email", "phoneNumber", "adress", "XXX"]); console.log("test ===>", test); expect(arraySorted).to.equal(arrayTmp); }); –  Jan 15 '20 at 11:09

2 Answers2

3

This is common in javascript. As you probably know already, an array is an object, so I would be explaining using objects.

TLDR: Variable assigned to an object is only a pointer to such value in memory. Hence it is impossible for two variables despite having the different objects containing the same PHYSICAL value but not referring to the same address in memory to be equal.

Javascript compares Objects by identity which means that for the case of the objects a and b below: Example 1:

a = {name: 'tolumide'}

b = {name: 'tolumide'} 

a === b // False
a !== b //True

Although a and b have the same content, there identity differs hence => a !== b //True

However, this is different from example 2 below: Example 2:

c = {name: 'tolumide'}
c = d
c === d // True
c !== d // False

This is because c and d refer to the same value in memory.

What you need is for testing in jest would be something like this:

const expected = ['Alice', 'Bob', 'Eve']
expect.arrayContaining(array)
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));

OR 
const shoppingList = ['beer', 'whiskey']
expect(shoppingList).toContain('beer');

Jest source

Tolumide
  • 944
  • 9
  • 11
  • I thought this too initially, however it seems that jest's `toEqual` performs comparisons on the object values, rather than the reference to memory. there is a `toBe` method that compares the references. – Tristan Trainer Jan 15 '20 at 11:12
  • Ok that's nice I understand very well the problem currently! If I use typescript and type the array could I fix the problem like this or must I found an other solution? –  Jan 15 '20 at 11:19
  • 1
    Typescript would not change anything about the object comparison. So what you need is a way to compare the contents of your array using jest. I mentioned some in my solution and you might want to checkout [Jest's documentation](https://jestjs.io/docs/en/using-matchers) too on how it compares objects and arrays – Tolumide Jan 15 '20 at 11:21
0

Forgive me if I state anything you already know, but the issue appears to be in the underlying object comparison performed by jest.

Array's in javascript are just objects with numbered properties, i.e.

{
   0: "value at first index",
   1: "value at second index"
}

As such the comparison is done on this underlying object. According to this issue raised by someone on the jest github page, it is possible that the function you are using to create the sorted array is returning a none standard array back, so the comparison fails on the underlying object.

Similar looking issue: https://github.com/facebook/jest/issues/5998

The solution suggested by one commenter is to Json.Stringify() each array in the test and perform a comparison on that, as this will compare the values themselves.

This is however, as stated "A work around not a fix".

Edit The stringify option does not work in all cases and should be avoided.

The complete solution for testing if two arrays are equal is found in the first answer to this question: How to check if two arrays are equal with JavaScript?

Disclaimer: Not my code!

function arraysEqual(a, b) {
  if (a === b) return true;
  if (a == null || b == null) return false;
  if (a.length != b.length) return false;

  // If you don't care about the order of the elements inside
  // the array (i.e. [1, 2, 3] == [3, 2, 1]), you should sort both arrays here.
  // Please note that calling sort on an array will modify that array.
  // you might want to clone your array first.

  for (var i = 0; i < a.length; ++i) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}
Tristan Trainer
  • 2,770
  • 2
  • 17
  • 33
  • That's great I totaly understand! I found it very normal so and I gonna try some stuff to fix it ! Thx so much! –  Jan 15 '20 at 11:21