diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c02eb4c007f..5aef0e7173e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ - `[jest-circus]` Fix `testLocation` on Windows when using `test.each` ([#10871](https://github.com/facebook/jest/pull/10871)) - `[jest-cli]` Use testFailureExitCode when bailing from a failed test ([#10958](https://github.com/facebook/jest/pull/10958)) - `[jest-cli]` Print custom error if error thrown from global hooks is not an error already ([#11003](https://github.com/facebook/jest/pull/11003)) +- `[jest-cli]` Allow running multiple "projects" from programmatic API ([#11307](https://github.com/facebook/jest/pull/11307)) - `[jest-config]` [**BREAKING**] Change default file extension order by moving json behind ts and tsx ([10572](https://github.com/facebook/jest/pull/10572)) - `[jest-console]` `console.dir` now respects the second argument correctly ([#10638](https://github.com/facebook/jest/pull/10638)) - `[jest-core]` Don't report PerformanceObserver as open handle ([#11123](https://github.com/facebook/jest/pull/11123)) diff --git a/e2e/__tests__/__snapshots__/runProgrammaticallyMultipleProjects.test.ts.snap b/e2e/__tests__/__snapshots__/runProgrammaticallyMultipleProjects.test.ts.snap new file mode 100644 index 000000000000..3362f97f2234 --- /dev/null +++ b/e2e/__tests__/__snapshots__/runProgrammaticallyMultipleProjects.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run programmatically with multiple projects: summary 1`] = ` +Test Suites: 2 passed, 2 total +Tests: 2 passed, 2 total +Snapshots: 0 total +Time: <> +Ran all test suites in 2 projects. +`; diff --git a/e2e/__tests__/runProgrammaticallyMultipleProjects.test.ts b/e2e/__tests__/runProgrammaticallyMultipleProjects.test.ts new file mode 100644 index 000000000000..16b3c257949f --- /dev/null +++ b/e2e/__tests__/runProgrammaticallyMultipleProjects.test.ts @@ -0,0 +1,20 @@ +/** + * 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 {resolve} from 'path'; +import {wrap} from 'jest-snapshot-serializer-raw'; +import stripAnsi = require('strip-ansi'); +import {extractSummary, run} from '../Utils'; + +const dir = resolve(__dirname, '../run-programmatically-multiple-projects'); + +test('run programmatically with multiple projects', () => { + const {stderr, exitCode} = run(`node run-jest.js`, dir); + const {summary} = extractSummary(stripAnsi(stderr)); + expect(exitCode).toEqual(0); + expect(wrap(summary)).toMatchSnapshot('summary'); +}); diff --git a/e2e/run-programmatically-multiple-projects/client/client.test.js b/e2e/run-programmatically-multiple-projects/client/client.test.js new file mode 100644 index 000000000000..c40068258659 --- /dev/null +++ b/e2e/run-programmatically-multiple-projects/client/client.test.js @@ -0,0 +1,10 @@ +/** + * 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. + */ + +describe('client', () => { + it('should work', () => {}); +}); diff --git a/e2e/run-programmatically-multiple-projects/package.json b/e2e/run-programmatically-multiple-projects/package.json new file mode 100644 index 000000000000..142909ad236a --- /dev/null +++ b/e2e/run-programmatically-multiple-projects/package.json @@ -0,0 +1,6 @@ +{ + "name": "runcli-multiple-projects", + "version": "1.0.0", + "dependencies": {}, + "jest": {} +} diff --git a/e2e/run-programmatically-multiple-projects/run-jest.js b/e2e/run-programmatically-multiple-projects/run-jest.js new file mode 100644 index 000000000000..06d66e72f007 --- /dev/null +++ b/e2e/run-programmatically-multiple-projects/run-jest.js @@ -0,0 +1,22 @@ +/** + * 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. + */ + +const {runCLI} = require('@jest/core'); + +const config = { + projects: [ + {testMatch: ['/client/**/*.test.js']}, + {testMatch: ['/server/**/*.test.js']}, + ], +}; + +runCLI({config: JSON.stringify(config)}, [process.cwd()]) + .then(() => console.log('run-programmatically-mutiple-projects completed')) + .catch(err => { + console.error(err); + process.exitCode = 1; + }); diff --git a/e2e/run-programmatically-multiple-projects/server/server.test.js b/e2e/run-programmatically-multiple-projects/server/server.test.js new file mode 100644 index 000000000000..96820356c380 --- /dev/null +++ b/e2e/run-programmatically-multiple-projects/server/server.test.js @@ -0,0 +1,10 @@ +/** + * 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. + */ + +describe('server', () => { + it('should work', () => {}); +}); diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 490cc769000d..35bc4f524e85 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -38,7 +38,7 @@ export async function readConfig( // `project` property, we don't want to read `--config` value and rather // read individual configs for every project. skipArgvConfigOption?: boolean, - parentConfigPath?: Config.Path | null, + parentConfigDirname?: Config.Path | null, projectIndex: number = Infinity, ): Promise { let rawOptions: @@ -47,8 +47,7 @@ export async function readConfig( let configPath = null; if (typeof packageRootOrConfig !== 'string') { - if (parentConfigPath) { - const parentConfigDirname = path.dirname(parentConfigPath); + if (parentConfigDirname) { rawOptions = packageRootOrConfig; rawOptions.rootDir = rawOptions.rootDir ? replaceRootDirInPath(parentConfigDirname, rawOptions.rootDir) @@ -301,10 +300,9 @@ export async function readConfigs( } if (projects.length > 0) { - const projectIsCwd = - process.platform === 'win32' - ? projects[0] === tryRealpath(process.cwd()) - : projects[0] === process.cwd(); + const cwd = + process.platform === 'win32' ? tryRealpath(process.cwd()) : process.cwd(); + const projectIsCwd = projects[0] === cwd; const parsedConfigs = await Promise.all( projects @@ -332,7 +330,7 @@ export async function readConfigs( argv, root, skipArgvConfigOption, - configPath, + configPath ? path.dirname(configPath) : cwd, projectIndex, ); }),