Skip to content

Commit

Permalink
expect: Highlight substring differences when matcher fails, part 2 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrottimark authored and SimenB committed Jun 13, 2019
1 parent 62ca17c commit 98bafaa
Show file tree
Hide file tree
Showing 27 changed files with 1,806 additions and 482 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Expand Up @@ -4,7 +4,7 @@ bin/
flow-typed/**
packages/*/build/**
packages/*/build-es5/**
packages/jest-matcher-utils/src/cleanupSemantic.ts
packages/jest-diff/src/cleanupSemantic.ts
website/blog
website/build
website/node_modules
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
@@ -1,4 +1,4 @@
fixtures/failing-jsons/
packages/jest-matcher-utils/src/cleanupSemantic.ts
packages/jest-diff/src/cleanupSemantic.ts
packages/jest-config/src/__tests__/jest-preset.json
packages/pretty-format/perf/world.geo.json
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
### Features

- `[expect]` Highlight substring differences when matcher fails, part 1 ([#8448](https://github.com/facebook/jest/pull/8448))
- `[expect]` Highlight substring differences when matcher fails, part 2 ([#8528](https://github.com/facebook/jest/pull/8528))
- `[jest-cli]` Improve chai support (with detailed output, to match jest exceptions) ([#8454](https://github.com/facebook/jest/pull/8454))
- `[*]` Manage the global timeout with `--testTimeout` command line argument. ([#8456](https://github.com/facebook/jest/pull/8456))
- `[pretty-format]` Render custom displayName of memoized components
Expand Down
72 changes: 66 additions & 6 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Expand Up @@ -303,9 +303,9 @@ string" 1`] = `
<green>- Expected</>
<red>+ Received</>

<green>- 3</>
<red>+ four</>
<red>+ 4</>
<green>- <inverse>3</></>
<red>+ <inverse>four</></>
<red>+ <inverse>4</></>
<dim> line</>
<dim> string</>"
`;
Expand All @@ -321,9 +321,12 @@ exports[`.toBe() fails for: "with
trailing space" and "without trailing space" 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBe<dim>(</><green>expected</><dim>) // Object.is equality</>

Expected: <green>\\"without trailing space\\"</>
Received: <red>\\"with<inverse> </></>
<red>trailing space\\"</>"
<green>- Expected</>
<red>+ Received</>

<green>- with<inverse>out</> trailing space</>
<red>+ with·</>
<red>+ trailing space</>"
`;

exports[`.toBe() fails for: /received/ and /expected/ 1`] = `
Expand Down Expand Up @@ -1971,6 +1974,20 @@ Expected: <green>\\"apple\\"</>
Received: <red>\\"banana\\"</>"
`;

exports[`.toEqual() {pass: false} expect("type TypeName<T> = T extends Function ? \\"function\\" : \\"object\\";").toEqual("type TypeName<T> = T extends Function
? \\"function\\"
: \\"object\\";") 1`] = `
"<dim>expect(</><red>received</><dim>).</>toEqual<dim>(</><green>expected</><dim>) // deep equality</>

<green>- Expected</>
<red>+ Received</>

<green>- type TypeName<T> = T extends Function</>
<green>- ? \\"function\\"</>
<green>- : \\"object\\";</>
<red>+ type TypeName<T> = T extends Function<inverse> </>? \\"function\\"<inverse> </>: \\"object\\";</>"
`;

exports[`.toEqual() {pass: false} expect([1, 2]).toEqual([2, 1]) 1`] = `
"<dim>expect(</><red>received</><dim>).</>toEqual<dim>(</><green>expected</><dim>) // deep equality</>

Expand Down Expand Up @@ -3080,6 +3097,26 @@ Expected value: <green>\\"\\\\\\"That <inverse>cat </>cartoon\\\\\\"\\"</>
Received value: <red>\\"\\\\\\"That cartoon\\\\\\"\\"</>"
`;

exports[`.toHaveProperty() {pass: false} expect({"children": ["Roses are red.
Violets are blue.
Testing with Jest is good for you."], "props": null, "type": "pre"}).toHaveProperty('children,0', "Roses are red, violets are blue.
Testing with Jest
Is good for you.") 1`] = `
"<dim>expect(</><red>received</><dim>).</>toHaveProperty<dim>(</><green>path</><dim>, </><green>value</><dim>)</>

Expected path: <green>[\\"children\\", 0]</>

<green>- Expected value</>
<red>+ Received value</>

<green>- Roses are red<inverse>, v</>iolets are blue.</>
<red>+ Roses are red<inverse>.</></>
<red>+ <inverse>V</>iolets are blue.</>
<green>- Testing with Jest</>
<green>- <inverse>I</>s good for you.</>
<red>+ Testing with Jest<inverse> i</>s good for you.</>"
`;

exports[`.toHaveProperty() {pass: false} expect({"key": 1}).toHaveProperty('not') 1`] = `
"<dim>expect(</><red>received</><dim>).</>toHaveProperty<dim>(</><green>path</><dim>)</>

Expand Down Expand Up @@ -3527,6 +3564,29 @@ Expected: <green>\\"<inverse>Another caveat is that</> Jest will not typecheck y
Received: <red>\\"<inverse>Because TypeScript support in Babel is just transpilation,</> Jest will not type<inverse>-</>check your tests<inverse> as they run</>.\\"</>"
`;

exports[`.toStrictEqual() displays substring diff for multiple lines 1`] = `
"<dim>expect(</><red>received</><dim>).</>toStrictEqual<dim>(</><green>expected</><dim>) // deep equality</>

<green>- Expected</>
<red>+ Received</>

<green>- 6<inverse>9</> |·</>
<red>+ 6<inverse>8</> |·</>
<green>- <inverse>70</> | test('assert.doesNotThrow', () => {</>
<red>+ <inverse>69</> | test('assert.doesNotThrow', () => {</>
<green>- > 7<inverse>1</> | assert.doesNotThrow(() => {</>
<red>+ > 7<inverse>0</> | assert.doesNotThrow(() => {</>
<dim> | ^</>
<green>- 7<inverse>2</> | throw Error('err!');</>
<red>+ 7<inverse>1</> | throw Error('err!');</>
<green>- 7<inverse>3</> | });</>
<red>+ 7<inverse>2</> | });</>
<green>- 7<inverse>4</> | });</>
<red>+ 7<inverse>3</> | });</>
<green>- at Object.doesNotThrow (__tests__/assertionError.test.js:7<inverse>1</>:10)</>
<red>+ at Object.doesNotThrow (__tests__/assertionError.test.js:7<inverse>0</>:10)</>"
`;

exports[`.toStrictEqual() matches the expected snapshot when it fails 1`] = `
"<dim>expect(</><red>received</><dim>).</>toStrictEqual<dim>(</><green>expected</><dim>) // deep equality</>

Expand Down
Expand Up @@ -161,6 +161,18 @@ Expected message: not <green>\\"Invalid array length\\"</>
"
`;

exports[`toThrow error-message fail multiline diff highlight incorrect expected space 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrow<dim>(</><green>expected</><dim>)</>

<green>- Expected message</>
<red>+ Received message</>

<green>- There is no route defined for key Settings.<inverse> </></>
<red>+ There is no route defined for key Settings.</>
<dim> Must be one of: 'Home'</>
"
`;

exports[`toThrow expected is undefined threw, but should not have (non-error falsey) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrow<dim>()</>

Expand Down Expand Up @@ -457,6 +469,18 @@ Expected message: not <green>\\"Invalid array length\\"</>
"
`;

exports[`toThrowError error-message fail multiline diff highlight incorrect expected space 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrowError<dim>(</><green>expected</><dim>)</>

<green>- Expected message</>
<red>+ Received message</>

<green>- There is no route defined for key Settings.<inverse> </></>
<red>+ There is no route defined for key Settings.</>
<dim> Must be one of: 'Home'</>
"
`;

exports[`toThrowError expected is undefined threw, but should not have (non-error falsey) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrowError<dim>()</>

Expand Down
51 changes: 46 additions & 5 deletions packages/expect/src/__tests__/matchers.test.js
Expand Up @@ -3,7 +3,6 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

const {stringify} = require('jest-matcher-utils');
Expand Down Expand Up @@ -330,6 +329,32 @@ describe('.toStrictEqual()', () => {
).toThrowErrorMatchingSnapshot();
});

it('displays substring diff for multiple lines', () => {
const expected = [
' 69 | ',
" 70 | test('assert.doesNotThrow', () => {",
' > 71 | assert.doesNotThrow(() => {',
' | ^',
" 72 | throw Error('err!');",
' 73 | });',
' 74 | });',
' at Object.doesNotThrow (__tests__/assertionError.test.js:71:10)',
].join('\n');
const received = [
' 68 | ',
" 69 | test('assert.doesNotThrow', () => {",
' > 70 | assert.doesNotThrow(() => {',
' | ^',
" 71 | throw Error('err!');",
' 72 | });',
' 73 | });',
' at Object.doesNotThrow (__tests__/assertionError.test.js:70:10)',
].join('\n');
expect(() =>
jestExpect(received).toStrictEqual(expected),
).toThrowErrorMatchingSnapshot();
});

it('does not pass for different types', () => {
expect({
test: new TestClassA(1, 2),
Expand Down Expand Up @@ -371,6 +396,10 @@ describe('.toEqual()', () => {
[{a: 5}, {b: 6}],
['banana', 'apple'],
['1\u{00A0}234,57\u{00A0}$', '1 234,57 $'], // issues/6881
[
'type TypeName<T> = T extends Function ? "function" : "object";',
'type TypeName<T> = T extends Function\n? "function"\n: "object";',
],
[null, undefined],
[[1], [2]],
[[1, 2], [2, 1]],
Expand Down Expand Up @@ -1361,13 +1390,24 @@ describe('.toHaveProperty()', () => {
const memoized = function() {};
memoized.memo = [];

const receivedDiff = {
const pathDiff = ['children', 0];

const receivedDiffSingle = {
children: ['"That cartoon"'],
props: null,
type: 'p',
};
const pathDiff = ['children', 0];
const valueDiff = '"That cat cartoon"';
const valueDiffSingle = '"That cat cartoon"';

const receivedDiffMultiple = {
children: [
'Roses are red.\nViolets are blue.\nTesting with Jest is good for you.',
],
props: null,
type: 'pre',
};
const valueDiffMultiple =
'Roses are red, violets are blue.\nTesting with Jest\nIs good for you.';

[
[{a: {b: {c: {d: 1}}}}, 'a.b.c.d', 1],
Expand Down Expand Up @@ -1405,7 +1445,8 @@ describe('.toHaveProperty()', () => {
[{a: {b: {c: {d: 1}}}}, 'a.b.c.d', 2],
[{'a.b.c.d': 1}, 'a.b.c.d', 2],
[{'a.b.c.d': 1}, ['a.b.c.d'], 2],
[receivedDiff, pathDiff, valueDiff],
[receivedDiffSingle, pathDiff, valueDiffSingle],
[receivedDiffMultiple, pathDiff, valueDiffMultiple],
[{a: {b: {c: {d: 1}}}}, ['a', 'b', 'c', 'd'], 2],
[{a: {b: {c: {}}}}, 'a.b.c.d', 1],
[{a: 1}, 'a.b.c.d', 5],
Expand Down
14 changes: 13 additions & 1 deletion packages/expect/src/__tests__/toThrowMatchers.test.js
Expand Up @@ -3,7 +3,6 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

'use strict';
Expand Down Expand Up @@ -266,6 +265,19 @@ class customError extends Error {
}).not[toThrow]({message}),
).toThrowErrorMatchingSnapshot();
});

test('multiline diff highlight incorrect expected space', () => {
// jest/issues/2673
const a =
"There is no route defined for key Settings. \nMust be one of: 'Home'";
const b =
"There is no route defined for key Settings.\nMust be one of: 'Home'";
expect(() =>
jestExpect(() => {
throw new ErrorMessage(b);
})[toThrow]({message: a}),
).toThrowErrorMatchingSnapshot();
});
});
});

Expand Down
18 changes: 14 additions & 4 deletions packages/expect/src/toThrowMatchers.ts
Expand Up @@ -12,6 +12,7 @@ import {
RECEIVED_COLOR,
matcherErrorMessage,
matcherHint,
printDiffOrStringify,
printExpected,
printReceived,
printWithType,
Expand Down Expand Up @@ -231,13 +232,22 @@ const toThrowExpectedObject = (
: () =>
matcherHint(matcherName, undefined, undefined, options) +
'\n\n' +
formatExpected('Expected message: ', expected.message) +
(thrown === null
? '\n' + DID_NOT_THROW
? formatExpected('Expected message: ', expected.message) +
'\n' +
DID_NOT_THROW
: thrown.hasMessage
? formatReceived('Received message: ', thrown, 'message') +
? printDiffOrStringify(
expected.message,
thrown.message,
'Expected message',
'Received message',
true,
) +
'\n' +
formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'));
: formatExpected('Expected message: ', expected.message) +
formatReceived('Received value: ', thrown, 'value'));

return {message, pass};
};
Expand Down

0 comments on commit 98bafaa

Please sign in to comment.