diff --git a/CHANGELOG.md b/CHANGELOG.md index 40949ac2e453..fa9845797717 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - `[jest-config]` Correctly detect CI environment and update snapshots accordingly ([#12378](https://github.com/facebook/jest/pull/12378)) - `[jest-config]` Pass `moduleTypes` to `ts-node` to enforce CJS when transpiling ([#12397](https://github.com/facebook/jest/pull/12397)) - `[jest-config, jest-haste-map]` Allow searching for tests in `node_modules` by exposing `retainAllFiles` ([#11084](https://github.com/facebook/jest/pull/11084)) +- `[jest-core]` [**BREAKING**] Exit with status `1` if no tests are found with `--findRelatedTests` flag ([#12487](https://github.com/facebook/jest/pull/12487)) - `[jest-environment-jsdom]` Make `jsdom` accessible to extending environments again ([#12232](https://github.com/facebook/jest/pull/12232)) - `[jest-environment-jsdom]` Log JSDOM errors more cleanly ([#12386](https://github.com/facebook/jest/pull/12386)) - `[@jest/expect-utils]` [**BREAKING**] Fix false positives when looking for `undefined` prop ([#8923](https://github.com/facebook/jest/pull/8923)) diff --git a/e2e/__tests__/noTestsFound.test.ts b/e2e/__tests__/noTestsFound.test.ts index 1e48a204a5b6..4d373c266fc8 100644 --- a/e2e/__tests__/noTestsFound.test.ts +++ b/e2e/__tests__/noTestsFound.test.ts @@ -17,7 +17,10 @@ describe('No tests are found', () => { '/non/existing/path/', ]); - expect(stdout).toMatch('No tests found'); + expect(stdout).toContain('No tests found, exiting with code 1'); + expect(stdout).toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); expect(exitCode).toBe(1); }); @@ -28,7 +31,10 @@ describe('No tests are found', () => { '--passWithNoTests', ]); - expect(stdout).toMatch('No tests found'); + expect(stdout).toContain('No tests found, exiting with code 0'); + expect(stdout).not.toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); expect(exitCode).toBe(0); }); @@ -36,7 +42,12 @@ describe('No tests are found', () => { // Since there are no files in DIR no tests will be found const {exitCode, stdout} = runJest(DIR, ['--lastCommit']); - expect(stdout).toMatch('No tests found'); + expect(stdout).toContain( + 'No tests found related to files changed since last commit.', + ); + expect(stdout).not.toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); expect(exitCode).toBe(0); }); @@ -44,18 +55,41 @@ describe('No tests are found', () => { // Since there are no files in DIR no tests will be found const {exitCode, stdout} = runJest(DIR, ['--onlyChanged']); - expect(stdout).toMatch('No tests found'); + expect(stdout).toContain( + 'No tests found related to files changed since last commit.', + ); + expect(stdout).not.toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); expect(exitCode).toBe(0); }); - test("doesn't fail the test suite if using --findRelatedTests", () => { + test('fails the test suite if using --findRelatedTests', () => { // Since there are no files in DIR no tests will be found const {exitCode, stdout} = runJest(DIR, [ '--findRelatedTests', '/non/existing/path', ]); - expect(stdout).toMatch('No tests found'); + expect(stdout).toContain('No tests found, exiting with code 1'); + expect(stdout).toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); + expect(exitCode).toBe(1); + }); + + test("doesn't fail the test suite if using --findRelatedTests and --passWithNoTests", () => { + // Since there are no files in DIR no tests will be found + const {exitCode, stdout} = runJest(DIR, [ + '--findRelatedTests', + '/non/existing/path', + '--passWithNoTests', + ]); + + expect(stdout).toContain('No tests found, exiting with code 0'); + expect(stdout).not.toContain( + 'Run with `--passWithNoTests` to exit with code 0', + ); expect(exitCode).toBe(0); }); }); diff --git a/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.js.snap b/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.js.snap deleted file mode 100644 index aa35efad47eb..000000000000 --- a/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.js.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getNoTestsFoundMessage returns correct message when monitoring only changed 1`] = `"No tests found related to files changed since last commit."`; - -exports[`getNoTestsFoundMessage returns correct message when monitoring only failures 1`] = `"No failed test found."`; - -exports[`getNoTestsFoundMessage returns correct message with passWithNoTests 1`] = `"No tests found, exiting with code 0"`; - -exports[`getNoTestsFoundMessage returns correct message with verbose option 1`] = ` -"No tests found, exiting with code 1 -Run with \`--passWithNoTests\` to exit with code 0 - -Pattern: /path/pattern - 0 matches" -`; - -exports[`getNoTestsFoundMessage returns correct message without options 1`] = ` -"No tests found, exiting with code 1 -Run with \`--passWithNoTests\` to exit with code 0 -In /root/dir - 0 files checked across 0 projects. Run with \`--verbose\` for more details. -Pattern: /path/pattern - 0 matches" -`; diff --git a/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.ts.snap b/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.ts.snap new file mode 100644 index 000000000000..bc5a0e7d3645 --- /dev/null +++ b/packages/jest-core/src/__tests__/__snapshots__/getNoTestsFoundMessage.test.ts.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getNoTestsFoundMessage returns correct message when monitoring only changed 1`] = ` +Object { + "exitWith0": true, + "message": "No tests found related to files changed since last commit. +Run Jest without \`-o\` or with \`--all\` to run all tests.", +} +`; + +exports[`getNoTestsFoundMessage returns correct message when monitoring only failures 1`] = ` +Object { + "exitWith0": false, + "message": "No failed test found. +Run Jest without \`--onlyFailures\` or with \`--all\` to run all tests.", +} +`; + +exports[`getNoTestsFoundMessage returns correct message with findRelatedTests 1`] = ` +Object { + "exitWith0": false, + "message": "No tests found, exiting with code 1 +Run with \`--passWithNoTests\` to exit with code 0 +In /root/dir + 0 files checked across 0 projects. Run with \`--verbose\` for more details. +Pattern: /path/pattern - 0 matches", +} +`; + +exports[`getNoTestsFoundMessage returns correct message with findRelatedTests 2`] = ` +Object { + "exitWith0": true, + "message": "No tests found, exiting with code 0", +} +`; + +exports[`getNoTestsFoundMessage returns correct message with passWithNoTests 1`] = ` +Object { + "exitWith0": true, + "message": "No tests found, exiting with code 0", +} +`; + +exports[`getNoTestsFoundMessage returns correct message with verbose option 1`] = ` +Object { + "exitWith0": false, + "message": "No tests found, exiting with code 1 +Run with \`--passWithNoTests\` to exit with code 0 + +Pattern: /path/pattern - 0 matches", +} +`; + +exports[`getNoTestsFoundMessage returns correct message without options 1`] = ` +Object { + "exitWith0": false, + "message": "No tests found, exiting with code 1 +Run with \`--passWithNoTests\` to exit with code 0 +In /root/dir + 0 files checked across 0 projects. Run with \`--verbose\` for more details. +Pattern: /path/pattern - 0 matches", +} +`; diff --git a/packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.js b/packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.ts similarity index 69% rename from packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.js rename to packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.ts index 217e6196bcea..259e46b7d66e 100644 --- a/packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.js +++ b/packages/jest-core/src/__tests__/getNoTestsFoundMessage.test.ts @@ -5,15 +5,22 @@ * LICENSE file in the root directory of this source tree. */ +import {makeGlobalConfig} from '@jest/test-utils'; +import type {Config} from '@jest/types'; import getNoTestsFoundMessage from '../getNoTestsFoundMessage'; +jest.mock('jest-util', () => ({ + ...jest.requireActual('jest-util'), + isInteractive: true, +})); + describe('getNoTestsFoundMessage', () => { - function createGlobalConfig(options) { - return { + function createGlobalConfig(options?: Partial) { + return makeGlobalConfig({ rootDir: '/root/dir', testPathPattern: '/path/pattern', ...options, - }; + }); } test('returns correct message when monitoring only failures', () => { @@ -40,4 +47,12 @@ describe('getNoTestsFoundMessage', () => { const config = createGlobalConfig({passWithNoTests: true}); expect(getNoTestsFoundMessage([], config)).toMatchSnapshot(); }); + + test('returns correct message with findRelatedTests', () => { + const config = createGlobalConfig({findRelatedTests: true}); + expect(getNoTestsFoundMessage([], config)).toMatchSnapshot(); + expect( + getNoTestsFoundMessage([], {...config, passWithNoTests: true}), + ).toMatchSnapshot(); + }); }); diff --git a/packages/jest-core/src/getNoTestFound.ts b/packages/jest-core/src/getNoTestFound.ts index 53d2a0b9355e..1f8ced3d4cb0 100644 --- a/packages/jest-core/src/getNoTestFound.ts +++ b/packages/jest-core/src/getNoTestFound.ts @@ -13,6 +13,7 @@ import type {TestRunData} from './types'; export default function getNoTestFound( testRunData: TestRunData, globalConfig: Config.GlobalConfig, + willExitWith0: boolean, ): string { const testFiles = testRunData.reduce( (current, testRun) => current + (testRun.matches.total || 0), @@ -30,6 +31,22 @@ export default function getNoTestFound( )} - 0 matches`; } + if (willExitWith0) { + return ( + chalk.bold('No tests found, exiting with code 0') + + '\n' + + `In ${chalk.bold(globalConfig.rootDir)}` + + '\n' + + ` ${pluralize('file', testFiles, 's')} checked across ${pluralize( + 'project', + testRunData.length, + 's', + )}. Run with \`--verbose\` for more details.` + + '\n' + + dataMessage + ); + } + return ( chalk.bold('No tests found, exiting with code 1') + '\n' + diff --git a/packages/jest-core/src/getNoTestFoundVerbose.ts b/packages/jest-core/src/getNoTestFoundVerbose.ts index b4379c48c948..4cf488238e0a 100644 --- a/packages/jest-core/src/getNoTestFoundVerbose.ts +++ b/packages/jest-core/src/getNoTestFoundVerbose.ts @@ -13,6 +13,7 @@ import type {Stats, TestRunData} from './types'; export default function getNoTestFoundVerbose( testRunData: TestRunData, globalConfig: Config.GlobalConfig, + willExitWith0: boolean, ): string { const individualResults = testRunData.map(testRun => { const stats = testRun.matches.stats || ({} as Stats); @@ -57,6 +58,16 @@ export default function getNoTestFoundVerbose( )} - 0 matches`; } + if (willExitWith0) { + return ( + chalk.bold('No tests found, exiting with code 0') + + '\n' + + individualResults.join('\n') + + '\n' + + dataMessage + ); + } + return ( chalk.bold('No tests found, exiting with code 1') + '\n' + diff --git a/packages/jest-core/src/getNoTestsFoundMessage.ts b/packages/jest-core/src/getNoTestsFoundMessage.ts index d6f2b3d988bf..f3e6298067b7 100644 --- a/packages/jest-core/src/getNoTestsFoundMessage.ts +++ b/packages/jest-core/src/getNoTestsFoundMessage.ts @@ -16,17 +16,29 @@ import type {TestRunData} from './types'; export default function getNoTestsFoundMessage( testRunData: TestRunData, globalConfig: Config.GlobalConfig, -): string { +): {exitWith0: boolean; message: string} { + const exitWith0 = + globalConfig.passWithNoTests || + globalConfig.lastCommit || + globalConfig.onlyChanged; + if (globalConfig.onlyFailures) { - return getNoTestFoundFailed(globalConfig); + return {exitWith0, message: getNoTestFoundFailed(globalConfig)}; } if (globalConfig.onlyChanged) { - return getNoTestFoundRelatedToChangedFiles(globalConfig); + return { + exitWith0, + message: getNoTestFoundRelatedToChangedFiles(globalConfig), + }; } if (globalConfig.passWithNoTests) { - return getNoTestFoundPassWithNoTests(); + return {exitWith0, message: getNoTestFoundPassWithNoTests()}; } - return testRunData.length === 1 || globalConfig.verbose - ? getNoTestFoundVerbose(testRunData, globalConfig) - : getNoTestFound(testRunData, globalConfig); + return { + exitWith0, + message: + testRunData.length === 1 || globalConfig.verbose + ? getNoTestFoundVerbose(testRunData, globalConfig, exitWith0) + : getNoTestFound(testRunData, globalConfig, exitWith0), + }; } diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts index cc4d9be4497e..138ddb838d91 100644 --- a/packages/jest-core/src/runJest.ts +++ b/packages/jest-core/src/runJest.ts @@ -220,17 +220,12 @@ export default async function runJest({ const hasTests = allTests.length > 0; if (!hasTests) { - const noTestsFoundMessage = getNoTestsFoundMessage( + const {exitWith0, message: noTestsFoundMessage} = getNoTestsFoundMessage( testRunData, globalConfig, ); - if ( - globalConfig.passWithNoTests || - globalConfig.findRelatedTests || - globalConfig.lastCommit || - globalConfig.onlyChanged - ) { + if (exitWith0) { new CustomConsole(outputStream, outputStream).log(noTestsFoundMessage); } else { new CustomConsole(outputStream, outputStream).error(noTestsFoundMessage);