Skip to content

Commit c78905c

Browse files
authored
Implement numPassingAsserts of testCaseResult (#13795)
1 parent be021fa commit c78905c

File tree

14 files changed

+129
-2
lines changed

14 files changed

+129
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Features
44

5+
- `[expect, jest-circus, @jest/types]` Implement `numPassingAsserts` of testResults to track the number of passing asserts in a test ([#13795](https://github.com/facebook/jest/pull/13795))
56
- `[jest-core]` Add newlines to JSON output ([#13817](https://github.com/facebook/jest/pull/13817))
67

78
### Fixes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Custom Reporters Integration on jest-circus valid failing assertion counts for adding reporters 1`] = `
4+
"onTestCaseResult: adds fail, status: failed, numExpectations: 0
5+
onTestFileResult testCaseResult 0: adds fail, status: failed, numExpectations: 0"
6+
`;
7+
8+
exports[`Custom Reporters Integration on jest-circus valid passing assertion counts for adding reporters 1`] = `
9+
"onTestCaseResult: adds ok, status: passed, numExpectations: 3
10+
onTestFileResult testCaseResult 0: adds ok, status: passed, numExpectations: 3"
11+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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+
import {skipSuiteOnJasmine} from '@jest/test-utils';
8+
import runJest from '../runJest';
9+
10+
skipSuiteOnJasmine();
11+
12+
describe('Custom Reporters Integration on jest-circus', () => {
13+
test('valid passing assertion counts for adding reporters', () => {
14+
const {stdout} = runJest('custom-reporters', [
15+
'--config',
16+
JSON.stringify({
17+
reporters: [
18+
'default',
19+
'<rootDir>/reporters/AssertionCountsReporter.js',
20+
],
21+
}),
22+
'add.test.js',
23+
]);
24+
25+
expect(stdout).toMatchSnapshot();
26+
});
27+
28+
test('valid failing assertion counts for adding reporters', () => {
29+
const {stdout} = runJest('custom-reporters', [
30+
'--config',
31+
JSON.stringify({
32+
reporters: [
33+
'default',
34+
'<rootDir>/reporters/AssertionCountsReporter.js',
35+
],
36+
}),
37+
'addFail.test.js',
38+
]);
39+
40+
expect(stdout).toMatchSnapshot();
41+
});
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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+
'use strict';
9+
10+
class AssertionCountsReporter {
11+
onTestFileResult(test, testResult, aggregatedResult) {
12+
testResult.testResults.forEach((testCaseResult, index) => {
13+
console.log(
14+
`onTestFileResult testCaseResult ${index}: ${testCaseResult.title}, ` +
15+
`status: ${testCaseResult.status}, ` +
16+
`numExpectations: ${testCaseResult.numPassingAsserts}`,
17+
);
18+
});
19+
}
20+
onTestCaseResult(test, testCaseResult) {
21+
console.log(
22+
`onTestCaseResult: ${testCaseResult.title}, ` +
23+
`status: ${testCaseResult.status}, ` +
24+
`numExpectations: ${testCaseResult.numPassingAsserts}`,
25+
);
26+
}
27+
}
28+
29+
module.exports = AssertionCountsReporter;

packages/expect/__typetests__/expect.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ expectType<void>(
7777
expectType<boolean>(this.isExpectingAssertions);
7878
expectType<Error | undefined>(this.isExpectingAssertionsError);
7979
expectType<boolean | undefined>(this.isNot);
80+
expectType<number>(this.numPassingAsserts);
8081
expectType<string | undefined>(this.promise);
8182
expectType<Array<Error>>(this.suppressedErrors);
8283
expectType<string | undefined>(this.testPath);

packages/expect/src/__tests__/assertionCounts.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,35 @@ describe('.hasAssertions()', () => {
4444

4545
it('hasAssertions not leaking to global state', () => {});
4646
});
47+
48+
describe('numPassingAsserts', () => {
49+
it('verify the default value of numPassingAsserts', () => {
50+
const {numPassingAsserts} = jestExpect.getState();
51+
expect(numPassingAsserts).toBe(0);
52+
});
53+
54+
it('verify the resetting of numPassingAsserts after a test', () => {
55+
expect('a').toBe('a');
56+
expect('a').toBe('a');
57+
// reset state
58+
jestExpect.extractExpectedAssertionsErrors();
59+
const {numPassingAsserts} = jestExpect.getState();
60+
expect(numPassingAsserts).toBe(0);
61+
});
62+
63+
it('verify the correctness of numPassingAsserts count for passing test', () => {
64+
expect('a').toBe('a');
65+
expect('a').toBe('a');
66+
const {numPassingAsserts} = jestExpect.getState();
67+
expect(numPassingAsserts).toBe(2);
68+
});
69+
70+
it('verify the correctness of numPassingAsserts count for failing test', () => {
71+
expect('a').toBe('a');
72+
try {
73+
expect('a').toBe('b');
74+
} catch (error) {}
75+
const {numPassingAsserts} = jestExpect.getState();
76+
expect(numPassingAsserts).toBe(1);
77+
});
78+
});

packages/expect/src/extractExpectedAssertionsErrors.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const resetAssertionsLocalState = () => {
2020
assertionCalls: 0,
2121
expectedAssertionsNumber: null,
2222
isExpectingAssertions: false,
23+
numPassingAsserts: 0,
2324
});
2425
};
2526

packages/expect/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ const makeThrowingMatcher = (
337337
} else {
338338
getState().suppressedErrors.push(error);
339339
}
340+
} else {
341+
getState().numPassingAsserts++;
340342
}
341343
};
342344

packages/expect/src/jestMatchersObject.ts

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ if (!Object.prototype.hasOwnProperty.call(globalThis, JEST_MATCHERS_OBJECT)) {
2929
assertionCalls: 0,
3030
expectedAssertionsNumber: null,
3131
isExpectingAssertions: false,
32+
numPassingAsserts: 0,
3233
suppressedErrors: [], // errors that are not thrown immediately.
3334
};
3435
Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, {

packages/expect/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface MatcherState {
6565
isExpectingAssertions: boolean;
6666
isExpectingAssertionsError?: Error;
6767
isNot?: boolean;
68+
numPassingAsserts: number;
6869
promise?: string;
6970
suppressedErrors: Array<Error>;
7071
testPath?: string;

packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export const runAndTransformResultsToJestFormat = async ({
178178
: ancestorTitles.join(' '),
179179
invocations: testResult.invocations,
180180
location: testResult.location,
181-
numPassingAsserts: 0,
181+
numPassingAsserts: testResult.numPassingAsserts,
182182
retryReasons: testResult.retryReasons,
183183
status,
184184
title: testResult.testPath[testResult.testPath.length - 1],
@@ -238,6 +238,7 @@ const eventHandler = async (event: Circus.Event) => {
238238
break;
239239
}
240240
case 'test_done': {
241+
event.test.numPassingAsserts = jestExpect.getState().numPassingAsserts;
241242
_addSuppressedErrors(event.test);
242243
_addExpectedAssertionErrors(event.test);
243244
break;

packages/jest-circus/src/utils.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export const makeTest = (
7878
invocations: 0,
7979
mode,
8080
name: convertDescriptorToString(name),
81+
numPassingAsserts: 0,
8182
parent,
8283
retryReasons: [],
8384
seenDone: false,
@@ -363,6 +364,7 @@ export const makeSingleTestResult = (
363364
errorsDetailed,
364365
invocations: test.invocations,
365366
location,
367+
numPassingAsserts: test.numPassingAsserts,
366368
retryReasons: test.retryReasons.map(_getError).map(getErrorStack),
367369
status,
368370
testPath: Array.from(testPath),
@@ -484,7 +486,7 @@ export const parseSingleTestResult = (
484486
: ancestorTitles.join(' '),
485487
invocations: testResult.invocations,
486488
location: testResult.location,
487-
numPassingAsserts: 0,
489+
numPassingAsserts: testResult.numPassingAsserts,
488490
retryReasons: Array.from(testResult.retryReasons),
489491
status,
490492
title: testResult.testPath[testResult.testPath.length - 1],

packages/jest-types/__typetests__/expect.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ expectType<void>(
446446
expectType<boolean>(this.isExpectingAssertions);
447447
expectType<Error | undefined>(this.isExpectingAssertionsError);
448448
expectType<boolean | undefined>(this.isNot);
449+
expectType<number>(this.numPassingAsserts);
449450
expectType<string | undefined>(this.promise);
450451
expectType<Array<Error>>(this.suppressedErrors);
451452
expectType<string | undefined>(this.testPath);

packages/jest-types/src/Circus.ts

+2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export type TestResult = {
185185
invocations: number;
186186
status: TestStatus;
187187
location?: {column: number; line: number} | null;
188+
numPassingAsserts: number;
188189
retryReasons: Array<FormattedError>;
189190
testPath: Array<TestName | BlockName>;
190191
};
@@ -245,6 +246,7 @@ export type TestEntry = {
245246
mode: TestMode;
246247
concurrent: boolean;
247248
name: TestName;
249+
numPassingAsserts: number;
248250
parent: DescribeBlock;
249251
startedAt?: number | null;
250252
duration?: number | null;

0 commit comments

Comments
 (0)