Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

toBeCloseTo equivalent for recursive equality test in Jest

I have two objects and I want to test a recursive equality using Jest. This is pretty simple:

test('should be recursively equal', () => {
  const test = { x: 0, y: 0 }
  const expected = { x: 0, y: 0 }

  expect(test).toEqual(expected)
})

But there is a problem in some cases; as you know, JavaScript is pretty bad to compute float numbers, so sometimes the test becomes the following:

test('should be recursively equal', () => {
  const test = { x: 0.00000000001, y: 0 }
  const expected = { x: 0, y: 0 }

  expect(test).toEqual(expected)
})

And it does not work anymore. Jest provides the toBeCloseTo test, which takes a number and a precision as parameters, but I would like to know if there is an equivalent for recursive equalities (something like toEqualCloseTo).

like image 913
Anthony Dugois Avatar asked Dec 09 '16 12:12

Anthony Dugois


People also ask

What matchers are used to test a value with exact equality?

Common Matchers​ The simplest way to test a value is with exact equality. expect(2 + 2).toBe(4); }); In this code, expect(2 + 2) returns an "expectation" object.

What's the difference between the toBe and toEqual matchers in Jest?

toBe compares primitive values or checks referential identity of object instances while toEqual looks for deep equailty.

How do you match an array in Jest?

If you want to compare two arrays in JEST use the bellow model. Be careful as this - as the name suggests - checks if the array contains the items in the other array. The test will pass if you check if expect(['a','b']). toEqual(expect.

How do you match objects in Jest?

With Jest's Object partial matching we can do: test('id should match', () => { const obj = { id: '111', productName: 'Jest Handbook', url: 'https://jesthandbook.com' }; expect(obj). toEqual( expect. objectContaining({ id: '111' }) ); });


1 Answers

I ended up with the following solution:

expect.extend({
  toEqualCloseTo(received, expected, precision = 3) {
    const { getType } = this.utils

    function round(obj) {
      switch (getType(obj)) {
      case 'array':
        return obj.map(round)

      case 'object':
        return Object.keys(obj).reduce((acc, key) => {
          acc[key] = round(obj[key])
          return acc
        }, {})

      case 'number':
        return +obj.toFixed(precision)

      default:
        return obj
      }
    }

    expect(round(received)).toEqual(expected)

    return { pass: true }
  },
})
like image 198
Anthony Dugois Avatar answered Oct 31 '22 18:10

Anthony Dugois