From 4f1cae76b3983f20aad13cb8c667635eb3e4d157 Mon Sep 17 00:00:00 2001 From: Dmitry Makhnev Date: Fri, 5 May 2023 14:20:14 +0200 Subject: [PATCH 1/5] ISSUE-13112: Add `onTestCaseStart` hook --- .../customReportersOnCircus.test.ts.snap | 22 ++++++ e2e/__tests__/customReportersOnCircus.test.ts | 51 +++++++++++++ .../__tests__/just2Tests.test.js | 19 +++++ e2e/custom-reporters/__tests__/skip.test.js | 13 ++++ .../reporters/TestCaseStartReporter.js | 32 ++++++++ .../jest-circus/src/testCaseReportHandler.ts | 12 ++- packages/jest-circus/src/utils.ts | 76 ++++++++++++++----- packages/jest-core/src/ReporterDispatcher.ts | 12 +++ packages/jest-core/src/TestScheduler.ts | 7 ++ packages/jest-reporters/src/types.ts | 6 +- packages/jest-test-result/src/types.ts | 3 +- packages/jest-types/src/Circus.ts | 13 +++- 12 files changed, 242 insertions(+), 24 deletions(-) create mode 100644 e2e/custom-reporters/__tests__/just2Tests.test.js create mode 100644 e2e/custom-reporters/__tests__/skip.test.js create mode 100644 e2e/custom-reporters/reporters/TestCaseStartReporter.js diff --git a/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap b/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap index 0f5823c60467..6ac4b3b552fe 100644 --- a/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap +++ b/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap @@ -14,3 +14,25 @@ exports[`Custom Reporters Integration on jest-circus push test case results for "onTestCaseResult: sample, status: todo, numExpectations: 0 onTestFileResult testCaseResult 0: sample, status: todo, numExpectations: 0" `; + +exports[`Custom Reporters Integration on jest-circus push test case results for skip tests 1`] = ` +"onTestCaseResult: sample, status: pending, numExpectations: 0 +onTestFileResult testCaseResult 0: sample, status: pending, numExpectations: 0" +`; + +exports[`Custom Reporters Integration on jest-circus push test case start 1`] = ` +"onTestCaseStart: test 1, mode: undefined, ancestorTitles: Custom Reporters +onTestCaseResult: test 1, status: passed +onTestCaseStart: test 2, mode: undefined, ancestorTitles: Custom Reporters +onTestCaseResult: test 2, status: passed" +`; + +exports[`Custom Reporters Integration on jest-circus push test case start for todo tests 1`] = ` +"onTestCaseStart: sample, mode: todo, ancestorTitles: Custom Reporters +onTestCaseResult: sample, status: todo" +`; + +exports[`Custom Reporters Integration on jest-circus push test case start for skip tests 1`] = ` +"onTestCaseStart: sample, mode: skip, ancestorTitles: Custom Reporters +onTestCaseResult: sample, status: pending" +`; diff --git a/e2e/__tests__/customReportersOnCircus.test.ts b/e2e/__tests__/customReportersOnCircus.test.ts index c6faf69467ae..bdf1d5d18354 100644 --- a/e2e/__tests__/customReportersOnCircus.test.ts +++ b/e2e/__tests__/customReportersOnCircus.test.ts @@ -54,4 +54,55 @@ describe('Custom Reporters Integration on jest-circus', () => { expect(stdout).toMatchSnapshot(); }); + + test('push test case results for skip tests', () => { + const {stdout} = runJest('custom-reporters', [ + '--config', + JSON.stringify({ + reporters: [ + 'default', + '/reporters/AssertionCountsReporter.js', + ], + }), + 'skip.test.js', + ]); + + expect(stdout).toMatchSnapshot(); + }); + + test('push test case start', () => { + const {stdout} = runJest('custom-reporters', [ + '--config', + JSON.stringify({ + reporters: ['default', '/reporters/TestCaseStartReporter.js'], + }), + 'just2Tests.test.js', + ]); + + expect(stdout).toMatchSnapshot(); + }); + + test('push test case start for todo tests', () => { + const {stdout} = runJest('custom-reporters', [ + '--config', + JSON.stringify({ + reporters: ['default', '/reporters/TestCaseStartReporter.js'], + }), + 'todo.test.js', + ]); + + expect(stdout).toMatchSnapshot(); + }); + + test('push test case start for skip tests', () => { + const {stdout} = runJest('custom-reporters', [ + '--config', + JSON.stringify({ + reporters: ['default', '/reporters/TestCaseStartReporter.js'], + }), + 'skip.test.js', + ]); + + expect(stdout).toMatchSnapshot(); + }); }); diff --git a/e2e/custom-reporters/__tests__/just2Tests.test.js b/e2e/custom-reporters/__tests__/just2Tests.test.js new file mode 100644 index 000000000000..ab8a346ac71f --- /dev/null +++ b/e2e/custom-reporters/__tests__/just2Tests.test.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +'use strict'; + +describe('Custom Reporters', () => { + it('test 1', () => { + expect(true).toBeTruthy(); + }); + + it('test 2', () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/e2e/custom-reporters/__tests__/skip.test.js b/e2e/custom-reporters/__tests__/skip.test.js new file mode 100644 index 000000000000..a0a6088a8f20 --- /dev/null +++ b/e2e/custom-reporters/__tests__/skip.test.js @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +'use strict'; + +describe('Custom Reporters', () => { + it.skip('sample', () => {}); +}); diff --git a/e2e/custom-reporters/reporters/TestCaseStartReporter.js b/e2e/custom-reporters/reporters/TestCaseStartReporter.js new file mode 100644 index 000000000000..8afd1e7f6634 --- /dev/null +++ b/e2e/custom-reporters/reporters/TestCaseStartReporter.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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 + * @implements {import('@jest/reporters').Reporter} + */ +class TestCaseStartReporter { + onTestCaseStart(test, testCaseStartInfo) { + const mode = + testCaseStartInfo.mode != null ? testCaseStartInfo.mode : 'undefined'; + console.log( + `onTestCaseStart: ${testCaseStartInfo.title}, ` + + `mode: ${mode}, ` + + `ancestorTitles: ${testCaseStartInfo.ancestorTitles.join('.')}`, + ); + } + onTestCaseResult(test, testCaseResult) { + console.log( + `onTestCaseResult: ${testCaseResult.title}, ` + + `status: ${testCaseResult.status}`, + ); + } +} + +module.exports = TestCaseStartReporter; diff --git a/packages/jest-circus/src/testCaseReportHandler.ts b/packages/jest-circus/src/testCaseReportHandler.ts index f7633db2622e..fd41c127a861 100644 --- a/packages/jest-circus/src/testCaseReportHandler.ts +++ b/packages/jest-circus/src/testCaseReportHandler.ts @@ -7,12 +7,22 @@ import type {TestFileEvent} from '@jest/test-result'; import type {Circus} from '@jest/types'; -import {makeSingleTestResult, parseSingleTestResult} from './utils'; +import { + createTestCaseStartInfo, + makeSingleTestResult, + parseSingleTestResult, +} from './utils'; const testCaseReportHandler = (testPath: string, sendMessageToJest: TestFileEvent) => (event: Circus.Event): void => { switch (event.name) { + case 'test_start': { + const testCaseStartInfo = createTestCaseStartInfo(event.test); + sendMessageToJest('test-case-start', [testPath, testCaseStartInfo]); + break; + } + case 'test_skip': case 'test_todo': case 'test_done': { const testResult = makeSingleTestResult(event.test); diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts index 13cf3b321e05..ff8f3bd55022 100644 --- a/packages/jest-circus/src/utils.ts +++ b/packages/jest-circus/src/utils.ts @@ -328,19 +328,25 @@ export const makeRunResult = ( unhandledErrors: unhandledErrors.map(_getError).map(getErrorStack), }); +const getTestNamesPath = (test: Circus.TestEntry): Circus.TestNamesPath => { + const titles = []; + let parent: Circus.TestEntry | Circus.DescribeBlock | undefined = test; + do { + titles.unshift(parent.name); + } while ((parent = parent.parent)); + + return titles; +}; + export const makeSingleTestResult = ( test: Circus.TestEntry, ): Circus.TestResult => { const {includeTestLocationInResult} = getState(); - const testPath = []; - let parent: Circus.TestEntry | Circus.DescribeBlock | undefined = test; const {status} = test; invariant(status, 'Status should be present after tests are run.'); - do { - testPath.unshift(parent.name); - } while ((parent = parent.parent)); + const testPath = getTestNamesPath(test); let location = null; if (includeTestLocationInResult) { @@ -402,14 +408,9 @@ const makeTestResults = ( // Return a string that identifies the test (concat of parent describe block // names + test title) export const getTestID = (test: Circus.TestEntry): string => { - const titles = []; - let parent: Circus.TestEntry | Circus.DescribeBlock | undefined = test; - do { - titles.unshift(parent.name); - } while ((parent = parent.parent)); - - titles.shift(); // remove TOP_DESCRIBE_BLOCK_NAME - return titles.join(' '); + const testNamesPath = getTestNamesPath(test); + testNamesPath.shift(); // remove TOP_DESCRIBE_BLOCK_NAME + return testNamesPath.join(' '); }; const _getError = ( @@ -464,6 +465,29 @@ export function invariant( } } +type TestDescription = { + ancestorTitles: Array; + fullName: string; + title: string; +}; + +const resolveTestCaseStartInfo = ( + testNamesPath: Circus.TestNamesPath, +): TestDescription => { + const ancestorTitles = testNamesPath.filter( + name => name !== ROOT_DESCRIBE_BLOCK_NAME, + ); + const fullName = ancestorTitles.join(' '); + const title = testNamesPath[testNamesPath.length - 1]; + // remove title + ancestorTitles.pop(); + return { + ancestorTitles, + fullName, + title, + }; +}; + export const parseSingleTestResult = ( testResult: Circus.TestResult, ): AssertionResult => { @@ -478,24 +502,36 @@ export const parseSingleTestResult = ( status = 'passed'; } - const ancestorTitles = testResult.testPath.filter( - name => name !== ROOT_DESCRIBE_BLOCK_NAME, + const {ancestorTitles, fullName, title} = resolveTestCaseStartInfo( + testResult.testPath, ); - const title = ancestorTitles.pop(); return { ancestorTitles, duration: testResult.duration, failureDetails: testResult.errorsDetailed, failureMessages: Array.from(testResult.errors), - fullName: title - ? ancestorTitles.concat(title).join(' ') - : ancestorTitles.join(' '), + fullName, invocations: testResult.invocations, location: testResult.location, numPassingAsserts: testResult.numPassingAsserts, retryReasons: Array.from(testResult.retryReasons), status, - title: testResult.testPath[testResult.testPath.length - 1], + title, + }; +}; + +export const createTestCaseStartInfo = ( + test: Circus.TestEntry, +): Circus.TestCaseStartInfo => { + const testPath = getTestNamesPath(test); + const {ancestorTitles, fullName, title} = resolveTestCaseStartInfo(testPath); + + return { + ancestorTitles, + fullName, + mode: test.mode, + startedAt: test.startedAt, + title, }; }; diff --git a/packages/jest-core/src/ReporterDispatcher.ts b/packages/jest-core/src/ReporterDispatcher.ts index b3683bbffb4f..2ab01253315d 100644 --- a/packages/jest-core/src/ReporterDispatcher.ts +++ b/packages/jest-core/src/ReporterDispatcher.ts @@ -13,6 +13,7 @@ import type { TestContext, TestResult, } from '@jest/test-result'; +import type {Circus} from '@jest/types'; import type {ReporterConstructor} from './TestScheduler'; export default class ReporterDispatcher { @@ -69,6 +70,17 @@ export default class ReporterDispatcher { } } + async onTestCaseStart( + test: Test, + testCaseStartInfo: Circus.TestCaseStartInfo, + ): Promise { + for (const reporter of this._reporters) { + if (reporter.onTestCaseStart) { + await reporter.onTestCaseStart(test, testCaseStartInfo); + } + } + } + async onTestCaseResult( test: Test, testCaseResult: TestCaseResult, diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 00ad2b053768..2c53db5a41fc 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -257,6 +257,13 @@ class TestScheduler { testRunner.on('test-file-failure', ([test, error]) => onFailure(test, error), ), + testRunner.on( + 'test-case-start', + ([testPath, testCaseStartInfo]) => { + const test: Test = {context, path: testPath}; + this._dispatcher.onTestCaseStart(test, testCaseStartInfo); + }, + ), testRunner.on( 'test-case-result', ([testPath, testCaseResult]) => { diff --git a/packages/jest-reporters/src/types.ts b/packages/jest-reporters/src/types.ts index dbf0361c7c1f..f7cfd50e0fb9 100644 --- a/packages/jest-reporters/src/types.ts +++ b/packages/jest-reporters/src/types.ts @@ -12,7 +12,7 @@ import type { TestContext, TestResult, } from '@jest/test-result'; -import type {Config} from '@jest/types'; +import type {Circus, Config} from '@jest/types'; export type ReporterOnStartOptions = { estimatedTime: number; @@ -30,6 +30,10 @@ export interface Reporter { testResult: TestResult, aggregatedResult: AggregatedResult, ) => Promise | void; + readonly onTestCaseStart?: ( + test: Test, + testCaseStartInfo: Circus.TestCaseStartInfo, + ) => Promise | void; readonly onTestCaseResult?: ( test: Test, testCaseResult: TestCaseResult, diff --git a/packages/jest-test-result/src/types.ts b/packages/jest-test-result/src/types.ts index 9bff7590784c..acab4be765ad 100644 --- a/packages/jest-test-result/src/types.ts +++ b/packages/jest-test-result/src/types.ts @@ -8,7 +8,7 @@ import type {V8Coverage} from 'collect-v8-coverage'; import type {CoverageMap, CoverageMapData} from 'istanbul-lib-coverage'; import type {ConsoleBuffer} from '@jest/console'; -import type {Config, TestResult, TransformTypes} from '@jest/types'; +import type {Circus, Config, TestResult, TransformTypes} from '@jest/types'; import type {IHasteFS, IModuleMap} from 'jest-haste-map'; import type Resolver from 'jest-resolve'; @@ -197,6 +197,7 @@ export type TestEvents = { 'test-file-start': [Test]; 'test-file-success': [Test, TestResult]; 'test-file-failure': [Test, SerializableError]; + 'test-case-start': [string, Circus.TestCaseStartInfo]; 'test-case-result': [string, AssertionResult]; }; diff --git a/packages/jest-types/src/Circus.ts b/packages/jest-types/src/Circus.ts index f7d1c0374923..9a9aa5089874 100644 --- a/packages/jest-types/src/Circus.ts +++ b/packages/jest-types/src/Circus.ts @@ -178,6 +178,17 @@ export type MatcherResults = { }; export type TestStatus = 'skip' | 'done' | 'todo'; + +export type TestNamesPath = Array; + +export type TestCaseStartInfo = { + ancestorTitles: Array; + fullName: string; + mode: TestMode; + title: string; + startedAt?: number | null; +}; + export type TestResult = { duration?: number | null; errors: Array; @@ -187,7 +198,7 @@ export type TestResult = { location?: {column: number; line: number} | null; numPassingAsserts: number; retryReasons: Array; - testPath: Array; + testPath: TestNamesPath; }; export type RunResult = { From 817c9b8bcc071a41821cd84eb45c2eb3b1d0884b Mon Sep 17 00:00:00 2001 From: Dmitry Makhnev Date: Fri, 5 May 2023 14:20:53 +0200 Subject: [PATCH 2/5] ISSUE-13112: Refactor `onTestCaseStart` hook calling to more stable and transparent approach - clean previous approach - add `test_started` event to Circus runner - fix tests for `test_started` event --- .../customReportersOnCircus.test.ts.snap | 19 +++---------------- e2e/__tests__/customReportersOnCircus.test.ts | 19 ++----------------- e2e/__tests__/testEnvironmentCircus.test.ts | 2 ++ .../testEnvironmentCircusAsync.test.ts | 2 ++ .../reporters/TestCaseStartReporter.js | 6 ------ .../src/__mocks__/testEventHandler.ts | 1 + .../__snapshots__/afterAll.test.ts.snap | 7 +++++++ .../__snapshots__/baseTest.test.ts.snap | 5 +++++ .../__snapshots__/hooks.test.ts.snap | 10 ++++++++++ .../__snapshots__/randomizeTest.test.ts.snap | 5 +++++ packages/jest-circus/src/run.ts | 2 ++ .../jest-circus/src/testCaseReportHandler.ts | 3 +-- packages/jest-types/src/Circus.ts | 4 ++++ 13 files changed, 44 insertions(+), 41 deletions(-) diff --git a/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap b/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap index 6ac4b3b552fe..e52b96c3dbb6 100644 --- a/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap +++ b/e2e/__tests__/__snapshots__/customReportersOnCircus.test.ts.snap @@ -15,24 +15,11 @@ exports[`Custom Reporters Integration on jest-circus push test case results for onTestFileResult testCaseResult 0: sample, status: todo, numExpectations: 0" `; -exports[`Custom Reporters Integration on jest-circus push test case results for skip tests 1`] = ` -"onTestCaseResult: sample, status: pending, numExpectations: 0 -onTestFileResult testCaseResult 0: sample, status: pending, numExpectations: 0" -`; - exports[`Custom Reporters Integration on jest-circus push test case start 1`] = ` "onTestCaseStart: test 1, mode: undefined, ancestorTitles: Custom Reporters -onTestCaseResult: test 1, status: passed -onTestCaseStart: test 2, mode: undefined, ancestorTitles: Custom Reporters -onTestCaseResult: test 2, status: passed" +onTestCaseStart: test 2, mode: undefined, ancestorTitles: Custom Reporters" `; -exports[`Custom Reporters Integration on jest-circus push test case start for todo tests 1`] = ` -"onTestCaseStart: sample, mode: todo, ancestorTitles: Custom Reporters -onTestCaseResult: sample, status: todo" -`; +exports[`Custom Reporters Integration on jest-circus doesn't push test case start for skip tests 1`] = `""`; -exports[`Custom Reporters Integration on jest-circus push test case start for skip tests 1`] = ` -"onTestCaseStart: sample, mode: skip, ancestorTitles: Custom Reporters -onTestCaseResult: sample, status: pending" -`; +exports[`Custom Reporters Integration on jest-circus doesn't push test case start for todo tests 1`] = `""`; diff --git a/e2e/__tests__/customReportersOnCircus.test.ts b/e2e/__tests__/customReportersOnCircus.test.ts index bdf1d5d18354..2dbe0b248cae 100644 --- a/e2e/__tests__/customReportersOnCircus.test.ts +++ b/e2e/__tests__/customReportersOnCircus.test.ts @@ -55,21 +55,6 @@ describe('Custom Reporters Integration on jest-circus', () => { expect(stdout).toMatchSnapshot(); }); - test('push test case results for skip tests', () => { - const {stdout} = runJest('custom-reporters', [ - '--config', - JSON.stringify({ - reporters: [ - 'default', - '/reporters/AssertionCountsReporter.js', - ], - }), - 'skip.test.js', - ]); - - expect(stdout).toMatchSnapshot(); - }); - test('push test case start', () => { const {stdout} = runJest('custom-reporters', [ '--config', @@ -82,7 +67,7 @@ describe('Custom Reporters Integration on jest-circus', () => { expect(stdout).toMatchSnapshot(); }); - test('push test case start for todo tests', () => { + test("doesn't push test case start for todo tests", () => { const {stdout} = runJest('custom-reporters', [ '--config', JSON.stringify({ @@ -94,7 +79,7 @@ describe('Custom Reporters Integration on jest-circus', () => { expect(stdout).toMatchSnapshot(); }); - test('push test case start for skip tests', () => { + test("doesn't push test case start for skip tests", () => { const {stdout} = runJest('custom-reporters', [ '--config', JSON.stringify({ diff --git a/e2e/__tests__/testEnvironmentCircus.test.ts b/e2e/__tests__/testEnvironmentCircus.test.ts index aec50e7c2b10..1cfc2a8c8d49 100644 --- a/e2e/__tests__/testEnvironmentCircus.test.ts +++ b/e2e/__tests__/testEnvironmentCircus.test.ts @@ -23,6 +23,7 @@ it('calls testEnvironment handleTestEvent', () => { "run_start", "run_describe_start", "test_start: test name here", + "test_started: test name here", "hook_start", "hook_success: test name here", "hook_start", @@ -31,6 +32,7 @@ it('calls testEnvironment handleTestEvent', () => { "test_fn_success: test name here", "test_done: test name here", "test_start: second test name here", + "test_started: second test name here", "hook_start", "hook_success: second test name here", "hook_start", diff --git a/e2e/__tests__/testEnvironmentCircusAsync.test.ts b/e2e/__tests__/testEnvironmentCircusAsync.test.ts index 56692be0c21f..90a4311e95ee 100644 --- a/e2e/__tests__/testEnvironmentCircusAsync.test.ts +++ b/e2e/__tests__/testEnvironmentCircusAsync.test.ts @@ -36,6 +36,7 @@ it('calls asynchronous handleTestEvent in testEnvironment', () => { "run_describe_start", "run_describe_start", "test_start: passing test", + "test_started: passing test", "hook_start: beforeEach", "hook_success: beforeEach", "hook_start: beforeEach", @@ -46,6 +47,7 @@ it('calls asynchronous handleTestEvent in testEnvironment', () => { "hook_failure: afterEach", "test_done: passing test", "test_start: failing test", + "test_started: failing test", "hook_start: beforeEach", "hook_success: beforeEach", "hook_start: beforeEach", diff --git a/e2e/custom-reporters/reporters/TestCaseStartReporter.js b/e2e/custom-reporters/reporters/TestCaseStartReporter.js index 8afd1e7f6634..096957ddefae 100644 --- a/e2e/custom-reporters/reporters/TestCaseStartReporter.js +++ b/e2e/custom-reporters/reporters/TestCaseStartReporter.js @@ -21,12 +21,6 @@ class TestCaseStartReporter { `ancestorTitles: ${testCaseStartInfo.ancestorTitles.join('.')}`, ); } - onTestCaseResult(test, testCaseResult) { - console.log( - `onTestCaseResult: ${testCaseResult.title}, ` + - `status: ${testCaseResult.status}`, - ); - } } module.exports = TestCaseStartReporter; diff --git a/packages/jest-circus/src/__mocks__/testEventHandler.ts b/packages/jest-circus/src/__mocks__/testEventHandler.ts index cfdaef275c79..b3c20200ac64 100644 --- a/packages/jest-circus/src/__mocks__/testEventHandler.ts +++ b/packages/jest-circus/src/__mocks__/testEventHandler.ts @@ -20,6 +20,7 @@ const testEventHandler: Circus.EventHandler = (event, state) => { break; } case 'test_start': + case 'test_started': case 'test_retry': case 'test_done': { console.log(`${event.name}:`, event.test.name); diff --git a/packages/jest-circus/src/__tests__/__snapshots__/afterAll.test.ts.snap b/packages/jest-circus/src/__tests__/__snapshots__/afterAll.test.ts.snap index 8ae3e7150ae1..0f4a157cbb31 100644 --- a/packages/jest-circus/src/__tests__/__snapshots__/afterAll.test.ts.snap +++ b/packages/jest-circus/src/__tests__/__snapshots__/afterAll.test.ts.snap @@ -54,6 +54,7 @@ hook_start: beforeAll hook_success: beforeAll run_describe_start: child describe test_start: my test +test_started: my test hook_start: beforeEach > beforeEach hook_success: beforeEach @@ -132,24 +133,29 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one test_fn_start: one test_fn_success: one test_done: one test_start: two +test_started: two test_fn_start: two test_fn_success: two test_done: two run_describe_start: 2nd level describe test_start: 2nd level test +test_started: 2nd level test test_fn_start: 2nd level test test_fn_success: 2nd level test test_done: 2nd level test run_describe_start: 3rd level describe test_start: 3rd level test +test_started: 3rd level test test_fn_start: 3rd level test test_fn_success: 3rd level test test_done: 3rd level test test_start: 3rd level test#2 +test_started: 3rd level test#2 test_fn_start: 3rd level test#2 test_fn_success: 3rd level test#2 test_done: 3rd level test#2 @@ -162,6 +168,7 @@ hook_success: afterAll run_describe_finish: describe run_describe_start: 2nd describe test_start: 2nd describe test +test_started: 2nd describe test test_fn_start: 2nd describe test test_fn_success: 2nd describe test test_done: 2nd describe test diff --git a/packages/jest-circus/src/__tests__/__snapshots__/baseTest.test.ts.snap b/packages/jest-circus/src/__tests__/__snapshots__/baseTest.test.ts.snap index f44411f9ac58..531ff0e13f1f 100644 --- a/packages/jest-circus/src/__tests__/__snapshots__/baseTest.test.ts.snap +++ b/packages/jest-circus/src/__tests__/__snapshots__/baseTest.test.ts.snap @@ -11,6 +11,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one hook_start: beforeEach hook_success: beforeEach test_fn_start: one @@ -19,6 +20,7 @@ hook_start: afterEach hook_failure: afterEach test_done: one test_start: two +test_started: two hook_start: beforeEach hook_success: beforeEach test_fn_start: two @@ -41,6 +43,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describer test_start: One +test_started: One test_fn_start: One test_fn_success: One test_done: One @@ -62,6 +65,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one hook_start: beforeEach hook_success: beforeEach test_fn_start: one @@ -70,6 +74,7 @@ hook_start: afterEach hook_success: afterEach test_done: one test_start: two +test_started: two hook_start: beforeEach hook_success: beforeEach test_fn_start: two diff --git a/packages/jest-circus/src/__tests__/__snapshots__/hooks.test.ts.snap b/packages/jest-circus/src/__tests__/__snapshots__/hooks.test.ts.snap index 465511f31286..277e3c17e2f7 100644 --- a/packages/jest-circus/src/__tests__/__snapshots__/hooks.test.ts.snap +++ b/packages/jest-circus/src/__tests__/__snapshots__/hooks.test.ts.snap @@ -17,6 +17,7 @@ hook_start: beforeAll > beforeAll 1 hook_success: beforeAll test_start: test 1 +test_started: test 1 test_fn_start: test 1 > test 1 test_fn_success: test 1 @@ -26,11 +27,13 @@ hook_start: beforeAll > beforeAll 2 hook_success: beforeAll test_start: test 2 +test_started: test 2 test_fn_start: test 2 > test 2 test_fn_success: test 2 test_done: test 2 test_start: test 3 +test_started: test 3 test_fn_start: test 3 > test 3 test_fn_success: test 3 @@ -65,6 +68,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one hook_start: beforeEach > describe beforeEach hook_success: beforeEach @@ -72,6 +76,7 @@ test_fn_start: one test_fn_success: one test_done: one test_start: two +test_started: two hook_start: beforeEach > describe beforeEach hook_success: beforeEach @@ -80,6 +85,7 @@ test_fn_success: two test_done: two run_describe_start: 2nd level describe test_start: 2nd level test +test_started: 2nd level test hook_start: beforeEach > describe beforeEach hook_success: beforeEach @@ -91,6 +97,7 @@ test_fn_success: 2nd level test test_done: 2nd level test run_describe_start: 3rd level describe test_start: 3rd level test +test_started: 3rd level test hook_start: beforeEach > describe beforeEach hook_success: beforeEach @@ -101,6 +108,7 @@ test_fn_start: 3rd level test test_fn_success: 3rd level test test_done: 3rd level test test_start: 3rd level test#2 +test_started: 3rd level test#2 hook_start: beforeEach > describe beforeEach hook_success: beforeEach @@ -115,6 +123,7 @@ run_describe_finish: 2nd level describe run_describe_finish: describe run_describe_start: 2nd describe test_start: 2nd describe test +test_started: 2nd describe test hook_start: beforeEach > 2nd describe beforeEach that throws hook_failure: beforeEach @@ -140,6 +149,7 @@ run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe 1 run_describe_start: 2nd level describe test_start: test +test_started: test hook_start: beforeEach before each 1 hook_success: beforeEach diff --git a/packages/jest-circus/src/__tests__/__snapshots__/randomizeTest.test.ts.snap b/packages/jest-circus/src/__tests__/__snapshots__/randomizeTest.test.ts.snap index f44411f9ac58..531ff0e13f1f 100644 --- a/packages/jest-circus/src/__tests__/__snapshots__/randomizeTest.test.ts.snap +++ b/packages/jest-circus/src/__tests__/__snapshots__/randomizeTest.test.ts.snap @@ -11,6 +11,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one hook_start: beforeEach hook_success: beforeEach test_fn_start: one @@ -19,6 +20,7 @@ hook_start: afterEach hook_failure: afterEach test_done: one test_start: two +test_started: two hook_start: beforeEach hook_success: beforeEach test_fn_start: two @@ -41,6 +43,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describer test_start: One +test_started: One test_fn_start: One test_fn_success: One test_done: One @@ -62,6 +65,7 @@ run_start run_describe_start: ROOT_DESCRIBE_BLOCK run_describe_start: describe test_start: one +test_started: one hook_start: beforeEach hook_success: beforeEach test_fn_start: one @@ -70,6 +74,7 @@ hook_start: afterEach hook_success: afterEach test_done: one test_start: two +test_started: two hook_start: beforeEach hook_success: beforeEach test_fn_start: two diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts index 7ccaf2d2e187..ec07b7d13dfd 100644 --- a/packages/jest-circus/src/run.ts +++ b/packages/jest-circus/src/run.ts @@ -166,6 +166,8 @@ const _runTest = async ( return; } + await dispatch({name: 'test_started', test}); + const {afterEach, beforeEach} = getEachHooksForTest(test); for (const hook of beforeEach) { diff --git a/packages/jest-circus/src/testCaseReportHandler.ts b/packages/jest-circus/src/testCaseReportHandler.ts index fd41c127a861..c1d987225518 100644 --- a/packages/jest-circus/src/testCaseReportHandler.ts +++ b/packages/jest-circus/src/testCaseReportHandler.ts @@ -17,12 +17,11 @@ const testCaseReportHandler = (testPath: string, sendMessageToJest: TestFileEvent) => (event: Circus.Event): void => { switch (event.name) { - case 'test_start': { + case 'test_started': { const testCaseStartInfo = createTestCaseStartInfo(event.test); sendMessageToJest('test-case-start', [testPath, testCaseStartInfo]); break; } - case 'test_skip': case 'test_todo': case 'test_done': { const testResult = makeSingleTestResult(event.test); diff --git a/packages/jest-types/src/Circus.ts b/packages/jest-types/src/Circus.ts index 9a9aa5089874..2b27c314f541 100644 --- a/packages/jest-types/src/Circus.ts +++ b/packages/jest-types/src/Circus.ts @@ -142,6 +142,10 @@ export type AsyncEvent = name: 'test_todo'; test: TestEntry; } + | { + name: 'test_started'; + test: TestEntry; + } | { // test failure is defined by presence of errors in `test.errors`, // `test_done` indicates that the test and all its hooks were run, From 063eb4ed9d7be71ce2d5ac38da66675e16cd6499 Mon Sep 17 00:00:00 2001 From: Dmitry Makhnev Date: Tue, 9 May 2023 00:09:28 +0200 Subject: [PATCH 3/5] ISSUE-13112: Fix docs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f6424a496c5..cdec308c4e35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - `[jest-cli]` Include type definitions to generated config files ([#14078](https://github.com/facebook/jest/pull/14078)) - `[jest-snapshot]` Support arrays as property matchers ([#14025](https://github.com/facebook/jest/pull/14025)) +- `[jest-core, jest-circus, jest-reporter, jest-runner]` Added support for reporting about start individual test cases using jest-circus ([#](https://github.com/facebook/jest/pull/)) ### Fixes From 05641b986023e29bc63d0f8c2926e0474b00eff0 Mon Sep 17 00:00:00 2001 From: Dmitry Makhnev Date: Fri, 26 May 2023 11:13:45 +0300 Subject: [PATCH 4/5] ISSUE-13112: Fix docs --- packages/jest-reporters/src/types.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/jest-reporters/src/types.ts b/packages/jest-reporters/src/types.ts index f7cfd50e0fb9..3f285ba9f285 100644 --- a/packages/jest-reporters/src/types.ts +++ b/packages/jest-reporters/src/types.ts @@ -30,6 +30,10 @@ export interface Reporter { testResult: TestResult, aggregatedResult: AggregatedResult, ) => Promise | void; + /** + * Called before running a spec (prior to `before` hooks) + * Not called for `skipped` and `todo` specs + */ readonly onTestCaseStart?: ( test: Test, testCaseStartInfo: Circus.TestCaseStartInfo, From cbd4a0e7114b934edefb8334e68cf7839e7dcfff Mon Sep 17 00:00:00 2001 From: Dmitry Makhnev Date: Wed, 31 May 2023 18:01:31 +0200 Subject: [PATCH 5/5] ISSUE-13112: Fix changelog with link to PR --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdec308c4e35..32e35704ae89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - `[jest-cli]` Include type definitions to generated config files ([#14078](https://github.com/facebook/jest/pull/14078)) - `[jest-snapshot]` Support arrays as property matchers ([#14025](https://github.com/facebook/jest/pull/14025)) -- `[jest-core, jest-circus, jest-reporter, jest-runner]` Added support for reporting about start individual test cases using jest-circus ([#](https://github.com/facebook/jest/pull/)) +- `[jest-core, jest-circus, jest-reporter, jest-runner]` Added support for reporting about start individual test cases using jest-circus ([#14174](https://github.com/jestjs/jest/pull/14174)) ### Fixes