Skip to content

Commit

Permalink
jest-jasmine2: pretty-print non-Error errors
Browse files Browse the repository at this point in the history
  • Loading branch information
wmertens committed Apr 13, 2018
1 parent 3919925 commit f235e2a
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 19 deletions.
95 changes: 93 additions & 2 deletions integration-tests/__tests__/__snapshots__/failures.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,96 @@ exports[`not throwing Error objects 4`] = `
"
`;
exports[`not throwing Error objects 5`] = `
"FAIL __tests__/during_tests.test.js
✕ Promise thrown during test
✕ Boolean thrown during test
✕ undefined thrown during test
✕ Object thrown during test
✕ Error during test
✕ done(Error)
✕ done(non-error)
● Promise thrown during test
thrown: Promise {}
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
● Boolean thrown during test
thrown: false
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
● undefined thrown during test
thrown: undefined
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
● Object thrown during test
thrown: Object {
\\"notAnError\\": Array [
Object {
\\"hello\\": true,
\\"tooDeep\\": [Object],
},
],
}
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
● Error during test
ReferenceError: doesNotExist is not defined
26 | test('Error during test', () => {
27 | // eslint-disable-next-line no-undef
> 28 | doesNotExist.alsoThisNot;
29 | });
30 |
31 | test('done(Error)', done => {
at __tests__/during_tests.test.js:28:3
done(Error)
this is an error
30 |
31 | test('done(Error)', done => {
> 32 | done(new Error('this is an error'));
33 | });
34 |
35 | test('done(non-error)', done => {
at __tests__/during_tests.test.js:32:8
done(non-error)
Failed: Object {
\\"notAnError\\": Array [
Object {
\\"hello\\": true,
\\"tooDeep\\": [Object],
},
],
}
34 |
35 | test('done(non-error)', done => {
> 36 | done(deepObject);
37 | });
38 |
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
at __tests__/during_tests.test.js:36:3
"
`;
exports[`works with assertions in separate files 1`] = `
"FAIL __tests__/test_macro.test.js
✕ use some imported macro to make assertion
Expand Down Expand Up @@ -442,8 +532,9 @@ exports[`works with node assert 1`] = `
assert.ifError
Error
1 thrown
thrown: 1
at packages/jest-jasmine2/build/expectation_result_factory.js:45:47
assert.doesNotThrow
Expand Down
10 changes: 6 additions & 4 deletions integration-tests/__tests__/failures.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ test('not throwing Error objects', () => {
expect(extractSummary(stderr).rest).toMatchSnapshot();
stderr = runJest(dir, ['assertion_count.test.js']).stderr;
expect(extractSummary(cleanupStackTrace(stderr)).rest).toMatchSnapshot();
stderr = runJest(dir, ['during_tests.test.js']).stderr;
expect(extractSummary(stderr).rest).toMatchSnapshot();
});

test('works with node assert', () => {
Expand All @@ -63,23 +65,23 @@ test('works with node assert', () => {
if (Number(process.versions.node.split('.')[0]) >= 9) {
expect(summary).toContain(`
assert.doesNotThrow(function)
Expected the function not to throw an error.
Instead, it threw:
[Error: err!]
Message:
Got unwanted exception.
err!
err!
69 |
69 |
70 | test('assert.doesNotThrow', () => {
> 71 | assert.doesNotThrow(() => {
72 | throw Error('err!');
73 | });
74 | });
at __tests__/node_assertion_error.test.js:71:10
`);

Expand Down
37 changes: 37 additions & 0 deletions integration-tests/failures/__tests__/during_tests.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

const deepObject = {
notAnError: [{hello: true, tooDeep: {notVisible: true}}],
};

test('Promise thrown during test', () => {
throw Promise.resolve(5);
});

test('Boolean thrown during test', () => {
// eslint-disable-next-line no-throw-literal
throw false;
});

test('undefined thrown during test', () => {
// eslint-disable-next-line no-throw-literal
throw undefined;
});

test('Object thrown during test', () => {
// eslint-disable-next-line no-throw-literal
throw deepObject;
});

test('Error during test', () => {
// eslint-disable-next-line no-undef
doesNotExist.alsoThisNot;
});

test('done(Error)', done => {
done(new Error('this is an error'));
});

test('done(non-error)', done => {
done(deepObject);
});
3 changes: 2 additions & 1 deletion packages/jest-jasmine2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"jest-message-util": "^22.4.0",
"jest-snapshot": "^22.4.0",
"jest-util": "^22.4.1",
"source-map-support": "^0.5.0"
"source-map-support": "^0.5.0",
"pretty-format": "^22.4.0"
},
"devDependencies": {
"jest-runtime": "^22.4.2"
Expand Down
13 changes: 7 additions & 6 deletions packages/jest-jasmine2/src/expectation_result_factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,27 @@
* @flow
*/

import prettyFormat from 'pretty-format';

function messageFormatter({error, message, passed}) {
if (passed) {
return 'Passed.';
}
if (message) {
return message;
}
if (!error) {
return '';
if (typeof error === 'string') {
return error;
}
return error.message && error.name
? `${error.name}: ${error.message}`
: `${error.toString()} thrown`;
return `thrown: ${prettyFormat(error, {maxDepth: 3})}`;
}

function stackFormatter(options, errorMessage) {
if (options.passed) {
return '';
}
const {stack} = options.error || new Error(errorMessage);
const stack =
(options.error && options.error.stack) || new Error(errorMessage).stack;
return stack;
}

Expand Down
14 changes: 8 additions & 6 deletions packages/jest-jasmine2/src/jasmine/Env.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import queueRunner from '../queue_runner';
import treeProcessor from '../tree_processor';
import prettyFormat from 'pretty-format';

// Try getting the real promise object from the context, if available. Someone
// could have overridden it in a test. Async functions return it implicitly.
Expand Down Expand Up @@ -547,19 +548,20 @@ export default function(j$) {
};

this.fail = function(error) {
let message = 'Failed';
if (error) {
message += ': ';
message += error.message || error;
}
// duck-type Error, see #2549
const isError =
typeof error === 'object' &&
typeof error.message === 'string' &&
typeof error.name === 'string';
const message = `Failed: ${prettyFormat(error, {maxDepth: 3})}`;

currentRunnable().addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
message,
error: error && error.message ? error : null,
error: isError ? error : null,
});
};
}
Expand Down

0 comments on commit f235e2a

Please sign in to comment.