diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e5947320ebe..c12bd0ed0e2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +- `[jest-reporters]` Fix issue where console output not displayed for GHA reporter even with `silent: false` option ([#15864](https://github.com/jestjs/jest/pull/15864)) - `[jest-runtime]` Fix issue where user cannot utilize dynamic import despite specifying `--experimental-vm-modules` Node option ([#15842](https://github.com/jestjs/jest/pull/15842)) - `[jest-test-sequencer]` Fix issue where failed tests due to compilation errors not getting re-executed even with `--onlyFailures` CLI option ([#15851](https://github.com/jestjs/jest/pull/15851)) diff --git a/packages/jest-reporters/src/GitHubActionsReporter.ts b/packages/jest-reporters/src/GitHubActionsReporter.ts index c25cb5c189b0..ddb5134b966c 100644 --- a/packages/jest-reporters/src/GitHubActionsReporter.ts +++ b/packages/jest-reporters/src/GitHubActionsReporter.ts @@ -7,6 +7,7 @@ import {stripVTControlCharacters as stripAnsi} from 'util'; import chalk from 'chalk'; +import {type ConsoleBuffer, getConsoleOutput} from '@jest/console'; import type { AggregatedResult, AssertionResult, @@ -66,12 +67,14 @@ type ResultTree = { export default class GitHubActionsReporter extends BaseReporter { static readonly filename = __filename; private readonly options: {silent: boolean}; + private readonly globalConfig: Config.GlobalConfig; constructor( - _globalConfig: Config.GlobalConfig, + globalConfig: Config.GlobalConfig, reporterOptions: {silent?: boolean} = {}, ) { super(); + this.globalConfig = globalConfig; this.options = { silent: typeof reporterOptions.silent === 'boolean' @@ -90,7 +93,7 @@ export default class GitHubActionsReporter extends BaseReporter { this.printFullResult(test.context, testResult); } if (this.isLastTestSuite(aggregatedResults)) { - this.printFailedTestLogs(test, aggregatedResults); + this.printFailedTestLogs(test, testResult.console, aggregatedResults); } } @@ -179,7 +182,7 @@ export default class GitHubActionsReporter extends BaseReporter { testDir, results.perfStats, ); - this.printResultTree(resultTree); + this.printResultTree(resultTree, context.config, results.console); } private arrayEqual(a1: Array, a2: Array): boolean { @@ -311,7 +314,11 @@ export default class GitHubActionsReporter extends BaseReporter { return node; } - private printResultTree(resultTree: ResultTree): void { + private printResultTree( + resultTree: ResultTree, + config: Config.ProjectConfig, + consoleLog: ConsoleBuffer | undefined, + ): void { let perfMs; if (resultTree.performanceInfo.slow) { perfMs = ` (${chalk.red.inverse( @@ -324,6 +331,9 @@ export default class GitHubActionsReporter extends BaseReporter { this.startGroup( `${chalk.bold.green.inverse('PASS')} ${resultTree.name}${perfMs}`, ); + if (consoleLog && !this.options.silent) { + this.log(getConsoleOutput(consoleLog, config, this.globalConfig)); + } for (const child of resultTree.children) { this.recursivePrintResultTree(child, true, 1); } @@ -401,6 +411,7 @@ export default class GitHubActionsReporter extends BaseReporter { private printFailedTestLogs( context: Test, + consoleLog: ConsoleBuffer | undefined, testResults: AggregatedResult, ): boolean { const rootDir = context.context.config.rootDir; @@ -416,6 +427,15 @@ export default class GitHubActionsReporter extends BaseReporter { written = true; } this.startGroup(`Errors thrown in ${testDir}`); + if (consoleLog && !this.options.silent) { + this.log( + getConsoleOutput( + consoleLog, + context.context.config, + this.globalConfig, + ), + ); + } this.log(result.failureMessage); this.endGroup(); } diff --git a/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts b/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts index 3587ed8dfbed..0fb113776981 100644 --- a/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts +++ b/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts @@ -13,8 +13,7 @@ import type { TestCaseResult, TestResult, } from '@jest/test-result'; -import {normalizeIcons} from '@jest/test-utils'; -import type {Config} from '@jest/types'; +import {makeGlobalConfig, normalizeIcons} from '@jest/test-utils'; import BaseGitHubActionsReporter from '../GitHubActionsReporter'; afterEach(() => { @@ -32,7 +31,7 @@ const mockedStderrWrite = jest .mockImplementation(() => true); describe('annotations', () => { - const reporter = new GitHubActionsReporter({} as Config.GlobalConfig); + const reporter = new GitHubActionsReporter(makeGlobalConfig()); const testMeta = { context: {config: {rootDir: '/user/project'}}, @@ -155,7 +154,7 @@ describe('annotations', () => { describe('logs', () => { test('can be instantiated', () => { - const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + const gha = new GitHubActionsReporter(makeGlobalConfig()); expect(gha).toBeTruthy(); expect(gha).toBeInstanceOf(GitHubActionsReporter); }); @@ -194,7 +193,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -237,7 +236,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -286,7 +285,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -335,7 +334,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -396,7 +395,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -427,7 +426,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -455,7 +454,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -489,7 +488,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -523,7 +522,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -557,7 +556,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -591,7 +590,7 @@ describe('logs', () => { start: 10, }, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); @@ -630,7 +629,7 @@ describe('logs', () => { numPassedTestSuites: 1, numTotalTestSuites: 3, }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); gha.generateAnnotations = jest.fn(); @@ -674,7 +673,110 @@ describe('logs', () => { numTotalTestSuites: 3, testResults: [mockTestResult], }; - const gha = new GitHubActionsReporter({} as Config.GlobalConfig, { + const gha = new GitHubActionsReporter(makeGlobalConfig(), { + silent: false, + }); + gha.generateAnnotations = jest.fn(); + + gha.onTestResult( + mockTest as Test, + mockTestResult as unknown as TestResult, + mockResults as unknown as AggregatedResult, + ); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('onTestResult last with console output for failed test', () => { + const mockTest = { + context: { + config: { + rootDir: '/testDir', + }, + }, + }; + const mockTestResult = { + console: [ + { + message: 'bar', + origin: + ' at Object.log (/tmp/jest-test/a.test.js:2:13)\n at Promise.finally.completed (/github.com/jestjs/jest/packages/jest-circus/build/jestAdapterInit.js:1557:28)', + type: 'log', + }, + ], + failureMessage: 'Failure message', + perfStats: { + runtime: 20, + slow: false, + }, + testFilePath: '/testDir/test1.js', + testResults: [ + { + ancestorTitles: [], + duration: 10, + status: 'passed', + title: 'test1', + }, + ], + }; + const mockResults = { + numFailedTestSuites: 1, + numPassedTestSuites: 2, + numTotalTestSuites: 3, + testResults: [mockTestResult], + }; + const gha = new GitHubActionsReporter(makeGlobalConfig(), { + silent: false, + }); + gha.generateAnnotations = jest.fn(); + + gha.onTestResult( + mockTest as Test, + mockTestResult as unknown as TestResult, + mockResults as unknown as AggregatedResult, + ); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('onTestResult last with console output for success test', () => { + const mockTest = { + context: { + config: { + rootDir: '/testDir', + }, + }, + }; + const mockTestResult = { + console: [ + { + message: 'bar', + origin: + ' at Object.log (/tmp/jest-test/a.test.js:2:13)\n at Promise.finally.completed (/github.com/jestjs/jest/packages/jest-circus/build/jestAdapterInit.js:1557:28)', + type: 'log', + }, + ], + perfStats: { + runtime: 20, + slow: false, + }, + testFilePath: '/testDir/test1.js', + testResults: [ + { + ancestorTitles: [], + duration: 10, + status: 'passed', + title: 'test1', + }, + ], + }; + const mockResults = { + numFailedTestSuites: 0, + numPassedTestSuites: 1, + numTotalTestSuites: 1, + testResults: [mockTestResult], + }; + const gha = new GitHubActionsReporter(makeGlobalConfig(), { silent: false, }); gha.generateAnnotations = jest.fn(); diff --git a/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap b/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap index eb022c9657f8..c2a7c34ae10c 100644 --- a/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap +++ b/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap @@ -72,6 +72,80 @@ Array [ ] `; +exports[`logs Reporter interface onTestResult last with console output for failed test 1`] = ` +Array [ + Array [ + "::group::PASS test1.js (20 ms) +", + ], + Array [ + " console.log + bar + + at Object.log (../tmp/jest-test/a.test.js:2:13) + +", + ], + Array [ + " ✓ test1 (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], + Array [ + " +", + ], + Array [ + "::group::Errors thrown in test1.js +", + ], + Array [ + " console.log + bar + + at Object.log (../tmp/jest-test/a.test.js:2:13) + +", + ], + Array [ + "Failure message +", + ], + Array [ + "::endgroup:: +", + ], +] +`; + +exports[`logs Reporter interface onTestResult last with console output for success test 1`] = ` +Array [ + Array [ + "::group::PASS test1.js (20 ms) +", + ], + Array [ + " console.log + bar + + at Object.log (../tmp/jest-test/a.test.js:2:13) + +", + ], + Array [ + " ✓ test1 (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], +] +`; + exports[`logs Reporter interface onTestResult not last 1`] = ` Array [ Array [