Skip to content

expect: Improve report when matcher fails, part 19 #8367

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

Merged
merged 5 commits into from
Apr 25, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
- `[docs]` Add DynamoDB guide ([#8319](https://github.com/facebook/jest/pull/8319))
- `[expect]` Improve report when matcher fails, part 17 ([#8349](https://github.com/facebook/jest/pull/8349))
- `[expect]` Improve report when matcher fails, part 18 ([#8356](https://github.com/facebook/jest/pull/8356))
- `[expect]` Improve report when matcher fails, part 19 ([#8367](https://github.com/facebook/jest/pull/8367))

### Fixes

31 changes: 23 additions & 8 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Original file line number Diff line number Diff line change
@@ -1265,6 +1265,7 @@ exports[`.toBeInstanceOf() failing "a" and [Function String] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>String</>

Received value has no prototype
Received value: <red>\\"a\\"</>"
`;
@@ -1274,13 +1275,14 @@ exports[`.toBeInstanceOf() failing /\\w+/ and [Function anonymous] 1`] = `

Expected constructor name is an empty string
Received constructor: <red>RegExp</>
Received value: <red>/\\\\w+/</>"
"
`;

exports[`.toBeInstanceOf() failing {} and [Function A] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>A</>

Received value has no prototype
Received value: <red>{}</>"
`;
@@ -1290,21 +1292,22 @@ exports[`.toBeInstanceOf() failing {} and [Function B] 1`] = `

Expected constructor: <green>B</>
Received constructor: <red>A</>
Received value: <red>{}</>"
"
`;

exports[`.toBeInstanceOf() failing {} and [Function RegExp] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>RegExp</>
Received constructor name is an empty string
Received value: <red>{}</>"
"
`;

exports[`.toBeInstanceOf() failing 1 and [Function Number] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>Number</>

Received value has no prototype
Received value: <red>1</>"
`;
@@ -1313,6 +1316,7 @@ exports[`.toBeInstanceOf() failing null and [Function String] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>String</>

Received value has no prototype
Received value: <red>null</>"
`;
@@ -1321,6 +1325,7 @@ exports[`.toBeInstanceOf() failing true and [Function Boolean] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>Boolean</>

Received value has no prototype
Received value: <red>true</>"
`;
@@ -1329,6 +1334,7 @@ exports[`.toBeInstanceOf() failing undefined and [Function String] 1`] = `
"<dim>expect(</><red>received</><dim>).</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: <green>String</>

Received value has no prototype
Received value: <red>undefined</>"
`;
@@ -1337,35 +1343,44 @@ exports[`.toBeInstanceOf() passing [] and [Function Array] 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Array</>
Received value: <red>[]</>"
"
`;

exports[`.toBeInstanceOf() passing {} and [Function A] 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>A</>
Received value: <red>{}</>"
"
`;

exports[`.toBeInstanceOf() passing {} and [Function B] 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>B</>
Received value: <red>{}</>"
Received constructor: <red>C</> extends <green>B</>
"
`;

exports[`.toBeInstanceOf() passing {} and [Function B] 2`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>B</>
Received constructor: <red>E</> extends … extends <green>B</>
"
`;

exports[`.toBeInstanceOf() passing {} and [Function name() {}] 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor name is not a string
Received value: <red>{}</>"
"
`;

exports[`.toBeInstanceOf() passing Map {} and [Function Map] 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toBeInstanceOf<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Map</>
Received value: <red>Map {}</>"
"
`;

exports[`.toBeInstanceOf() throws if constructor is not a function 1`] = `
Original file line number Diff line number Diff line change
@@ -89,16 +89,16 @@ Received message: <red>\\"apple\\"</>
exports[`toThrow error class did not throw at all 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrow<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err\\"</>
Expected constructor: <green>Err</>

Received function did not throw"
`;

exports[`toThrow error class threw, but class did not match (error) 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrow<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: <green>Err2</>
Received constructor: <red>Err</>

Received message: <red>\\"apple\\"</>

@@ -108,17 +108,38 @@ Received message: <red>\\"apple\\"</>
exports[`toThrow error class threw, but class did not match (non-error falsey) 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrow<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Expected constructor: <green>Err2</>

Received value: <red>undefined</>
"
`;

exports[`toThrow error class threw, but class should not match (error subclass) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrow<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Err</>
Received constructor: <red>SubErr</> extends <green>Err</>

Received message: <red>\\"apple\\"</>

<dim>at jestExpect (</>packages/expect/src/__tests__/toThrowMatchers-test.js<dim>:24:74)</>"
`;

exports[`toThrow error class threw, but class should not match (error subsubclass) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrow<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Err</>
Received constructor: <red>SubSubErr</> extends … extends <green>Err</>

Received message: <red>\\"apple\\"</>

<dim>at jestExpect (</>packages/expect/src/__tests__/toThrowMatchers-test.js<dim>:24:74)</>"
`;

exports[`toThrow error class threw, but class should not match (error) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrow<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: not <green>Err</>

Received message: <red>\\"apple\\"</>

@@ -174,8 +195,8 @@ Received function did not throw"
exports[`toThrow promise/async throws if Error-like object is returned threw, but class did not match 1`] = `
"<dim>expect(</><red>received</><dim>).</>rejects<dim>.</>toThrow<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: <green>Err2</>
Received constructor: <red>Err</>

Received message: <red>\\"async apple\\"</>

@@ -364,16 +385,16 @@ Received message: <red>\\"apple\\"</>
exports[`toThrowError error class did not throw at all 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err\\"</>
Expected constructor: <green>Err</>

Received function did not throw"
`;

exports[`toThrowError error class threw, but class did not match (error) 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: <green>Err2</>
Received constructor: <red>Err</>

Received message: <red>\\"apple\\"</>

@@ -383,17 +404,38 @@ Received message: <red>\\"apple\\"</>
exports[`toThrowError error class threw, but class did not match (non-error falsey) 1`] = `
"<dim>expect(</><red>received</><dim>).</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Expected constructor: <green>Err2</>

Received value: <red>undefined</>
"
`;

exports[`toThrowError error class threw, but class should not match (error subclass) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Err</>
Received constructor: <red>SubErr</> extends <green>Err</>

Received message: <red>\\"apple\\"</>

<dim>at jestExpect (</>packages/expect/src/__tests__/toThrowMatchers-test.js<dim>:24:74)</>"
`;

exports[`toThrowError error class threw, but class should not match (error subsubclass) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected constructor: not <green>Err</>
Received constructor: <red>SubSubErr</> extends … extends <green>Err</>

Received message: <red>\\"apple\\"</>

<dim>at jestExpect (</>packages/expect/src/__tests__/toThrowMatchers-test.js<dim>:24:74)</>"
`;

exports[`toThrowError error class threw, but class should not match (error) 1`] = `
"<dim>expect(</><red>received</><dim>).</>not<dim>.</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: not <green>Err</>

Received message: <red>\\"apple\\"</>

@@ -449,8 +491,8 @@ Received function did not throw"
exports[`toThrowError promise/async throws if Error-like object is returned threw, but class did not match 1`] = `
"<dim>expect(</><red>received</><dim>).</>rejects<dim>.</>toThrowError<dim>(</><green>expected</><dim>)</>

Expected name: <green>\\"Err2\\"</>
Received name: <red>\\"Error\\"</>
Expected constructor: <green>Err2</>
Received constructor: <red>Err</>

Received message: <red>\\"async apple\\"</>

5 changes: 4 additions & 1 deletion packages/expect/src/__tests__/matchers.test.js
Original file line number Diff line number Diff line change
@@ -687,6 +687,8 @@ describe('.toBeInstanceOf()', () => {
class A {}
class B {}
class C extends B {}
class D extends C {}
class E extends D {}

class HasStaticNameMethod {
constructor() {}
@@ -705,7 +707,8 @@ describe('.toBeInstanceOf()', () => {
[new Map(), Map],
[[], Array],
[new A(), A],
[new C(), B], // subclass
[new C(), B], // C extends B
[new E(), B], // E extends … extends B
[new HasStaticNameMethod(), HasStaticNameMethod],
].forEach(([a, b]) => {
test(`passing ${stringify(a)} and ${stringify(b)}`, () => {
34 changes: 34 additions & 0 deletions packages/expect/src/__tests__/toThrowMatchers.test.js
Original file line number Diff line number Diff line change
@@ -146,6 +146,24 @@ class customError extends Error {
});

describe('error class', () => {
class SubErr extends Err {
constructor(...args) {
super(...args);
// In a carefully written error subclass,
// name property is equal to constructor name.
this.name = this.constructor.name;
}
}

class SubSubErr extends SubErr {
constructor(...args) {
super(...args);
// In a carefully written error subclass,
// name property is equal to constructor name.
this.name = this.constructor.name;
}
}

it('passes', () => {
jestExpect(() => {
throw new Err();
@@ -189,6 +207,22 @@ class customError extends Error {
}).not[toThrow](Err);
}).toThrowErrorMatchingSnapshot();
});

test('threw, but class should not match (error subclass)', () => {
expect(() => {
jestExpect(() => {
throw new SubErr('apple');
}).not[toThrow](Err);
}).toThrowErrorMatchingSnapshot();
});

test('threw, but class should not match (error subsubclass)', () => {
expect(() => {
jestExpect(() => {
throw new SubSubErr('apple');
}).not[toThrow](Err);
}).toThrowErrorMatchingSnapshot();
});
});

describe('error-message', () => {
Loading