From bcaa1463abf3f5488f30d0ce602c5911cca7b999 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 26 Feb 2019 00:39:20 +0100 Subject: [PATCH] Fix asymmetric equal for Number (#7948) * Fix asymmetric equal for Number * Update CHANGELOG * Handle the case of a being a new Number * Use Object.is for Number equality * Add unit tests related to issues/7941 * Add extra units for equality * Remove unnecessary comment in eq --- CHANGELOG.md | 1 + .../__snapshots__/matchers.test.js.snap | 49 +++++++++++++++++++ .../expect/src/__tests__/matchers.test.js | 11 +++++ packages/expect/src/jasmineUtils.ts | 4 +- 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ff03985fa81..af04a394f8f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - `[jest-cli]` Refactor `-o` and `--coverage` combined ([#7611](https://github.com/facebook/jest/pull/7611)) - `[expect]` Fix custom async matcher stack trace ([#7652](https://github.com/facebook/jest/pull/7652)) - `[expect]` Fix `toStrictEqual` not considering arrays with objects having undefined values correctly ([#7938](https://github.com/facebook/jest/pull/7938)) +- `[expect]` Fix non-symmetric equal for Number ([#7948](https://github.com/facebook/jest/pull/7948)) - `[jest-changed-files]` Improve default file selection for Mercurial repos ([#7880](https://github.com/facebook/jest/pull/7880)) - `[jest-validate]` Fix validating async functions ([#7894](https://github.com/facebook/jest/issues/7894)) - `[jest-circus]` Fix bug with test.only ([#7888](https://github.com/facebook/jest/pull/7888)) diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index 8e07feaf3198..d576cdbad479 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -1818,6 +1818,13 @@ Expected: \\"abc\\" Received: \\"abc\\"" `; +exports[`.toEqual() {pass: false} expect("abc").not.toEqual({"0": "a", "1": "b", "2": "c"}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected: {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"} +Received: \\"abc\\"" +`; + exports[`.toEqual() {pass: false} expect("abcd").not.toEqual(StringContaining "bc") 1`] = ` "expect(received).not.toEqual(expected) @@ -1931,6 +1938,13 @@ Expected: Any Received: [Function anonymous]" `; +exports[`.toEqual() {pass: false} expect({"0": "a", "1": "b", "2": "c"}).not.toEqual("abc") 1`] = ` +"expect(received).not.toEqual(expected) + +Expected: \\"abc\\" +Received: {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"}" +`; + exports[`.toEqual() {pass: false} expect({"a": 1, "b": [Function b], "c": true}).not.toEqual({"a": 1, "b": Any, "c": Anything}) 1`] = ` "expect(received).not.toEqual(expected) @@ -2006,6 +2020,20 @@ Expected: {} Received: {}" `; +exports[`.toEqual() {pass: false} expect({}).not.toEqual(0) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected: 0 +Received: {}" +`; + +exports[`.toEqual() {pass: false} expect(0).not.toEqual({}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected: {} +Received: 0" +`; + exports[`.toEqual() {pass: false} expect(0).toEqual(-0) 1`] = ` "expect(received).toEqual(expected) @@ -2013,6 +2041,13 @@ Expected: -0 Received: 0" `; +exports[`.toEqual() {pass: false} expect(0).toEqual(5e-324) 1`] = ` +"expect(received).toEqual(expected) + +Expected: 5e-324 +Received: 0" +`; + exports[`.toEqual() {pass: false} expect(1).not.toEqual(1) 1`] = ` "expect(received).not.toEqual(expected) @@ -2034,6 +2069,13 @@ Expected: ArrayContaining [1, 2] Received: 1" `; +exports[`.toEqual() {pass: false} expect(5e-324).toEqual(0) 1`] = ` +"expect(received).toEqual(expected) + +Expected: 0 +Received: 5e-324" +`; + exports[`.toEqual() {pass: false} expect(Immutable.List [1, 2]).not.toEqual(Immutable.List [1, 2]) 1`] = ` "expect(received).not.toEqual(expected) @@ -2394,6 +2436,13 @@ Expected: Map {2 => [\\"two\\"], 1 => [\\"one\\"]} Received: Map {1 => [\\"one\\"], 2 => [\\"two\\"]}" `; +exports[`.toEqual() {pass: false} expect(NaN).not.toEqual(NaN) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected: NaN +Received: NaN" +`; + exports[`.toEqual() {pass: false} expect(Set {[1], [2], [3], [3]}).not.toEqual(Set {[3], [3], [2], [1]}) 1`] = ` "expect(received).not.toEqual(expected) diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index 89435ff47c1d..4e2cf535b6b3 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -344,6 +344,8 @@ describe('.toEqual()', () => { [true, false], [1, 2], [0, -0], + [0, Number.MIN_VALUE], // issues/7941 + [Number.MIN_VALUE, 0], [{a: 5}, {b: 6}], ['banana', 'apple'], [null, undefined], @@ -426,7 +428,16 @@ describe('.toEqual()', () => { [ [true, true], [1, 1], + [NaN, NaN], + // eslint-disable-next-line no-new-wrappers + [0, new Number(0)], + // eslint-disable-next-line no-new-wrappers + [new Number(0), 0], ['abc', 'abc'], + // eslint-disable-next-line no-new-wrappers + [new String('abc'), 'abc'], + // eslint-disable-next-line no-new-wrappers + ['abc', new String('abc')], [[1], [1]], [[1, 2], [1, 2]], [Immutable.List([1]), Immutable.List([1])], diff --git a/packages/expect/src/jasmineUtils.ts b/packages/expect/src/jasmineUtils.ts index f9945dbf64df..11e368d11001 100644 --- a/packages/expect/src/jasmineUtils.ts +++ b/packages/expect/src/jasmineUtils.ts @@ -106,9 +106,7 @@ function eq( // $FlowFixMe – Flow sees `a` as a number return a == String(b); case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - return a != +a ? b != +b : a === 0 ? 1 / a == 1 / b : a == +b; + return Object.is(Number(a), Number(b)); case '[object Date]': case '[object Boolean]': // Coerce dates and booleans to numeric primitive values. Dates are compared by their