Skip to content

Commit 5f85233

Browse files
committed
add stringifying errors
1 parent 7b5e820 commit 5f85233

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import serializeToJSON from '../serializeToJSON';
9+
10+
// populate an object with all basic JavaScript datatypes
11+
const object = {
12+
species: 'capybara',
13+
ok: true,
14+
i: ['pull up'],
15+
hopOut: {
16+
atThe: 'after party',
17+
when: new Date('2000-07-14'),
18+
},
19+
chillness: 100,
20+
weight: 9.5,
21+
flaws: null,
22+
location: undefined,
23+
};
24+
25+
it('serializes regular objects like JSON.stringify', () => {
26+
expect(serializeToJSON(object)).toEqual(JSON.stringify(object));
27+
});
28+
29+
it('serializes errors', () => {
30+
const objectWithError = {
31+
...object,
32+
error: new Error('too cool'),
33+
};
34+
const withError = serializeToJSON(objectWithError);
35+
const withoutError = JSON.stringify(objectWithError);
36+
37+
expect(withoutError).not.toEqual(withError);
38+
39+
expect(withError).toContain(`"message":"too cool"`);
40+
expect(withError).toContain(`"name":"Error"`);
41+
expect(withError).toContain(`"stack":"Error:`);
42+
43+
expect(JSON.parse(withError)).toMatchObject({
44+
error: {
45+
message: 'too cool',
46+
name: 'Error',
47+
},
48+
});
49+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
/**
9+
* When we're asked to give a JSON output with the --json flag or otherwise,
10+
* some data we need to return don't serialize well with a basic
11+
* `JSON.stringify`, particularly Errors returned in `.openHandles`.
12+
*
13+
* This function handles the extended serialization wanted above.
14+
*/
15+
export default function serializeToJSON(
16+
value: any,
17+
space?: string | number,
18+
): string {
19+
return JSON.stringify(
20+
value,
21+
(_, value) => {
22+
// There might be more in Error, but pulling out just the message, name,
23+
// and stack should be good enough
24+
if (value instanceof Error) {
25+
return {
26+
message: value.message,
27+
name: value.name,
28+
stack: value.stack,
29+
};
30+
}
31+
return value;
32+
},
33+
space,
34+
);
35+
}

packages/jest-core/src/runJest.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import collectNodeHandles, {
3535
import getNoTestsFoundMessage from './getNoTestsFoundMessage';
3636
import runGlobalHook from './runGlobalHook';
3737
import type {Filter, TestRunData} from './types';
38+
import serializeToJSON from './lib/serializeToJSON';
3839

3940
const getTestPaths = async (
4041
globalConfig: Config.GlobalConfig,
@@ -111,20 +112,21 @@ const processResults = async (
111112
runResults = await processor(runResults);
112113
}
113114
if (isJSON) {
115+
const jsonString = serializeToJSON(formatTestResults(runResults));
114116
if (outputFile) {
115117
const cwd = tryRealpath(process.cwd());
116118
const filePath = path.resolve(cwd, outputFile);
117119

118120
fs.writeFileSync(
119121
filePath,
120-
`${JSON.stringify(formatTestResults(runResults))}\n`,
122+
`${jsonString}\n`,
121123
);
122124
outputStream.write(
123125
`Test results written to: ${path.relative(cwd, filePath)}\n`,
124126
);
125127
} else {
126128
process.stdout.write(
127-
`${JSON.stringify(formatTestResults(runResults))}\n`,
129+
`${jsonString}\n`,
128130
);
129131
}
130132
}

0 commit comments

Comments
 (0)