diff --git a/CHANGELOG.md b/CHANGELOG.md index 30ed31b65ec4..13b6d23aad45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - `[expect]` Improve report when matcher fails, part 15 ([#8281](https://github.com/facebook/jest/pull/8281)) +- `[expect]` Improve report when matcher fails, part 16 ([#8306](https://github.com/facebook/jest/pull/8306)) - `[jest-runner]` Pass docblock pragmas to TestEnvironment constructor ([#8320](https://github.com/facebook/jest/pull/8320)) ### Fixes diff --git a/e2e/__tests__/__snapshots__/failures.test.ts.snap b/e2e/__tests__/__snapshots__/failures.test.ts.snap index 39f7e80eb37d..dad936e44a6f 100644 --- a/e2e/__tests__/__snapshots__/failures.test.ts.snap +++ b/e2e/__tests__/__snapshots__/failures.test.ts.snap @@ -260,7 +260,7 @@ FAIL __tests__/testMacro.test.js ● use some imported macro to make assertion - expect(received).toEqual(expected) + expect(received).toEqual(expected) // deep equality Expected: 2 Received: 1 @@ -286,9 +286,7 @@ FAIL __tests__/asyncFailures.test.js ● resolve, but fail - expect(received).toEqual(expected) - - Difference: + expect(received).resolves.toEqual(expected) // deep equality - Expected + Received @@ -310,9 +308,7 @@ FAIL __tests__/asyncFailures.test.js ● reject, but fail - expect(received).toEqual(expected) - - Difference: + expect(received).rejects.toEqual(expected) // deep equality - Expected + Received diff --git a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap index fa8c8daae7bc..4705aef06b68 100644 --- a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap @@ -1,9 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`defines asymmetric unary matchers 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -15,9 +13,7 @@ Difference: `; exports[`defines asymmetric unary matchers that can be prefixed by not 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -29,9 +25,7 @@ Difference: `; exports[`defines asymmetric variadic matchers 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -43,9 +37,7 @@ Difference: `; exports[`defines asymmetric variadic matchers that can be prefixed by not 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index 196f8238cc5b..e74042085cc7 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -325,7 +325,7 @@ exports[`.toBe() fails for: [] and [] 1`] = ` If it should pass with deep equality, replace \\"toBe\\" with \\"toStrictEqual\\" Expected: [] -Received value has no visual difference" +Received: serializes to the same string" `; exports[`.toBe() fails for: [Error: received] and [Error: expected] 1`] = ` @@ -339,7 +339,7 @@ exports[`.toBe() fails for: [Function anonymous] and [Function anonymous] 1`] = "expect(received).toBe(expected) // Object.is equality Expected: [Function anonymous] -Received value has no visual difference" +Received: serializes to the same string" `; exports[`.toBe() fails for: {"a": [Function a], "b": 2} and {"a": Any, "b": 2} 1`] = ` @@ -363,7 +363,7 @@ exports[`.toBe() fails for: {"a": 1} and {"a": 1} 1`] = ` If it should pass with deep equality, replace \\"toBe\\" with \\"toStrictEqual\\" Expected: {\\"a\\": 1} -Received value has no visual difference" +Received: serializes to the same string" `; exports[`.toBe() fails for: {"a": 1} and {"a": 5} 1`] = ` @@ -398,7 +398,7 @@ exports[`.toBe() fails for: {} and {} 1`] = ` If it should pass with deep equality, replace \\"toBe\\" with \\"toStrictEqual\\" Expected: {} -Received value has no visual difference" +Received: serializes to the same string" `; exports[`.toBe() fails for: -0 and 0 1`] = ` @@ -421,7 +421,7 @@ exports[`.toBe() fails for: 2020-02-20T00:00:00.000Z and 2020-02-20T00:00:00.000 If it should pass with deep equality, replace \\"toBe\\" with \\"toStrictEqual\\" Expected: 2020-02-20T00:00:00.000Z -Received value has no visual difference" +Received: serializes to the same string" `; exports[`.toBe() fails for: 2020-02-21T00:00:00.000Z and 2020-02-20T00:00:00.000Z 1`] = ` @@ -1892,42 +1892,35 @@ Received has value: null" `; exports[`.toEqual() {pass: false} expect("Eve").toEqual({"asymmetricMatch": [Function asymmetricMatch]}) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: {\\"asymmetricMatch\\": [Function asymmetricMatch]} Received: \\"Eve\\"" `; exports[`.toEqual() {pass: false} expect("abd").toEqual(StringContaining "bc") 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: StringContaining \\"bc\\" Received: \\"abd\\"" `; exports[`.toEqual() {pass: false} expect("abd").toEqual(StringMatching /bc/i) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: StringMatching /bc/i Received: \\"abd\\"" `; exports[`.toEqual() {pass: false} expect("banana").toEqual("apple") 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality -Difference: - -- Expected -+ Received - -- apple -+ banana" +Expected: \\"apple\\" +Received: \\"banana\\"" `; exports[`.toEqual() {pass: false} expect([1, 2]).toEqual([2, 1]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -1940,25 +1933,14 @@ Difference: `; exports[`.toEqual() {pass: false} expect([1, 3]).toEqual(ArrayContaining [1, 2]) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality -Difference: - -- Expected -+ Received - -- ArrayContaining [ -+ Array [ - 1, -- 2, -+ 3, - ]" +Expected: ArrayContaining [1, 2] +Received: [1, 3]" `; exports[`.toEqual() {pass: false} expect([1]).toEqual([2]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -1970,9 +1952,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect({"a": 1, "b": 2}).toEqual(ObjectContaining {"a": 2}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -1986,9 +1966,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect({"a": 1}).toEqual({"a": 2}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2000,9 +1978,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect({"a": 5}).toEqual({"b": 6}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2014,9 +1990,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect({"nodeName": "div", "nodeType": 1}).toEqual({"nodeName": "p", "nodeType": 1}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2029,9 +2003,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect({"target": {"nodeType": 1, "value": "a"}}).toEqual({"target": {"nodeType": 1, "value": "b"}}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2046,44 +2018,42 @@ Difference: `; exports[`.toEqual() {pass: false} expect(0).toEqual(-0) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: -0 Received: 0" `; exports[`.toEqual() {pass: false} expect(0).toEqual(5e-324) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: 5e-324 Received: 0" `; exports[`.toEqual() {pass: false} expect(1).toEqual(2) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: 2 Received: 1" `; exports[`.toEqual() {pass: false} expect(1).toEqual(ArrayContaining [1, 2]) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: ArrayContaining [1, 2] Received: 1" `; exports[`.toEqual() {pass: false} expect(5e-324).toEqual(0) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: 0 Received: 5e-324" `; exports[`.toEqual() {pass: false} expect(Immutable.List [1, 2]).toEqual(Immutable.List [2, 1]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2096,9 +2066,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.List [1]).toEqual(Immutable.List [2]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2110,9 +2078,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.Map {"1": Immutable.Map {"2": {"a": 99}}}).toEqual(Immutable.Map {"1": Immutable.Map {"2": {"a": 11}}}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2128,9 +2094,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.Map {"a": 0}).toEqual(Immutable.Map {"b": 0}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2142,9 +2106,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.Map {"v": 1}).toEqual(Immutable.Map {"v": 2}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2156,9 +2118,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.OrderedMap {1: "one", 2: "two"}).toEqual(Immutable.OrderedMap {2: "two", 1: "one"}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2171,9 +2131,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.OrderedSet [1, 2]).toEqual(Immutable.OrderedSet [2, 1]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2186,9 +2144,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.Set [1, 2]).toEqual(Immutable.Set []) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2201,9 +2157,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Immutable.Set [1, 2]).toEqual(Immutable.Set [1, 2, 3]) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2216,9 +2170,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Map {"a" => 0}).toEqual(Map {"b" => 0}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2230,9 +2182,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Map {"v" => 1}).toEqual(Map {"v" => 2}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2244,9 +2194,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Map {["v"] => 1}).toEqual(Map {["v"] => 2}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2260,9 +2208,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Map {[1] => Map {[1] => "one"}}).toEqual(Map {[1] => Map {[1] => "two"}}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2280,16 +2226,14 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Map {}).toEqual(Set {}) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: Set {} Received: Map {}" `; exports[`.toEqual() {pass: false} expect(Map {1 => "one", 2 => "two"}).toEqual(Map {1 => "one"}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2301,9 +2245,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [2]}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2321,9 +2263,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [3]}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2341,9 +2281,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Set {1, 2}).toEqual(Set {}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2356,9 +2294,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Set {1, 2}).toEqual(Set {1, 2, 3}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2371,9 +2307,7 @@ Difference: `; exports[`.toEqual() {pass: false} expect(Set {Set {1}, Set {2}}).toEqual(Set {Set {1}, Set {3}}) 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received @@ -2390,374 +2324,374 @@ Difference: `; exports[`.toEqual() {pass: false} expect(false).toEqual(ObjectContaining {"a": 2}) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: ObjectContaining {\\"a\\": 2} Received: false" `; exports[`.toEqual() {pass: false} expect(null).toEqual(undefined) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: undefined Received: null" `; exports[`.toEqual() {pass: false} expect(true).toEqual(false) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: false Received: true" `; exports[`.toEqual() {pass: false} expect(undefined).toEqual(Any) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: Any Received: undefined" `; exports[`.toEqual() {pass: false} expect(undefined).toEqual(Anything) 1`] = ` -"expect(received).toEqual(expected) +"expect(received).toEqual(expected) // deep equality Expected: Anything Received: undefined" `; exports[`.toEqual() {pass: true} expect("Alice").not.toEqual({"asymmetricMatch": [Function asymmetricMatch]}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {\\"asymmetricMatch\\": [Function asymmetricMatch]} -Received: \\"Alice\\"" +Expected: not {\\"asymmetricMatch\\": [Function asymmetricMatch]} +Received: \\"Alice\\"" `; exports[`.toEqual() {pass: true} expect("abc").not.toEqual("abc") 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: \\"abc\\" -Received: \\"abc\\"" +Expected: not \\"abc\\" +" `; exports[`.toEqual() {pass: true} expect("abc").not.toEqual({"0": "a", "1": "b", "2": "c"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"} -Received: \\"abc\\"" +Expected: not {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"} +Received: \\"abc\\"" `; exports[`.toEqual() {pass: true} expect("abcd").not.toEqual(StringContaining "bc") 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: StringContaining \\"bc\\" -Received: \\"abcd\\"" +Expected: not StringContaining \\"bc\\" +Received: \\"abcd\\"" `; exports[`.toEqual() {pass: true} expect("abcd").not.toEqual(StringMatching /bc/) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: StringMatching /bc/ -Received: \\"abcd\\"" +Expected: not StringMatching /bc/ +Received: \\"abcd\\"" `; exports[`.toEqual() {pass: true} expect([1, 2, 3]).not.toEqual(ArrayContaining [2, 3]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: ArrayContaining [2, 3] -Received: [1, 2, 3]" +Expected: not ArrayContaining [2, 3] +Received: [1, 2, 3]" `; exports[`.toEqual() {pass: true} expect([1, 2]).not.toEqual([1, 2]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: [1, 2] -Received: [1, 2]" +Expected: not [1, 2] +" `; exports[`.toEqual() {pass: true} expect([1]).not.toEqual([1]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: [1] -Received: [1]" +Expected: not [1] +" `; exports[`.toEqual() {pass: true} expect([Function anonymous]).not.toEqual(Any) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Any -Received: [Function anonymous]" +Expected: not Any +Received: [Function anonymous]" `; exports[`.toEqual() {pass: true} expect({"0": "a", "1": "b", "2": "c"}).not.toEqual("abc") 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: \\"abc\\" -Received: {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"}" +Expected: not \\"abc\\" +Received: {\\"0\\": \\"a\\", \\"1\\": \\"b\\", \\"2\\": \\"c\\"}" `; exports[`.toEqual() {pass: true} expect({"a": 1, "b": [Function b], "c": true}).not.toEqual({"a": 1, "b": Any, "c": Anything}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {\\"a\\": 1, \\"b\\": Any, \\"c\\": Anything} -Received: {\\"a\\": 1, \\"b\\": [Function b], \\"c\\": true}" +Expected: not {\\"a\\": 1, \\"b\\": Any, \\"c\\": Anything} +Received: {\\"a\\": 1, \\"b\\": [Function b], \\"c\\": true}" `; exports[`.toEqual() {pass: true} expect({"a": 1, "b": 2}).not.toEqual(ObjectContaining {"a": 1}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: ObjectContaining {\\"a\\": 1} -Received: {\\"a\\": 1, \\"b\\": 2}" +Expected: not ObjectContaining {\\"a\\": 1} +Received: {\\"a\\": 1, \\"b\\": 2}" `; exports[`.toEqual() {pass: true} expect({"a": 99}).not.toEqual({"a": 99}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {\\"a\\": 99} -Received: {\\"a\\": 99}" +Expected: not {\\"a\\": 99} +" `; exports[`.toEqual() {pass: true} expect({"nodeName": "div", "nodeType": 1}).not.toEqual({"nodeName": "div", "nodeType": 1}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {\\"nodeName\\": \\"div\\", \\"nodeType\\": 1} -Received: {\\"nodeName\\": \\"div\\", \\"nodeType\\": 1}" +Expected: not {\\"nodeName\\": \\"div\\", \\"nodeType\\": 1} +" `; exports[`.toEqual() {pass: true} expect({}).not.toEqual({}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {} -Received: {}" +Expected: not {} +" `; exports[`.toEqual() {pass: true} expect({}).not.toEqual(0) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: 0 -Received: {}" +Expected: not 0 +Received: {}" `; exports[`.toEqual() {pass: true} expect(0).not.toEqual({}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: {} -Received: 0" +Expected: not {} +Received: 0" `; exports[`.toEqual() {pass: true} expect(1).not.toEqual(1) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: 1 -Received: 1" +Expected: not 1 +" `; exports[`.toEqual() {pass: true} expect(Immutable.List [1, 2]).not.toEqual(Immutable.List [1, 2]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.List [1, 2] -Received: Immutable.List [1, 2]" +Expected: not Immutable.List [1, 2] +" `; exports[`.toEqual() {pass: true} expect(Immutable.List [1]).not.toEqual(Immutable.List [1]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.List [1] -Received: Immutable.List [1]" +Expected: not Immutable.List [1] +" `; exports[`.toEqual() {pass: true} expect(Immutable.Map {"1": Immutable.Map {"2": {"a": 99}}}).not.toEqual(Immutable.Map {"1": Immutable.Map {"2": {"a": 99}}}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Map {\\"1\\": Immutable.Map {\\"2\\": {\\"a\\": 99}}} -Received: Immutable.Map {\\"1\\": Immutable.Map {\\"2\\": {\\"a\\": 99}}}" +Expected: not Immutable.Map {\\"1\\": Immutable.Map {\\"2\\": {\\"a\\": 99}}} +" `; exports[`.toEqual() {pass: true} expect(Immutable.Map {}).not.toEqual(Immutable.Map {}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Map {} -Received: Immutable.Map {}" +Expected: not Immutable.Map {} +" `; exports[`.toEqual() {pass: true} expect(Immutable.Map {1: "one", 2: "two"}).not.toEqual(Immutable.Map {1: "one", 2: "two"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Map {1: \\"one\\", 2: \\"two\\"} -Received: Immutable.Map {1: \\"one\\", 2: \\"two\\"}" +Expected: not Immutable.Map {1: \\"one\\", 2: \\"two\\"} +" `; exports[`.toEqual() {pass: true} expect(Immutable.Map {1: "one", 2: "two"}).not.toEqual(Immutable.Map {2: "two", 1: "one"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Map {2: \\"two\\", 1: \\"one\\"} -Received: Immutable.Map {1: \\"one\\", 2: \\"two\\"}" +Expected: not Immutable.Map {2: \\"two\\", 1: \\"one\\"} +Received: Immutable.Map {1: \\"one\\", 2: \\"two\\"}" `; exports[`.toEqual() {pass: true} expect(Immutable.OrderedMap {1: "one", 2: "two"}).not.toEqual(Immutable.OrderedMap {1: "one", 2: "two"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.OrderedMap {1: \\"one\\", 2: \\"two\\"} -Received: Immutable.OrderedMap {1: \\"one\\", 2: \\"two\\"}" +Expected: not Immutable.OrderedMap {1: \\"one\\", 2: \\"two\\"} +" `; exports[`.toEqual() {pass: true} expect(Immutable.OrderedSet []).not.toEqual(Immutable.OrderedSet []) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.OrderedSet [] -Received: Immutable.OrderedSet []" +Expected: not Immutable.OrderedSet [] +" `; exports[`.toEqual() {pass: true} expect(Immutable.OrderedSet [1, 2]).not.toEqual(Immutable.OrderedSet [1, 2]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.OrderedSet [1, 2] -Received: Immutable.OrderedSet [1, 2]" +Expected: not Immutable.OrderedSet [1, 2] +" `; exports[`.toEqual() {pass: true} expect(Immutable.Set []).not.toEqual(Immutable.Set []) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Set [] -Received: Immutable.Set []" +Expected: not Immutable.Set [] +" `; exports[`.toEqual() {pass: true} expect(Immutable.Set [1, 2]).not.toEqual(Immutable.Set [1, 2]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Set [1, 2] -Received: Immutable.Set [1, 2]" +Expected: not Immutable.Set [1, 2] +" `; exports[`.toEqual() {pass: true} expect(Immutable.Set [1, 2]).not.toEqual(Immutable.Set [2, 1]) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Immutable.Set [2, 1] -Received: Immutable.Set [1, 2]" +Expected: not Immutable.Set [2, 1] +Received: Immutable.Set [1, 2]" `; exports[`.toEqual() {pass: true} expect(Map {[1] => "one", [2] => "two", [3] => "three", [3] => "four"}).not.toEqual(Map {[3] => "three", [3] => "four", [2] => "two", [1] => "one"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {[3] => \\"three\\", [3] => \\"four\\", [2] => \\"two\\", [1] => \\"one\\"} -Received: Map {[1] => \\"one\\", [2] => \\"two\\", [3] => \\"three\\", [3] => \\"four\\"}" +Expected: not Map {[3] => \\"three\\", [3] => \\"four\\", [2] => \\"two\\", [1] => \\"one\\"} +Received: Map {[1] => \\"one\\", [2] => \\"two\\", [3] => \\"three\\", [3] => \\"four\\"}" `; exports[`.toEqual() {pass: true} expect(Map {[1] => "one", [2] => "two"}).not.toEqual(Map {[2] => "two", [1] => "one"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {[2] => \\"two\\", [1] => \\"one\\"} -Received: Map {[1] => \\"one\\", [2] => \\"two\\"}" +Expected: not Map {[2] => \\"two\\", [1] => \\"one\\"} +Received: Map {[1] => \\"one\\", [2] => \\"two\\"}" `; exports[`.toEqual() {pass: true} expect(Map {[1] => Map {[1] => "one"}, [2] => Map {[2] => "two"}}).not.toEqual(Map {[2] => Map {[2] => "two"}, [1] => Map {[1] => "one"}}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {[2] => Map {[2] => \\"two\\"}, [1] => Map {[1] => \\"one\\"}} -Received: Map {[1] => Map {[1] => \\"one\\"}, [2] => Map {[2] => \\"two\\"}}" +Expected: not Map {[2] => Map {[2] => \\"two\\"}, [1] => Map {[1] => \\"one\\"}} +Received: Map {[1] => Map {[1] => \\"one\\"}, [2] => Map {[2] => \\"two\\"}}" `; exports[`.toEqual() {pass: true} expect(Map {{"a": 1} => "one", {"b": 2} => "two"}).not.toEqual(Map {{"b": 2} => "two", {"a": 1} => "one"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {{\\"b\\": 2} => \\"two\\", {\\"a\\": 1} => \\"one\\"} -Received: Map {{\\"a\\": 1} => \\"one\\", {\\"b\\": 2} => \\"two\\"}" +Expected: not Map {{\\"b\\": 2} => \\"two\\", {\\"a\\": 1} => \\"one\\"} +Received: Map {{\\"a\\": 1} => \\"one\\", {\\"b\\": 2} => \\"two\\"}" `; exports[`.toEqual() {pass: true} expect(Map {}).not.toEqual(Map {}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {} -Received: Map {}" +Expected: not Map {} +" `; exports[`.toEqual() {pass: true} expect(Map {1 => "one", 2 => "two"}).not.toEqual(Map {1 => "one", 2 => "two"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {1 => \\"one\\", 2 => \\"two\\"} -Received: Map {1 => \\"one\\", 2 => \\"two\\"}" +Expected: not Map {1 => \\"one\\", 2 => \\"two\\"} +" `; exports[`.toEqual() {pass: true} expect(Map {1 => "one", 2 => "two"}).not.toEqual(Map {2 => "two", 1 => "one"}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {2 => \\"two\\", 1 => \\"one\\"} -Received: Map {1 => \\"one\\", 2 => \\"two\\"}" +Expected: not Map {2 => \\"two\\", 1 => \\"one\\"} +Received: Map {1 => \\"one\\", 2 => \\"two\\"}" `; exports[`.toEqual() {pass: true} expect(Map {1 => ["one"], 2 => ["two"]}).not.toEqual(Map {2 => ["two"], 1 => ["one"]}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Map {2 => [\\"two\\"], 1 => [\\"one\\"]} -Received: Map {1 => [\\"one\\"], 2 => [\\"two\\"]}" +Expected: not Map {2 => [\\"two\\"], 1 => [\\"one\\"]} +Received: Map {1 => [\\"one\\"], 2 => [\\"two\\"]}" `; exports[`.toEqual() {pass: true} expect(NaN).not.toEqual(NaN) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: NaN -Received: NaN" +Expected: not NaN +" `; exports[`.toEqual() {pass: true} expect(Set {[1], [2], [3], [3]}).not.toEqual(Set {[3], [3], [2], [1]}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {[3], [3], [2], [1]} -Received: Set {[1], [2], [3], [3]}" +Expected: not Set {[3], [3], [2], [1]} +Received: Set {[1], [2], [3], [3]}" `; exports[`.toEqual() {pass: true} expect(Set {[1], [2]}).not.toEqual(Set {[2], [1]}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {[2], [1]} -Received: Set {[1], [2]}" +Expected: not Set {[2], [1]} +Received: Set {[1], [2]}" `; exports[`.toEqual() {pass: true} expect(Set {{"a": 1}, {"b": 2}}).not.toEqual(Set {{"b": 2}, {"a": 1}}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {{\\"b\\": 2}, {\\"a\\": 1}} -Received: Set {{\\"a\\": 1}, {\\"b\\": 2}}" +Expected: not Set {{\\"b\\": 2}, {\\"a\\": 1}} +Received: Set {{\\"a\\": 1}, {\\"b\\": 2}}" `; exports[`.toEqual() {pass: true} expect(Set {}).not.toEqual(Set {}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {} -Received: Set {}" +Expected: not Set {} +" `; exports[`.toEqual() {pass: true} expect(Set {1, 2}).not.toEqual(Set {1, 2}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {1, 2} -Received: Set {1, 2}" +Expected: not Set {1, 2} +" `; exports[`.toEqual() {pass: true} expect(Set {1, 2}).not.toEqual(Set {2, 1}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {2, 1} -Received: Set {1, 2}" +Expected: not Set {2, 1} +Received: Set {1, 2}" `; exports[`.toEqual() {pass: true} expect(Set {Set {[1]}, Set {[2]}}).not.toEqual(Set {Set {[2]}, Set {[1]}}) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Set {Set {[2]}, Set {[1]}} -Received: Set {Set {[1]}, Set {[2]}}" +Expected: not Set {Set {[2]}, Set {[1]}} +Received: Set {Set {[1]}, Set {[2]}}" `; exports[`.toEqual() {pass: true} expect(true).not.toEqual(Anything) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: Anything -Received: true" +Expected: not Anything +Received: true" `; exports[`.toEqual() {pass: true} expect(true).not.toEqual(true) 1`] = ` -"expect(received).not.toEqual(expected) +"expect(received).not.toEqual(expected) // deep equality -Expected: true -Received: true" +Expected: not true +" `; exports[`.toHaveLength {pass: false} expect("").toHaveLength(1) 1`] = ` @@ -3659,9 +3593,7 @@ Received string: \\"bar\\"" `; exports[`.toStrictEqual() matches the expected snapshot when it fails 1`] = ` -"expect(received).toStrictEqual(expected) - -Difference: +"expect(received).toStrictEqual(expected) // deep equality - Expected + Received @@ -3676,10 +3608,10 @@ Difference: `; exports[`.toStrictEqual() matches the expected snapshot when it fails 2`] = ` -"expect(received).not.toStrictEqual(expected) +"expect(received).not.toStrictEqual(expected) // deep equality -Expected: {\\"test\\": {\\"a\\": 1, \\"b\\": 2}} -Received: {\\"test\\": {\\"a\\": 1, \\"b\\": 2}}" +Expected: not {\\"test\\": {\\"a\\": 1, \\"b\\": 2}} +" `; exports[`toMatchObject() {pass: false} expect([0]).toMatchObject([-0]) 1`] = ` diff --git a/packages/expect/src/matchers.ts b/packages/expect/src/matchers.ts index 405b479330cc..a26fe2a7ebbe 100644 --- a/packages/expect/src/matchers.ts +++ b/packages/expect/src/matchers.ts @@ -27,6 +27,7 @@ import { } from 'jest-matcher-utils'; import {MatchersObject, MatcherState} from './types'; import { + printDiffOrStringify, printReceivedArrayContainExpectedItem, printReceivedStringContainExpectedResult, printReceivedStringContainExpectedSubstring, @@ -38,10 +39,13 @@ import { sparseArrayEquality, subsetEquality, typeEquality, - isOneline, } from './utils'; import {equals} from './jasmineUtils'; +// Include colon and one or more spaces, same as returned by getLabelPrinter. +const EXPECTED_LABEL = 'Expected: '; +const RECEIVED_LABEL = 'Received: '; + const toStrictEqualTesters = [ iterableEquality, typeEquality, @@ -72,7 +76,6 @@ const matchers: MatchersObject = { '\n\n' + `Expected: not ${printExpected(expected)}` : () => { - const receivedType = getType(received); const expectedType = getType(expected); let deepEqualityName = null; @@ -86,20 +89,6 @@ const matchers: MatchersObject = { } } - const hasConciseReport = - receivedType !== expectedType || - (isPrimitive(expected) && - (expectedType !== 'string' || isOneline(expected, received))) || - expectedType === 'date' || - expectedType === 'function' || - expectedType === 'regexp' || - (received instanceof Error && expected instanceof Error); - const hasDifference = stringify(expected) !== stringify(received); - const difference = - !hasConciseReport && hasDifference - ? diff(expected, received, {expand: this.expand}) // string | null - : null; - return ( matcherHint(matcherName, undefined, undefined, options) + '\n\n' + @@ -108,12 +97,13 @@ const matchers: MatchersObject = { `If it should pass with deep equality, replace "${matcherName}" with "${deepEqualityName}"`, ) + '\n\n' : '') + - (difference !== null - ? difference - : `Expected: ${printExpected(expected)}\n` + - (hasDifference - ? `Received: ${printReceived(received)}` - : 'Received value has no visual difference')) + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + this.expand, + ) ); }; @@ -569,9 +559,11 @@ const matchers: MatchersObject = { }, toEqual(this: MatcherState, received: unknown, expected: unknown) { - const matcherName = '.toEqual'; + const matcherName = 'toEqual'; const options: MatcherHintOptions = { + comment: 'deep equality', isNot: this.isNot, + promise: this.promise, }; const pass = equals(received, expected, [iterableEquality]); @@ -580,25 +572,25 @@ const matchers: MatchersObject = { ? () => matcherHint(matcherName, undefined, undefined, options) + '\n\n' + - `Expected: ${printExpected(expected)}\n` + - `Received: ${printReceived(received)}` - : () => { - const difference = diff(expected, received, {expand: this.expand}); - - return ( - matcherHint(matcherName, undefined, undefined, options) + - '\n\n' + - (difference && difference.includes('- Expect') - ? `Difference:\n\n${difference}` - : `Expected: ${printExpected(expected)}\n` + - `Received: ${printReceived(received)}`) + `Expected: not ${printExpected(expected)}\n` + + (stringify(expected) !== stringify(received) + ? `Received: ${printReceived(received)}` + : '') + : () => + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + this.expand, ); - }; // Passing the actual and expected objects so that a custom reporter // could access them, for example in order to display a custom visual diff, // or create a different error message - return {actual: received, expected, message, name: 'toEqual', pass}; + return {actual: received, expected, message, name: matcherName, pass}; }, toHaveLength(this: MatcherState, received: any, expected: number) { @@ -884,9 +876,11 @@ const matchers: MatchersObject = { }, toStrictEqual(this: MatcherState, received: unknown, expected: unknown) { - const matcherName = '.toStrictEqual'; + const matcherName = 'toStrictEqual'; const options: MatcherHintOptions = { + comment: 'deep equality', isNot: this.isNot, + promise: this.promise, }; const pass = equals(received, expected, toStrictEqualTesters, true); @@ -895,22 +889,25 @@ const matchers: MatchersObject = { ? () => matcherHint(matcherName, undefined, undefined, options) + '\n\n' + - `Expected: ${printExpected(expected)}\n` + - `Received: ${printReceived(received)}` - : () => { - const difference = diff(expected, received, { - expand: this.expand, - }); - return ( - matcherHint(matcherName, undefined, undefined, options) + - (difference ? `\n\nDifference:\n\n${difference}` : '') + `Expected: not ${printExpected(expected)}\n` + + (stringify(expected) !== stringify(received) + ? `Received: ${printReceived(received)}` + : '') + : () => + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + this.expand, ); - }; // Passing the actual and expected objects so that a custom reporter // could access them, for example in order to display a custom visual diff, // or create a different error message - return {actual: received, expected, message, name: 'toStrictEqual', pass}; + return {actual: received, expected, message, name: matcherName, pass}; }, }; diff --git a/packages/expect/src/print.ts b/packages/expect/src/print.ts index a8c50038a225..725a16ddbfac 100644 --- a/packages/expect/src/print.ts +++ b/packages/expect/src/print.ts @@ -6,12 +6,16 @@ * */ +import getType, {isPrimitive} from 'jest-get-type'; import { INVERTED_COLOR, RECEIVED_COLOR, + diff, + printExpected, printReceived, stringify, } from 'jest-matcher-utils'; +import {isOneline} from './utils'; // Format substring but do not enclose in double quote marks. // The replacement is compatible with pretty-format package. @@ -59,3 +63,58 @@ export const printReceivedArrayContainExpectedItem = ( .join(', ') + ']', ); + +const shouldPrintDiff = (expected: unknown, received: unknown): boolean => { + const expectedType = getType(expected); + const receivedType = getType(received); + + if (expectedType !== receivedType) { + return false; + } + + if (isPrimitive(expected)) { + // Print diff only if both strings have more than one line. + return expectedType === 'string' && !isOneline(expected, received); + } + + if ( + expectedType === 'date' || + expectedType === 'function' || + expectedType === 'regexp' + ) { + return false; + } + + if (expected instanceof Error && received instanceof Error) { + return false; + } + + return true; +}; + +export const printDiffOrStringify = ( + expected: unknown, + received: unknown, + expectedLabel: string, // include colon and one or more spaces, + receivedLabel: string, // same as returned by getLabelPrinter + expand?: boolean, // diff option: true if `--expand` CLI option +): string => { + // Cannot use same serialization as shortcut to avoid diff, + // because stringify (that is, pretty-format with min option) + // omits constructor name for array or object, too bad so sad :( + const difference = shouldPrintDiff(expected, received) + ? diff(expected, received, {expand}) // string | null + : null; + + // Cannot reuse value of stringify(received) in report string, + // because printReceived does inverse highlight space at end of line, + // but RECEIVED_COLOR does not (it refers to a plain chalk method). + return typeof difference === 'string' && difference.includes('- Expected') + ? difference + : `${expectedLabel}${printExpected(expected)}\n` + + `${receivedLabel}${ + stringify(expected) === stringify(received) + ? 'serializes to the same string' + : printReceived(received) + }`; +}; diff --git a/packages/jest-matcher-utils/src/__tests__/__snapshots__/index.test.ts.snap b/packages/jest-matcher-utils/src/__tests__/__snapshots__/index.test.ts.snap index 208598d4c2f2..b495afe03d41 100644 --- a/packages/jest-matcher-utils/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/jest-matcher-utils/src/__tests__/__snapshots__/index.test.ts.snap @@ -93,9 +93,7 @@ exports[`.stringify() reduces maxDepth if stringifying very large objects 1`] = exports[`.stringify() reduces maxDepth if stringifying very large objects 2`] = `"{\\"a\\": 1, \\"b\\": {\\"0\\": \\"test\\", \\"1\\": \\"test\\", \\"2\\": \\"test\\", \\"3\\": \\"test\\", \\"4\\": \\"test\\", \\"5\\": \\"test\\", \\"6\\": \\"test\\", \\"7\\": \\"test\\", \\"8\\": \\"test\\", \\"9\\": \\"test\\"}}"`; exports[`.stringify() toJSON errors when comparing two objects 1`] = ` -"expect(received).toEqual(expected) - -Difference: +"expect(received).toEqual(expected) // deep equality - Expected + Received