Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expect: Highlight substring differences when matcher fails, part 1 #8448

Merged
merged 16 commits into from May 27, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Expand Up @@ -4,6 +4,7 @@ bin/
flow-typed/**
packages/*/build/**
packages/*/build-es5/**
packages/expect/src/cleanupSemantic.js
website/blog
website/build
website/node_modules
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
@@ -1,3 +1,4 @@
fixtures/failing-jsons/
packages/expect/src/cleanupSemantic.js
packages/jest-config/src/__tests__/jest-preset.json
packages/pretty-format/perf/world.geo.json
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,8 @@

### Features

- `[expect]` Improve report when matcher fails, part 20 ([#8448](https://github.com/facebook/jest/pull/8448))
pedrottimark marked this conversation as resolved.
Show resolved Hide resolved

### Fixes

- `[babel-plugin-jest-hoist]` Expand list of whitelisted globals in global mocks ([#8429](https://github.com/facebook/jest/pull/8429)
Expand Down
1 change: 1 addition & 0 deletions packages/expect/package.json
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@jest/types": "^24.8.0",
"ansi-styles": "^3.2.0",
"diff-sequences": "^24.3.0",
"jest-get-type": "^24.8.0",
"jest-matcher-utils": "^24.8.0",
"jest-message-util": "^24.8.0",
Expand Down
30 changes: 30 additions & 0 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Expand Up @@ -303,6 +303,13 @@ string" 1`] = `
<dim> string</>"
`;

exports[`.toBe() fails for: "painless JavaScript testing" and "delightful JavaScript testing" 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBe<dim>(</><green>expected</><dim>) // Object.is equality</>

Expected: <green>\\"<inverse>delightful</> JavaScript testing\\"</>
Received: <red>\\"<inverse>painless</> JavaScript testing\\"</>"
`;

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</>
Expand Down Expand Up @@ -1922,6 +1929,13 @@ exports[`.toContain(), .toContainEqual() error cases for toContainEqual 1`] = `
Received has value: <red>null</>"
`;

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

Expected: <green>\\"1<inverse> </>234,57<inverse> </>$\\"</>
Received: <red>\\"1<inverse> </>234,57<inverse> </>$\\"</>"
`;

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

Expand Down Expand Up @@ -3057,6 +3071,15 @@ Expected value: <green>2</>
Received value: <red>1</>"
`;

exports[`.toHaveProperty() {pass: false} expect({"children": ["\\"That cartoon\\""], "props": null, "type": "p"}).toHaveProperty('children,0', "\\"That cat cartoon\\"") 1`] = `
"<dim>expect(</><red>received</><dim>).</>toHaveProperty<dim>(</><green>path</><dim>, </><green>value</><dim>)</>

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

Expected value: <green>\\"\\\\\\"That <inverse>cat </>cartoon\\\\\\"\\"</>
Received value: <red>\\"\\\\\\"That cartoon\\\\\\"\\"</>"
`;

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

Expand Down Expand Up @@ -3497,6 +3520,13 @@ Expected substring: <green>\\"foo\\"</>
Received string: <red>\\"bar\\"</>"
`;

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

Expected: <green>\\"<inverse>Another caveat is that</> Jest will not typecheck your tests.\\"</>
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() matches the expected snapshot when it fails 1`] = `
"<dim>expect(</><red>received</><dim>).</>toStrictEqual<dim>(</><green>expected</><dim>) // deep equality</>

Expand Down
21 changes: 21 additions & 0 deletions packages/expect/src/__tests__/matchers.test.js
Expand Up @@ -215,6 +215,7 @@ describe('.toBe()', () => {
[Symbol('received'), Symbol('expected')],
[new Error('received'), new Error('expected')],
['abc', 'cde'],
['painless JavaScript testing', 'delightful JavaScript testing'],
['with \ntrailing space', 'without trailing space'],
['four\n4\nline\nstring', '3\nline\nstring'],
[[], []],
Expand Down Expand Up @@ -318,6 +319,16 @@ describe('.toStrictEqual()', () => {
).toThrowErrorMatchingSnapshot();
});

it('displays substring diff', () => {
const expected =
'Another caveat is that Jest will not typecheck your tests.';
const received =
'Because TypeScript support in Babel is just transpilation, Jest will not type-check your tests as they run.';
expect(() =>
jestExpect(received).toStrictEqual(expected),
).toThrowErrorMatchingSnapshot();
});

it('does not pass for different types', () => {
expect({
test: new TestClassA(1, 2),
Expand Down Expand Up @@ -358,6 +369,7 @@ describe('.toEqual()', () => {
[{a: 1}, {a: 2}],
[{a: 5}, {b: 6}],
['banana', 'apple'],
['1\u{00A0}234,57\u{00A0}$', '1 234,57 $'], // issues/6881
[null, undefined],
[[1], [2]],
[[1, 2], [2, 1]],
Expand Down Expand Up @@ -1348,6 +1360,14 @@ describe('.toHaveProperty()', () => {
const memoized = function() {};
memoized.memo = [];

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

[
[{a: {b: {c: {d: 1}}}}, 'a.b.c.d', 1],
[{a: {b: {c: {d: 1}}}}, ['a', 'b', 'c', 'd'], 1],
Expand Down Expand Up @@ -1384,6 +1404,7 @@ 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],
[{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
21 changes: 21 additions & 0 deletions packages/expect/src/cleanupSemantic.d.ts
@@ -0,0 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

export declare const DIFF_COMMON = 0;
export declare const DIFF_DELETE = -1;
export declare const DIFF_INSERT = 1;

type DIFF_OP = 0 | -1 | 1;

export declare class Diff {
constructor(op: DIFF_OP, substring: string);
// properties have indexes like an array tuple
0: DIFF_OP;
1: string;
}

export declare const cleanupSemantic: (diffs: Array<Diff>) => void;