diff --git a/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts b/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts index 9d4bb73e68ba..415589dded1e 100644 --- a/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts +++ b/packages/jest-reporters/src/__tests__/GitHubActionsReporter.test.ts @@ -5,134 +5,530 @@ * LICENSE file in the root directory of this source tree. */ -import type {Test, TestCaseResult, TestResult} from '@jest/test-result'; +import type { + AggregatedResult, + AssertionResult, + Test, + TestCaseResult, + TestResult, +} from '@jest/test-result'; import type {Config} from '@jest/types'; import GitHubActionsReporter from '../GitHubActionsReporter'; +afterEach(() => { + jest.clearAllMocks(); +}); + const mockedStderrWrite = jest .spyOn(process.stderr, 'write') .mockImplementation(() => true); -afterEach(() => { - jest.clearAllMocks(); -}); +describe('annotations', () => { + const reporter = new GitHubActionsReporter({} as Config.GlobalConfig); + + const testMeta = { + context: {config: {rootDir: '/user/project'}}, + } as Test; + + const expectationsErrorMessage = + 'Error: \x1B[2mexpect(\x1B[22m\x1B[31mreceived\x1B[39m\x1B[2m).\x1B[22mtoBe\x1B[2m(\x1B[22m\x1B[32mexpected\x1B[39m\x1B[2m) // Object.is equality\x1B[22m\n' + + '\n' + + 'Expected: \x1B[32m1\x1B[39m\n' + + 'Received: \x1B[31m10\x1B[39m\n' + + ' at Object.toBe (/user/project/__tests__/example.test.js:20:14)\n' + + ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + + ' at new Promise ()\n' + + ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + + ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + + ' at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' + + ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + + ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + + ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)\n' + + ' at runAndTransformResultsToJestFormat (/user/project/jest/packages/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:135:21)'; + + const referenceErrorMessage = + 'ReferenceError: abc is not defined\n' + + ' at Object.abc (/user/project/__tests__/example.test.js:25:12)\n' + + ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + + ' at new Promise ()\n' + + ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + + ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + + ' at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' + + ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + + ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + + ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:90:9)\n' + + ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)'; + + const retryErrorMessage = + 'Error: \x1B[2mexpect(\x1B[22m\x1B[31mreceived\x1B[39m\x1B[2m).\x1B[22mtoBeFalsy\x1B[2m()\x1B[22m\n' + + '\n' + + 'Received: \x1B[31mtrue\x1B[39m\n' + + ' at Object.toBeFalsy (/user/project/__tests__/example.test.js:19:20)\n' + + ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + + ' at new Promise ()\n' + + ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + + ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + + ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + + ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + + ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:90:9)\n' + + ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)\n' + + ' at runAndTransformResultsToJestFormat (/user/project/jest/packages/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:135:21)'; + + const testCaseResult = { + ancestorTitles: [] as Array, + failureMessages: [expectationsErrorMessage], + title: 'example test', + } as TestCaseResult; + + describe('logs error annotation', () => { + test('when an expectation fails to pass', () => { + reporter['generateAnnotations'](testMeta, { + testResults: [ + { + ...testCaseResult, + failureMessages: [expectationsErrorMessage], + }, + ], + } as TestResult); -const reporter = new GitHubActionsReporter({} as Config.GlobalConfig); - -const testMeta = { - context: {config: {rootDir: '/user/project'}}, -} as Test; - -const expectationsErrorMessage = - 'Error: \x1B[2mexpect(\x1B[22m\x1B[31mreceived\x1B[39m\x1B[2m).\x1B[22mtoBe\x1B[2m(\x1B[22m\x1B[32mexpected\x1B[39m\x1B[2m) // Object.is equality\x1B[22m\n' + - '\n' + - 'Expected: \x1B[32m1\x1B[39m\n' + - 'Received: \x1B[31m10\x1B[39m\n' + - ' at Object.toBe (/user/project/__tests__/example.test.js:20:14)\n' + - ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + - ' at new Promise ()\n' + - ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + - ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + - ' at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' + - ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + - ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + - ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)\n' + - ' at runAndTransformResultsToJestFormat (/user/project/jest/packages/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:135:21)'; - -const referenceErrorMessage = - 'ReferenceError: abc is not defined\n' + - ' at Object.abc (/user/project/__tests__/example.test.js:25:12)\n' + - ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + - ' at new Promise ()\n' + - ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + - ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + - ' at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' + - ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + - ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + - ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:90:9)\n' + - ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)'; - -const retryErrorMessage = - 'Error: \x1B[2mexpect(\x1B[22m\x1B[31mreceived\x1B[39m\x1B[2m).\x1B[22mtoBeFalsy\x1B[2m()\x1B[22m\n' + - '\n' + - 'Received: \x1B[31mtrue\x1B[39m\n' + - ' at Object.toBeFalsy (/user/project/__tests__/example.test.js:19:20)\n' + - ' at Promise.then.completed (/user/project/jest/packages/jest-circus/build/utils.js:333:28)\n' + - ' at new Promise ()\n' + - ' at callAsyncCircusFn (/user/project/jest/packages/jest-circus/build/utils.js:259:10)\n' + - ' at _callCircusTest (/user/project/jest/packages/jest-circus/build/run.js:276:40)\n' + - ' at _runTest (/user/project/jest/packages/jest-circus/build/run.js:208:3)\n' + - ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:96:9)\n' + - ' at _runTestsForDescribeBlock (/user/project/jest/packages/jest-circus/build/run.js:90:9)\n' + - ' at run (/user/project/jest/packages/jest-circus/build/run.js:31:3)\n' + - ' at runAndTransformResultsToJestFormat (/user/project/jest/packages/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:135:21)'; - -const testCaseResult = { - ancestorTitles: [] as Array, - failureMessages: [expectationsErrorMessage], - title: 'example test', -} as TestCaseResult; - -describe('logs error annotation', () => { - test('when an expectation fails to pass', () => { - reporter.generateAnnotations(testMeta, { - testResults: [ + expect(mockedStderrWrite).toHaveBeenCalledTimes(1); + expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); + }); + + test('when a test has reference error', () => { + reporter['generateAnnotations']( + {...testMeta, path: '/user/project/__tests__/example.test.js:25:12'}, { - ...testCaseResult, - failureMessages: [expectationsErrorMessage], - }, - ], - } as TestResult); + testResults: [ + { + ...testCaseResult, + failureMessages: [referenceErrorMessage], + }, + ], + } as TestResult, + ); + + expect(mockedStderrWrite).toHaveBeenCalledTimes(1); + expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); + }); - expect(mockedStderrWrite).toHaveBeenCalledTimes(1); - expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); + test('when test is wrapped in describe block', () => { + reporter['generateAnnotations'](testMeta, { + testResults: [ + { + ...testCaseResult, + ancestorTitles: ['describe'], + }, + ], + } as TestResult); + + expect(mockedStderrWrite).toHaveBeenCalledTimes(1); + expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); + }); }); - test('when a test has reference error', () => { - reporter.generateAnnotations( - {...testMeta, path: '/user/project/__tests__/example.test.js:25:12'}, - { + describe('logs warning annotation before logging errors', () => { + test('when test result includes retry reasons', () => { + reporter['generateAnnotations'](testMeta, { testResults: [ { ...testCaseResult, - failureMessages: [referenceErrorMessage], + failureMessages: [retryErrorMessage], + retryReasons: [retryErrorMessage], }, ], - } as TestResult, - ); + } as TestResult); - expect(mockedStderrWrite).toHaveBeenCalledTimes(1); - expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); + expect(mockedStderrWrite).toHaveBeenCalledTimes(2); + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); }); +}); - test('when test is wrapped in describe block', () => { - reporter.generateAnnotations(testMeta, { - testResults: [ +describe('logs', () => { + test('can be instantiated', () => { + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + expect(gha).toBeTruthy(); + expect(gha).toBeInstanceOf(GitHubActionsReporter); + }); + + describe('Result tree generation', () => { + test('failed single test without describe', () => { + const testResults = [ { - ...testCaseResult, - ancestorTitles: ['describe'], + ancestorTitles: [], + duration: 10, + status: 'failed', + title: 'test', }, - ], - } as TestResult); + ] as unknown as Array; + const suitePerf = { + end: 30, + runtime: 20, + slow: false, + start: 10, + }; + const expectedResults = { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: false, + }, + ], + name: '/', + passed: false, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); - expect(mockedStderrWrite).toHaveBeenCalledTimes(1); - expect(mockedStderrWrite.mock.calls[0]).toMatchSnapshot(); - }); -}); + const generated = gha['getResultTree'](testResults, '/', suitePerf); + + expect(mockedStderrWrite).not.toHaveBeenCalled(); + expect(generated).toEqual(expectedResults); + }); + + test('passed single test without describe', () => { + const testResults = [ + { + ancestorTitles: [], + duration: 10, + status: 'passed', + title: 'test', + }, + ] as unknown as Array; + const suitePerf = { + end: 30, + runtime: 20, + slow: false, + start: 10, + }; + const expectedResults = { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: true, + }, + ], + name: '/', + passed: true, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + const generated = gha['getResultTree'](testResults, '/', suitePerf); + + expect(mockedStderrWrite).not.toHaveBeenCalled(); + expect(generated).toEqual(expectedResults); + }); + + test('failed single test inside describe', () => { + const testResults = [ + { + ancestorTitles: ['Test describe'], + duration: 10, + status: 'failed', + title: 'test', + }, + ] as unknown as Array; + const suitePerf = { + end: 30, + runtime: 20, + slow: false, + start: 10, + }; + const expectedResults = { + children: [ + { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: false, + }, + ], + name: 'Test describe', + passed: false, + }, + ], + name: '/', + passed: false, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + const generated = gha['getResultTree'](testResults, '/', suitePerf); + + expect(mockedStderrWrite).not.toHaveBeenCalled(); + expect(generated).toEqual(expectedResults); + }); -describe('logs warning annotation before logging errors', () => { - test('when test result includes retry reasons', () => { - reporter.generateAnnotations(testMeta, { - testResults: [ + test('passed single test inside describe', () => { + const testResults = [ { - ...testCaseResult, - failureMessages: [retryErrorMessage], - retryReasons: [retryErrorMessage], + ancestorTitles: ['Test describe'], + duration: 10, + status: 'passed', + title: 'test', }, - ], - } as TestResult); + ] as unknown as Array; + const suitePerf = { + end: 30, + runtime: 20, + slow: false, + start: 10, + }; + const expectedResults = { + children: [ + { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: true, + }, + ], + name: 'Test describe', + passed: true, + }, + ], + name: '/', + passed: true, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + const generated = gha['getResultTree'](testResults, '/', suitePerf); + + expect(mockedStderrWrite).not.toHaveBeenCalled(); + expect(generated).toEqual(expectedResults); + }); + }); + + describe('Result tree output', () => { + test('failed single test without describe', () => { + const generatedTree = { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: false, + }, + ], + name: '/', + passed: false, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + gha['printResultTree'](generatedTree); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('passed single test without describe', () => { + const generatedTree = { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: true, + }, + ], + name: '/', + passed: true, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + gha['printResultTree'](generatedTree); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('failed single test inside describe', () => { + const generatedTree = { + children: [ + { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: false, + }, + ], + name: 'Test describe', + passed: false, + }, + ], + name: '/', + passed: false, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + gha['printResultTree'](generatedTree); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('passed single test inside describe', () => { + const generatedTree = { + children: [ + { + children: [ + { + children: [], + duration: 10, + name: 'test', + passed: true, + }, + ], + name: 'Test describe', + passed: true, + }, + ], + name: '/', + passed: true, + performanceInfo: { + end: 30, + runtime: 20, + slow: false, + start: 10, + }, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + + gha['printResultTree'](generatedTree); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + }); + + describe('Reporter interface', () => { + test('onTestResult not last', () => { + const mockTest = { + context: { + config: { + rootDir: '/testDir', + }, + }, + }; + const mockTestResult = { + perfStats: { + runtime: 20, + slow: false, + }, + testFilePath: '/testDir/test1.js', + testResults: [ + { + ancestorTitles: [], + duration: 10, + status: 'passed', + title: 'test1', + }, + ], + }; + const mockResults = { + numFailedTestSuites: 1, + numPassedTestSuites: 1, + numTotalTestSuites: 3, + }; + const gha = new GitHubActionsReporter({} as Config.GlobalConfig); + gha['generateAnnotations'] = jest.fn(); + + gha.onTestResult( + mockTest as Test, + mockTestResult as unknown as TestResult, + mockResults as AggregatedResult, + ); + + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); + + test('onTestResult last', () => { + const mockTest = { + context: { + config: { + rootDir: '/testDir', + }, + }, + }; + const mockTestResult = { + 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({} as Config.GlobalConfig); + gha['generateAnnotations'] = jest.fn(); + + gha.onTestResult( + mockTest as Test, + mockTestResult as unknown as TestResult, + mockResults as unknown as AggregatedResult, + ); - expect(mockedStderrWrite).toHaveBeenCalledTimes(2); - expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + expect(mockedStderrWrite.mock.calls).toMatchSnapshot(); + }); }); }); diff --git a/packages/jest-reporters/src/__tests__/GithubActionsLogsReporter.test.js b/packages/jest-reporters/src/__tests__/GithubActionsLogsReporter.test.js deleted file mode 100644 index f3a5428f1b60..000000000000 --- a/packages/jest-reporters/src/__tests__/GithubActionsLogsReporter.test.js +++ /dev/null @@ -1,416 +0,0 @@ -/** - * 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. - */ - -// copied from https://github.com/MatteoH2O1999/github-actions-jest-reporter/blob/master/tests/gha.reporter.test.js - -import util from 'util'; -import chalk from 'chalk'; -import {beforeEach, describe, expect, jest, test} from '@jest/globals'; -import BaseReporter from '../BaseReporter'; -import GhaReporter from '../GitHubActionsReporter'; - -const xSymbol = '\u00D7'; -const ySymbol = '\u2713'; - -let consoleLog; -const mockLog = jest - .spyOn(BaseReporter.prototype, 'log') - .mockImplementation(message => { - consoleLog = consoleLog.concat(message); - }); - -beforeEach(() => { - consoleLog = ''; -}); - -test('can be instantiated', () => { - const gha = new GhaReporter(); - expect(gha).toBeTruthy(); - expect(gha).toBeInstanceOf(GhaReporter); -}); - -describe('Result tree generation', () => { - test('failed single test without describe', () => { - const testResults = [ - { - ancestorTitles: [], - duration: 10, - status: 'failed', - title: 'test', - }, - ]; - const testContext = {}; - const suitePerf = { - runtime: 20, - slow: false, - }; - const expectedResults = { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: false, - }, - ], - name: '/', - passed: false, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const gha = new GhaReporter(); - - const generated = gha.getResultTree(testResults, '/', suitePerf); - - expect(consoleLog).toBe(''); - expect(generated).toEqual(expectedResults); - }); - - test('passed single test without describe', () => { - const testResults = [ - { - ancestorTitles: [], - duration: 10, - status: 'passed', - title: 'test', - }, - ]; - const testContext = {}; - const suitePerf = { - runtime: 20, - slow: false, - }; - const expectedResults = { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: true, - }, - ], - name: '/', - passed: true, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const gha = new GhaReporter(); - - const generated = gha.getResultTree(testResults, '/', suitePerf); - - expect(consoleLog).toBe(''); - expect(generated).toEqual(expectedResults); - }); - - test('failed single test inside describe', () => { - const testResults = [ - { - ancestorTitles: ['Test describe'], - duration: 10, - status: 'failed', - title: 'test', - }, - ]; - const testContext = {}; - const suitePerf = { - runtime: 20, - slow: false, - }; - const expectedResults = { - children: [ - { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: false, - }, - ], - name: 'Test describe', - passed: false, - }, - ], - name: '/', - passed: false, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const gha = new GhaReporter(); - - const generated = gha.getResultTree(testResults, '/', suitePerf); - - expect(consoleLog).toBe(''); - expect(generated).toEqual(expectedResults); - }); - - test('passed single test inside describe', () => { - const testResults = [ - { - ancestorTitles: ['Test describe'], - duration: 10, - status: 'passed', - title: 'test', - }, - ]; - const testContext = {}; - const suitePerf = { - runtime: 20, - slow: false, - }; - const expectedResults = { - children: [ - { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: true, - }, - ], - name: 'Test describe', - passed: true, - }, - ], - name: '/', - passed: true, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const gha = new GhaReporter(); - - const generated = gha.getResultTree(testResults, '/', suitePerf); - - expect(consoleLog).toBe(''); - expect(generated).toEqual(expectedResults); - }); -}); - -describe('Result tree output', () => { - test('failed single test without describe', () => { - const generatedTree = { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: false, - }, - ], - name: '/', - passed: false, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const testContext = {}; - const expectedOutput = ` ${chalk.bold.red.inverse( - 'FAIL', - )} / (20 ms) ${chalk.red(xSymbol)} test (10 ms)`; - const gha = new GhaReporter(); - - gha.printResultTree(generatedTree); - - expect(consoleLog).toEqual(expectedOutput); - }); - - test('passed single test without describe', () => { - const generatedTree = { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: true, - }, - ], - name: '/', - passed: true, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const testContext = {}; - const expectedOutput = `::group::${chalk.bold.green.inverse( - 'PASS', - )} / (20 ms) ${chalk.green(ySymbol)} test (10 ms)::endgroup::`; - const gha = new GhaReporter(); - - gha.printResultTree(generatedTree); - - expect(consoleLog).toEqual(expectedOutput); - }); - - test('failed single test inside describe', () => { - const generatedTree = { - children: [ - { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: false, - }, - ], - name: 'Test describe', - passed: false, - }, - ], - name: '/', - passed: false, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const testContext = {}; - const expectedOutput = - ` ${chalk.bold.red.inverse('FAIL')} / (20 ms)` + - ' Test describe' + - ` ${chalk.red(xSymbol)} test (10 ms)`; - const gha = new GhaReporter(); - - gha.printResultTree(generatedTree); - - expect(consoleLog).toEqual(expectedOutput); - }); - - test('passed single test inside describe', () => { - const generatedTree = { - children: [ - { - children: [ - { - children: [], - duration: 10, - name: 'test', - passed: true, - }, - ], - name: 'Test describe', - passed: true, - }, - ], - name: '/', - passed: true, - performanceInfo: { - runtime: 20, - slow: false, - }, - }; - const testContext = {}; - const expectedOutput = - `::group::${chalk.bold.green.inverse('PASS')} / (20 ms)` + - ' Test describe' + - ` ${chalk.green(ySymbol)} test (10 ms)` + - '::endgroup::'; - const gha = new GhaReporter(); - - gha.printResultTree(generatedTree); - - expect(consoleLog).toEqual(expectedOutput); - }); -}); - -describe('Reporter interface', () => { - test('onTestResult not last', () => { - const mockTest = { - context: { - config: { - rootDir: '/testDir', - }, - }, - }; - const mockTestResult = { - perfStats: { - runtime: 20, - slow: false, - }, - testFilePath: '/testDir/test1.js', - testResults: [ - { - ancestorTitles: [], - duration: 10, - status: 'passed', - title: 'test1', - }, - ], - }; - const mockResults = { - numFailedTestSuites: 1, - numPassedTestSuites: 1, - numTotalTestSuites: 3, - }; - const expectedOutput = - `::group::${chalk.bold.green.inverse('PASS')} test1.js (20 ms)` + - ` ${chalk.green(ySymbol)} test1 (10 ms)` + - '::endgroup::'; - const gha = new GhaReporter(); - gha.generateAnnotations = jest.fn(); - - gha.onTestResult(mockTest, mockTestResult, mockResults); - - expect(consoleLog).toEqual(expectedOutput); - }); - - test('onTestResult last', () => { - const mockTest = { - context: { - config: { - rootDir: '/testDir', - }, - }, - }; - const mockTestResult = { - 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 expectedOutput = - `::group::${chalk.bold.green.inverse('PASS')} test1.js (20 ms)` + - ` ${chalk.green(ySymbol)} test1 (10 ms)` + - '::endgroup::' + - '::group::Errors thrown in test1.js' + - 'Failure message' + - '::endgroup::'; - const gha = new GhaReporter(); - gha.generateAnnotations = jest.fn(); - - gha.onTestResult(mockTest, mockTestResult, mockResults); - - expect(consoleLog).toEqual(expectedOutput); - }); -}); 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 4201d36f388d..1010136fe994 100644 --- a/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap +++ b/packages/jest-reporters/src/__tests__/__snapshots__/GitHubActionsReporter.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`logs error annotation when a test has reference error 1`] = ` +exports[`annotations logs error annotation when a test has reference error 1`] = ` Array [ " ::error file=/user/project/__tests__/example.test.js,line=25,title=example test::ReferenceError: abc is not defined%0A%0A at Object.abc (__tests__/example.test.js:25:12) @@ -8,7 +8,7 @@ Array [ ] `; -exports[`logs error annotation when an expectation fails to pass 1`] = ` +exports[`annotations logs error annotation when an expectation fails to pass 1`] = ` Array [ " ::error file=/user/project/__tests__/example.test.js,line=20,title=example test::expect(received).toBe(expected) // Object.is equality%0A%0AExpected: 1%0AReceived: 10%0A%0A at Object.toBe (__tests__/example.test.js:20:14) @@ -16,7 +16,7 @@ Array [ ] `; -exports[`logs error annotation when test is wrapped in describe block 1`] = ` +exports[`annotations logs error annotation when test is wrapped in describe block 1`] = ` Array [ " ::error file=/user/project/__tests__/example.test.js,line=20,title=describe › example test::expect(received).toBe(expected) // Object.is equality%0A%0AExpected: 1%0AReceived: 10%0A%0A at Object.toBe (__tests__/example.test.js:20:14) @@ -24,7 +24,7 @@ Array [ ] `; -exports[`logs warning annotation before logging errors when test result includes retry reasons 1`] = ` +exports[`annotations logs warning annotation before logging errors when test result includes retry reasons 1`] = ` Array [ Array [ " @@ -38,3 +38,121 @@ Array [ ], ] `; + +exports[`logs Reporter interface onTestResult last 1`] = ` +Array [ + Array [ + "::group::PASS test1.js (20 ms) +", + ], + Array [ + " ✓ test1 (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], + Array [ + " +", + ], + Array [ + "::group::Errors thrown in test1.js +", + ], + Array [ + "Failure message +", + ], + Array [ + "::endgroup:: +", + ], +] +`; + +exports[`logs Reporter interface onTestResult not last 1`] = ` +Array [ + Array [ + "::group::PASS test1.js (20 ms) +", + ], + Array [ + " ✓ test1 (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], +] +`; + +exports[`logs Result tree output failed single test inside describe 1`] = ` +Array [ + Array [ + " FAIL / (20 ms) +", + ], + Array [ + " Test describe +", + ], + Array [ + " × test (10 ms) +", + ], +] +`; + +exports[`logs Result tree output failed single test without describe 1`] = ` +Array [ + Array [ + " FAIL / (20 ms) +", + ], + Array [ + " × test (10 ms) +", + ], +] +`; + +exports[`logs Result tree output passed single test inside describe 1`] = ` +Array [ + Array [ + "::group::PASS / (20 ms) +", + ], + Array [ + " Test describe +", + ], + Array [ + " ✓ test (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], +] +`; + +exports[`logs Result tree output passed single test without describe 1`] = ` +Array [ + Array [ + "::group::PASS / (20 ms) +", + ], + Array [ + " ✓ test (10 ms) +", + ], + Array [ + "::endgroup:: +", + ], +] +`;