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

Implement numPassingAsserts of testCaseResult #13795

Merged
merged 29 commits into from Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f442c15
chore: numPassingAsserts type
ymqy Jan 21, 2023
edefeab
chore: numPassingAsserts default value
ymqy Jan 21, 2023
4173948
chore: increment numPassingAsserts
ymqy Jan 21, 2023
590003b
chore: numPassingAsserts type
ymqy Jan 21, 2023
559c28f
chore: add numPassingAsserts to testResult
ymqy Jan 21, 2023
a8e0584
chore: changelog
ymqy Jan 21, 2023
9ecbb59
chore: update changelog
ymqy Jan 21, 2023
d4f62c0
chore: fix ci
ymqy Jan 23, 2023
a423029
chore: TestEntry numPassingAsserts
ymqy Jan 23, 2023
cdfd96f
fix: missing numPassingAsserts
ymqy Jan 23, 2023
ba550ce
chore: numPassingAsserts unit test
ymqy Jan 24, 2023
82e450f
chore: AssertionCountsReporter e2e test
ymqy Jan 24, 2023
0418a30
chore: only test in jest-circus
ymqy Jan 24, 2023
94386e1
chore: update numPassingAsserts snapshot
ymqy Jan 24, 2023
249388c
chore: onNotJestJasmine helper
ymqy Jan 24, 2023
8e13c11
chore: remove hard code
ymqy Jan 24, 2023
e5408ae
chore: rename
ymqy Jan 24, 2023
2aa739f
chore: update fn name
ymqy Jan 24, 2023
886a709
chore: update export
ymqy Jan 24, 2023
bae470a
chore: update copyright
ymqy Jan 24, 2023
607bdb3
chore: use inline snapshot
ymqy Jan 24, 2023
309f98d
Merge branch 'main' into feature/numPassingAsserts
SimenB Jan 25, 2023
d683aaf
move changelog entry
SimenB Jan 25, 2023
e920161
chore: remove skipTestOnJasmine
ymqy Jan 25, 2023
7f2f2df
chore: customReportersOnCircus e2e test
ymqy Jan 25, 2023
9d0c78a
fix: ci error
ymqy Jan 25, 2023
f3dff25
Merge branch 'main' into feature/numPassingAsserts
ymqy Jan 26, 2023
e5cac79
Update CHANGELOG.md
ymqy Jan 26, 2023
565fef8
Update CHANGELOG.md
SimenB Jan 26, 2023
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 CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

### Features

- `[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))
- `[jest-core]` Add newlines to JSON output ([#13817](https://github.com/facebook/jest/pull/13817))

### Fixes
Expand Down
11 changes: 11 additions & 0 deletions e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Custom Reporters Integration on jest-circus valid failing assertion counts for adding reporters 1`] = `
"onTestCaseResult: adds fail, status: failed, numExpectations: 0
onTestFileResult testCaseResult 0: adds fail, status: failed, numExpectations: 0"
`;

exports[`Custom Reporters Integration on jest-circus valid passing assertion counts for adding reporters 1`] = `
"onTestCaseResult: adds ok, status: passed, numExpectations: 3
onTestFileResult testCaseResult 0: adds ok, status: passed, numExpectations: 3"
`;
42 changes: 42 additions & 0 deletions e2e/__tests__/customReportersOnCircus.test.ts
@@ -0,0 +1,42 @@
/**
* 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.
*/
import {skipSuiteOnJasmine} from '@jest/test-utils';
import runJest from '../runJest';

skipSuiteOnJasmine();

describe('Custom Reporters Integration on jest-circus', () => {
test('valid passing assertion counts for adding reporters', () => {
const {stdout} = runJest('custom-reporters', [
'--config',
JSON.stringify({
reporters: [
'default',
'<rootDir>/reporters/AssertionCountsReporter.js',
],
}),
'add.test.js',
]);

expect(stdout).toMatchSnapshot();
});

test('valid failing assertion counts for adding reporters', () => {
const {stdout} = runJest('custom-reporters', [
'--config',
JSON.stringify({
reporters: [
'default',
'<rootDir>/reporters/AssertionCountsReporter.js',
],
}),
'addFail.test.js',
]);

expect(stdout).toMatchSnapshot();
});
});
29 changes: 29 additions & 0 deletions e2e/custom-reporters/reporters/AssertionCountsReporter.js
@@ -0,0 +1,29 @@
/**
* 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.
*/

'use strict';

class AssertionCountsReporter {
onTestFileResult(test, testResult, aggregatedResult) {
testResult.testResults.forEach((testCaseResult, index) => {
console.log(
`onTestFileResult testCaseResult ${index}: ${testCaseResult.title}, ` +
`status: ${testCaseResult.status}, ` +
`numExpectations: ${testCaseResult.numPassingAsserts}`,
);
});
}
onTestCaseResult(test, testCaseResult) {
console.log(
`onTestCaseResult: ${testCaseResult.title}, ` +
`status: ${testCaseResult.status}, ` +
`numExpectations: ${testCaseResult.numPassingAsserts}`,
);
}
}

module.exports = AssertionCountsReporter;
1 change: 1 addition & 0 deletions packages/expect/__typetests__/expect.test.ts
Expand Up @@ -77,6 +77,7 @@ expectType<void>(
expectType<boolean>(this.isExpectingAssertions);
expectType<Error | undefined>(this.isExpectingAssertionsError);
expectType<boolean | undefined>(this.isNot);
expectType<number>(this.numPassingAsserts);
expectType<string | undefined>(this.promise);
expectType<Array<Error>>(this.suppressedErrors);
expectType<string | undefined>(this.testPath);
Expand Down
32 changes: 32 additions & 0 deletions packages/expect/src/__tests__/assertionCounts.test.ts
Expand Up @@ -44,3 +44,35 @@ describe('.hasAssertions()', () => {

it('hasAssertions not leaking to global state', () => {});
});

describe('numPassingAsserts', () => {
it('verify the default value of numPassingAsserts', () => {
const {numPassingAsserts} = jestExpect.getState();
expect(numPassingAsserts).toBe(0);
});

it('verify the resetting of numPassingAsserts after a test', () => {
expect('a').toBe('a');
expect('a').toBe('a');
// reset state
jestExpect.extractExpectedAssertionsErrors();
const {numPassingAsserts} = jestExpect.getState();
expect(numPassingAsserts).toBe(0);
});

it('verify the correctness of numPassingAsserts count for passing test', () => {
expect('a').toBe('a');
expect('a').toBe('a');
const {numPassingAsserts} = jestExpect.getState();
expect(numPassingAsserts).toBe(2);
});

it('verify the correctness of numPassingAsserts count for failing test', () => {
expect('a').toBe('a');
try {
expect('a').toBe('b');
} catch (error) {}
const {numPassingAsserts} = jestExpect.getState();
expect(numPassingAsserts).toBe(1);
});
});
1 change: 1 addition & 0 deletions packages/expect/src/extractExpectedAssertionsErrors.ts
Expand Up @@ -20,6 +20,7 @@ const resetAssertionsLocalState = () => {
assertionCalls: 0,
expectedAssertionsNumber: null,
isExpectingAssertions: false,
numPassingAsserts: 0,
});
};

Expand Down
2 changes: 2 additions & 0 deletions packages/expect/src/index.ts
Expand Up @@ -337,6 +337,8 @@ const makeThrowingMatcher = (
} else {
getState().suppressedErrors.push(error);
}
} else {
getState().numPassingAsserts++;
}
};

Expand Down
1 change: 1 addition & 0 deletions packages/expect/src/jestMatchersObject.ts
Expand Up @@ -29,6 +29,7 @@ if (!Object.prototype.hasOwnProperty.call(globalThis, JEST_MATCHERS_OBJECT)) {
assertionCalls: 0,
expectedAssertionsNumber: null,
isExpectingAssertions: false,
numPassingAsserts: 0,
suppressedErrors: [], // errors that are not thrown immediately.
};
Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, {
Expand Down
1 change: 1 addition & 0 deletions packages/expect/src/types.ts
Expand Up @@ -65,6 +65,7 @@ export interface MatcherState {
isExpectingAssertions: boolean;
isExpectingAssertionsError?: Error;
isNot?: boolean;
numPassingAsserts: number;
promise?: string;
suppressedErrors: Array<Error>;
testPath?: string;
Expand Down
Expand Up @@ -178,7 +178,7 @@ export const runAndTransformResultsToJestFormat = async ({
: ancestorTitles.join(' '),
invocations: testResult.invocations,
location: testResult.location,
numPassingAsserts: 0,
numPassingAsserts: testResult.numPassingAsserts,
retryReasons: testResult.retryReasons,
status,
title: testResult.testPath[testResult.testPath.length - 1],
Expand Down Expand Up @@ -238,6 +238,7 @@ const eventHandler = async (event: Circus.Event) => {
break;
}
case 'test_done': {
event.test.numPassingAsserts = jestExpect.getState().numPassingAsserts;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we reset it?

Copy link
Contributor Author

@ymqy ymqy Jan 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numPassingAsserts is reset to 0 after execution of _addExpectedAssertionErrors, reset method is called within jestExpect.extractExpectedAssertionsErrors method.

https://github.com/facebook/jest/blob/d683aafde24f2cf6f6cb5a0a71069fd6a0a55c36/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts#L249-L253

_addSuppressedErrors(event.test);
_addExpectedAssertionErrors(event.test);
break;
Expand Down
4 changes: 3 additions & 1 deletion packages/jest-circus/src/utils.ts
Expand Up @@ -78,6 +78,7 @@ export const makeTest = (
invocations: 0,
mode,
name: convertDescriptorToString(name),
numPassingAsserts: 0,
parent,
retryReasons: [],
seenDone: false,
Expand Down Expand Up @@ -363,6 +364,7 @@ export const makeSingleTestResult = (
errorsDetailed,
invocations: test.invocations,
location,
numPassingAsserts: test.numPassingAsserts,
retryReasons: test.retryReasons.map(_getError).map(getErrorStack),
status,
testPath: Array.from(testPath),
Expand Down Expand Up @@ -484,7 +486,7 @@ export const parseSingleTestResult = (
: ancestorTitles.join(' '),
invocations: testResult.invocations,
location: testResult.location,
numPassingAsserts: 0,
numPassingAsserts: testResult.numPassingAsserts,
retryReasons: Array.from(testResult.retryReasons),
status,
title: testResult.testPath[testResult.testPath.length - 1],
Expand Down
1 change: 1 addition & 0 deletions packages/jest-types/__typetests__/expect.test.ts
Expand Up @@ -446,6 +446,7 @@ expectType<void>(
expectType<boolean>(this.isExpectingAssertions);
expectType<Error | undefined>(this.isExpectingAssertionsError);
expectType<boolean | undefined>(this.isNot);
expectType<number>(this.numPassingAsserts);
expectType<string | undefined>(this.promise);
expectType<Array<Error>>(this.suppressedErrors);
expectType<string | undefined>(this.testPath);
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-types/src/Circus.ts
Expand Up @@ -185,6 +185,7 @@ export type TestResult = {
invocations: number;
status: TestStatus;
location?: {column: number; line: number} | null;
numPassingAsserts: number;
retryReasons: Array<FormattedError>;
testPath: Array<TestName | BlockName>;
};
Expand Down Expand Up @@ -245,6 +246,7 @@ export type TestEntry = {
mode: TestMode;
concurrent: boolean;
name: TestName;
numPassingAsserts: number;
parent: DescribeBlock;
startedAt?: number | null;
duration?: number | null;
Expand Down