From 3210659c78d2caa7afbf0a17a21ae48afc220ce6 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 31 Mar 2023 21:28:47 -0300 Subject: [PATCH 01/25] Loads .json config file when jest key has a path --- packages/jest-config/src/resolveConfigPath.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index 4010ff8dc6d0..c9cc7f8714d7 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -76,7 +76,9 @@ const resolveConfigPathByTraversing = ( const packageJson = findPackageJson(pathToResolve); if (packageJson && hasPackageJsonJestKey(packageJson)) { - configFiles.push(packageJson); + const referencedJsonConfig = findReferencingJsonByJestKey(packageJson); + + configFiles.push(referencedJsonConfig || packageJson); } if (!skipMultipleConfigError && configFiles.length > 1) { @@ -111,6 +113,19 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; +const findReferencingJsonByJestKey = (packagePath: string) => { + try { + const content = fs().readFileSync(packagePath, 'utf8'); + const jestConfigPath = JSON.parse(content).jest; + + if (typeof jestConfigPath === 'string' && isFile(jestConfigPath)) { + return path().resolve(jestConfigPath); + } + } catch { + return undefined; + } +}; + const hasPackageJsonJestKey = (packagePath: string) => { const content = fs.readFileSync(packagePath, 'utf8'); try { From 398dc0629b14bce2813583f247736c05fd8bc6b4 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 31 Mar 2023 21:30:08 -0300 Subject: [PATCH 02/25] Adds feature explaining section for docs --- docs/Configuration.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/Configuration.md b/docs/Configuration.md index ed7eb7c09f00..cd14bdb3fb72 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -81,6 +81,14 @@ Alternatively Jest's configuration can be defined through the `"jest"` key in th } ``` +Also Jest's configuration json can be referenced through the `"jest"` key in the `package.json` of your project: + +```json title="package.json" +{ + "name": "my-project", + "jest": "" +} + ## Options :::info From d0fd07de6d4b2000e9a473fc7ca3446fa33faff6 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 31 Mar 2023 21:55:04 -0300 Subject: [PATCH 03/25] Adds changelog info --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index feea55330ed2..434f3fa2f624 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-changed-files]` Loads .json config file from provided path in package.json ([#13941]()) + ### Fixes - `[jest-environment-jsdom, jest-environment-node]` Fix assignment of `customExportConditions` via `testEnvironmentOptions` when custom env subclass defines a default value ([#13989](https://github.com/facebook/jest/pull/13989)) From 22250773dfa1662d3a48554e670675aadb0c9888 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 31 Mar 2023 22:10:36 -0300 Subject: [PATCH 04/25] Update changelog with PR info --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 434f3fa2f624..e664d8e8f52f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -- `[jest-changed-files]` Loads .json config file from provided path in package.json ([#13941]()) +- `[jest-changed-files]` Loads .json config file from provided path in package.json ([#14044](https://github.com/facebook/jest/pull/14044)) ### Fixes From 0948287c8a01a9a1b1702a99d14a7c3893e39f3d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 5 Apr 2023 12:15:14 +0200 Subject: [PATCH 05/25] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e664d8e8f52f..3b9ee543d6e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -- `[jest-changed-files]` Loads .json config file from provided path in package.json ([#14044](https://github.com/facebook/jest/pull/14044)) +- `[jest-config]` Loads .json config file from provided path in package.json ([#14044](https://github.com/facebook/jest/pull/14044)) ### Fixes From c539a993053b36e205bef0c30fa6edf8b2a3202a Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 5 Apr 2023 19:12:26 -0300 Subject: [PATCH 06/25] fix non callable expressions --- packages/jest-config/src/resolveConfigPath.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index c9cc7f8714d7..04b03832c90b 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -115,11 +115,11 @@ const findPackageJson = (pathToResolve: string) => { const findReferencingJsonByJestKey = (packagePath: string) => { try { - const content = fs().readFileSync(packagePath, 'utf8'); + const content = fs.readFileSync(packagePath, 'utf8'); const jestConfigPath = JSON.parse(content).jest; if (typeof jestConfigPath === 'string' && isFile(jestConfigPath)) { - return path().resolve(jestConfigPath); + return path.resolve(jestConfigPath); } } catch { return undefined; From 0a211222e8c2b5dc03d1ec711bc3c8d518054420 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 5 Apr 2023 19:30:48 -0300 Subject: [PATCH 07/25] Fixed formatting issues in Configuration.md --- docs/Configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Configuration.md b/docs/Configuration.md index cd14bdb3fb72..5847bb708fbe 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -88,6 +88,7 @@ Also Jest's configuration json can be referenced through the `"jest"` key in the "name": "my-project", "jest": "" } +``` ## Options From 111ce1193356bc379c9482d54773e2d21fe3bd44 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 5 Apr 2023 22:03:41 -0300 Subject: [PATCH 08/25] Refactor to optimize readFileAsync calls --- packages/jest-config/src/resolveConfigPath.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index 04b03832c90b..bd2a34de8952 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -75,10 +75,9 @@ const resolveConfigPathByTraversing = ( ).filter(isFile); const packageJson = findPackageJson(pathToResolve); - if (packageJson && hasPackageJsonJestKey(packageJson)) { - const referencedJsonConfig = findReferencingJsonByJestKey(packageJson); - configFiles.push(referencedJsonConfig || packageJson); + if (packageJson) { + configFiles.push(resolveJestKey(packageJson) || packageJson); } if (!skipMultipleConfigError && configFiles.length > 1) { @@ -113,23 +112,28 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const findReferencingJsonByJestKey = (packagePath: string) => { +const resolveJestKey = (packagePath: string) => { try { const content = fs.readFileSync(packagePath, 'utf8'); - const jestConfigPath = JSON.parse(content).jest; + const parsedPackageJson = JSON.parse(content); - if (typeof jestConfigPath === 'string' && isFile(jestConfigPath)) { - return path.resolve(jestConfigPath); + if(hasPackageJsonJestKey(parsedPackageJson)){ + const { jest } = parsedPackageJson; + + if (typeof jest === 'string' && isFile(jest)) { + return path.resolve(jest); + } } + + return packagePath; } catch { return undefined; } }; -const hasPackageJsonJestKey = (packagePath: string) => { - const content = fs.readFileSync(packagePath, 'utf8'); +const hasPackageJsonJestKey = (parsedPackageJson: any) => { try { - return 'jest' in JSON.parse(content); + return 'jest' in parsedPackageJson; } catch { // If package is not a valid JSON return false; From 26f5427f44ada9fbddcef0e48d3bad4b0638d55e Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 9 Aug 2023 11:57:29 -0300 Subject: [PATCH 09/25] Lint fixing for resolveConfigPath --- packages/jest-config/src/resolveConfigPath.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index bd2a34de8952..ecf14196fba8 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -115,16 +115,16 @@ const findPackageJson = (pathToResolve: string) => { const resolveJestKey = (packagePath: string) => { try { const content = fs.readFileSync(packagePath, 'utf8'); - const parsedPackageJson = JSON.parse(content); + const parsedPackageJson = JSON.parse(content); - if(hasPackageJsonJestKey(parsedPackageJson)){ - const { jest } = parsedPackageJson; + if (hasPackageJsonJestKey(parsedPackageJson)) { + const {jest} = parsedPackageJson; if (typeof jest === 'string' && isFile(jest)) { return path.resolve(jest); } } - + return packagePath; } catch { return undefined; From b3379dcec6a3be372683de3a616177de5b99be4c Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 9 Aug 2023 12:14:44 -0300 Subject: [PATCH 10/25] Fixes code style issues from prettier --- docs/Configuration.md | 1 + website/versioned_docs/version-29.6/Configuration.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/Configuration.md b/docs/Configuration.md index cbf9b29d28a3..f43edf9ac5fc 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -1186,6 +1186,7 @@ export default config; ``` We hope to support Prettier v3 seamlessly out of the box in a future version of Jest. See [this](https://github.com/jestjs/jest/issues/14305) tracking issue. + ### `projects` \[array<string | ProjectConfig>] diff --git a/website/versioned_docs/version-29.6/Configuration.md b/website/versioned_docs/version-29.6/Configuration.md index f60f505bef71..0fe862f4bb3d 100644 --- a/website/versioned_docs/version-29.6/Configuration.md +++ b/website/versioned_docs/version-29.6/Configuration.md @@ -1177,6 +1177,7 @@ export default config; ``` We hope to support Prettier v3 seamlessly out of the box in a future version of Jest. See [this](https://github.com/jestjs/jest/issues/14305) tracking issue. + ### `projects` \[array<string | ProjectConfig>] From dd4238b9844a46c054b7d5f226fe426b307a50d1 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Thu, 10 Aug 2023 23:27:12 -0300 Subject: [PATCH 11/25] Avoid multiple configuration files --- packages/jest-config/src/resolveConfigPath.ts | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index ecf14196fba8..d74ffbd27dcd 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -77,7 +77,16 @@ const resolveConfigPathByTraversing = ( const packageJson = findPackageJson(pathToResolve); if (packageJson) { - configFiles.push(resolveJestKey(packageJson) || packageJson); + try { + const packageContent = fs.readFileSync(packageJson, 'utf8'); + const parsedPackageJson = JSON.parse(packageContent); + + if (hasPackageJsonJestKey(parsedPackageJson)) { + configFiles.push(resolveJestKey(parsedPackageJson) || packageJson); + } + } catch (err) { + throw new Error(makeLoadFileErrorMessage(initialPath, cwd, err)); + } } if (!skipMultipleConfigError && configFiles.length > 1) { @@ -112,23 +121,16 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (packagePath: string) => { - try { - const content = fs.readFileSync(packagePath, 'utf8'); - const parsedPackageJson = JSON.parse(content); - - if (hasPackageJsonJestKey(parsedPackageJson)) { - const {jest} = parsedPackageJson; +const resolveJestKey = (parsedPackageJson: any) => { + if (hasPackageJsonJestKey(parsedPackageJson)) { + const {jest} = parsedPackageJson; - if (typeof jest === 'string' && isFile(jest)) { - return path.resolve(jest); - } + if (jest && typeof jest === 'string' && isFile(jest)) { + return path.resolve(jest); } - - return packagePath; - } catch { - return undefined; } + + return undefined; }; const hasPackageJsonJestKey = (parsedPackageJson: any) => { @@ -140,6 +142,19 @@ const hasPackageJsonJestKey = (parsedPackageJson: any) => { } }; +const makeLoadFileErrorMessage = ( + initialPath: string, + cwd: string, + error: any, +) => + 'Trying to load a config file based on provided values:\n' + + `path: "${initialPath}"\n` + + `cwd: "${cwd}"\n` + + 'resulted in an error:\n' + + `${error}\n` + + 'Make sure your package.json "jest" key are an valid\n' + + 'object or points to a valid config file\n'; + const makeResolutionErrorMessage = (initialPath: string, cwd: string) => 'Could not find a config file based on provided values:\n' + `path: "${initialPath}"\n` + From 517e3023e22e4a6d6e212d55b59638777895021b Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 11 Aug 2023 00:36:04 -0300 Subject: [PATCH 12/25] Remove unecessary try-catch --- packages/jest-config/src/resolveConfigPath.ts | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index d74ffbd27dcd..2d35ff3bdff3 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -77,15 +77,11 @@ const resolveConfigPathByTraversing = ( const packageJson = findPackageJson(pathToResolve); if (packageJson) { - try { - const packageContent = fs.readFileSync(packageJson, 'utf8'); - const parsedPackageJson = JSON.parse(packageContent); - - if (hasPackageJsonJestKey(parsedPackageJson)) { - configFiles.push(resolveJestKey(parsedPackageJson) || packageJson); - } - } catch (err) { - throw new Error(makeLoadFileErrorMessage(initialPath, cwd, err)); + const packageContent = fs.readFileSync(packageJson, 'utf8'); + const parsedPackageJson = JSON.parse(packageContent); + + if (hasPackageJsonJestKey(parsedPackageJson)) { + configFiles.push(resolveJestKey(parsedPackageJson) || packageJson); } } @@ -142,19 +138,6 @@ const hasPackageJsonJestKey = (parsedPackageJson: any) => { } }; -const makeLoadFileErrorMessage = ( - initialPath: string, - cwd: string, - error: any, -) => - 'Trying to load a config file based on provided values:\n' + - `path: "${initialPath}"\n` + - `cwd: "${cwd}"\n` + - 'resulted in an error:\n' + - `${error}\n` + - 'Make sure your package.json "jest" key are an valid\n' + - 'object or points to a valid config file\n'; - const makeResolutionErrorMessage = (initialPath: string, cwd: string) => 'Could not find a config file based on provided values:\n' + `path: "${initialPath}"\n` + From 8f326a26d4aacedaaa621081cf09f94ec26c4984 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 11 Aug 2023 01:00:16 -0300 Subject: [PATCH 13/25] Refactor for "jest" key catch on parse errors --- packages/jest-config/src/resolveConfigPath.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index 2d35ff3bdff3..93d6f3c60a15 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -78,10 +78,9 @@ const resolveConfigPathByTraversing = ( if (packageJson) { const packageContent = fs.readFileSync(packageJson, 'utf8'); - const parsedPackageJson = JSON.parse(packageContent); - if (hasPackageJsonJestKey(parsedPackageJson)) { - configFiles.push(resolveJestKey(parsedPackageJson) || packageJson); + if (hasPackageJsonJestKey(packageContent)) { + configFiles.push(resolveJestKey(packageContent) || packageJson); } } @@ -117,9 +116,9 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (parsedPackageJson: any) => { - if (hasPackageJsonJestKey(parsedPackageJson)) { - const {jest} = parsedPackageJson; +const resolveJestKey = (packageContent: any) => { + if (hasPackageJsonJestKey(packageContent)) { + const {jest} = JSON.parse(packageContent); if (jest && typeof jest === 'string' && isFile(jest)) { return path.resolve(jest); @@ -129,9 +128,9 @@ const resolveJestKey = (parsedPackageJson: any) => { return undefined; }; -const hasPackageJsonJestKey = (parsedPackageJson: any) => { +const hasPackageJsonJestKey = (packageContent: any) => { try { - return 'jest' in parsedPackageJson; + return 'jest' in JSON.parse(packageContent); } catch { // If package is not a valid JSON return false; From e50fda76e75df7497db1835235a38092a19d8b96 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 11 Aug 2023 01:38:47 -0300 Subject: [PATCH 14/25] adds test case for load config file from jest key --- .../src/__tests__/resolveConfigPath.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 0b16288ba1fd..e65f566a35e3 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -45,6 +45,25 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( ); }); + test('file path from "jest" key', () => { + const anyFileName = `anyJestConfigfile.name${extension}`; + const packageJsonPath = 'a/b/c/package.json'; + const anyFilePath = `a/b/c/conf/${anyFileName}`; + + const absolutePackageJsonPath = path.resolve(DIR, packageJsonPath); + + jest + .mocked(fs.readFileSync) + .mockReturnValueOnce(`{ "jest": "conf/${anyFileName}" }`); + + writeFiles(DIR, {[packageJsonPath]: ''}); + writeFiles(DIR, {[anyFilePath]: ''}); + + expect(() => + resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), + ).toBe(anyFilePath); + }); + test(`directory path with "${extension}"`, () => { const relativePackageJsonPath = 'a/b/c/package.json'; const absolutePackageJsonPath = path.resolve( From 1f3b8f0fa4cca63eeca25cf9407c100b1fba46e5 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 11 Aug 2023 02:12:24 -0300 Subject: [PATCH 15/25] Adds fs dependency --- packages/jest-config/src/__tests__/resolveConfigPath.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index e65f566a35e3..42371fe8672a 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -7,6 +7,7 @@ import {tmpdir} from 'os'; import * as path from 'path'; +import * as fs from 'graceful-fs'; import {cleanup, writeFiles} from '../../../../e2e/Utils'; import {JEST_CONFIG_EXT_ORDER} from '../constants'; import resolveConfigPath from '../resolveConfigPath'; From 94e23f251dc896fe91fb057b3cb34e64e95bd9ca Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Fri, 11 Aug 2023 23:05:05 -0300 Subject: [PATCH 16/25] Test and fix file resolution --- .../src/__tests__/resolveConfigPath.test.ts | 57 ++++++++++++++----- packages/jest-config/src/resolveConfigPath.ts | 12 ++-- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 42371fe8672a..44c17e3ee57a 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -7,7 +7,6 @@ import {tmpdir} from 'os'; import * as path from 'path'; -import * as fs from 'graceful-fs'; import {cleanup, writeFiles} from '../../../../e2e/Utils'; import {JEST_CONFIG_EXT_ORDER} from '../constants'; import resolveConfigPath from '../resolveConfigPath'; @@ -47,22 +46,54 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); test('file path from "jest" key', () => { - const anyFileName = `anyJestConfigfile.name${extension}`; - const packageJsonPath = 'a/b/c/package.json'; - const anyFilePath = `a/b/c/conf/${anyFileName}`; + // Arrange + const anyFileName = `anyJestConfigfile${extension}`; + const relativePackageJsonPath = 'a/b/c/package.json'; + const relativeAnyFilePath = `a/b/c/conf/${anyFileName}`; + const absolutePackageJsonPath = path.resolve( + DIR, + relativePackageJsonPath, + ); + const absoluteAnyFilePath = path.resolve(DIR, relativeAnyFilePath); - const absolutePackageJsonPath = path.resolve(DIR, packageJsonPath); + writeFiles(DIR, { + 'a/b/c/package.json': `{ "jest": "conf/${anyFileName}" }`, + }); + writeFiles(DIR, {[relativeAnyFilePath]: ''}); - jest - .mocked(fs.readFileSync) - .mockReturnValueOnce(`{ "jest": "conf/${anyFileName}" }`); + // Act + const result = resolveConfigPath( + path.dirname(absolutePackageJsonPath), + DIR, + ); - writeFiles(DIR, {[packageJsonPath]: ''}); - writeFiles(DIR, {[anyFilePath]: ''}); + // Assert + expect(result).toBe(absoluteAnyFilePath); + }); - expect(() => - resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), - ).toBe(anyFilePath); + test('not a file path from "jest" key', () => { + // Arrange + const anyFileName = `anyJestConfigfile${extension}`; + const relativePackageJsonPath = 'a/b/c/package.json'; + const relativeAnyFilePath = `a/b/c/conf/${anyFileName}`; + const absolutePackageJsonPath = path.resolve( + DIR, + relativePackageJsonPath, + ); + + writeFiles(DIR, { + 'a/b/c/package.json': '{ "jest": {"verbose": true} }', + }); + writeFiles(DIR, {[relativeAnyFilePath]: ''}); + + // Act + const result = resolveConfigPath( + path.dirname(absolutePackageJsonPath), + DIR, + ); + + // Assert + expect(result).toBe(absolutePackageJsonPath); }); test(`directory path with "${extension}"`, () => { diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index 93d6f3c60a15..e7baa7f2f754 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -78,9 +78,11 @@ const resolveConfigPathByTraversing = ( if (packageJson) { const packageContent = fs.readFileSync(packageJson, 'utf8'); + const packagePath = path.dirname(packageJson); + const resolvedKey = resolveJestKey(packageContent, packagePath); if (hasPackageJsonJestKey(packageContent)) { - configFiles.push(resolveJestKey(packageContent) || packageJson); + configFiles.push(resolvedKey || packageJson); } } @@ -116,12 +118,14 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (packageContent: any) => { +const resolveJestKey = (packageContent: any, packagePath: string) => { if (hasPackageJsonJestKey(packageContent)) { const {jest} = JSON.parse(packageContent); - if (jest && typeof jest === 'string' && isFile(jest)) { - return path.resolve(jest); + if (jest && typeof jest === 'string') { + const resolvedConfigFile = path.resolve(packagePath, jest); + + return isFile(resolvedConfigFile) ? resolvedConfigFile : undefined; } } From 8fcfa682bf21cb5fccac3f669101d0d3270049c3 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Sat, 12 Aug 2023 00:15:54 -0300 Subject: [PATCH 17/25] Improves doc example --- docs/Configuration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index f43edf9ac5fc..93740cd1bb98 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -81,12 +81,12 @@ Alternatively Jest's configuration can be defined through the `"jest"` key in th } ``` -Also Jest's configuration json can be referenced through the `"jest"` key in the `package.json` of your project: +Also Jest's configuration json file can be referenced through the `"jest"` key in the `package.json` of your project: ```json title="package.json" { "name": "my-project", - "jest": "" + "jest": "" } ``` From d1747942edeb6f25f815bb2b3e6644c6081cbb3e Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Sat, 12 Aug 2023 22:06:14 -0300 Subject: [PATCH 18/25] Update docs/Configuration.md Co-authored-by: Tom Mrazauskas --- docs/Configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index 93740cd1bb98..00abd6e66e37 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -86,7 +86,7 @@ Also Jest's configuration json file can be referenced through the `"jest"` key i ```json title="package.json" { "name": "my-project", - "jest": "" + "jest": "./path/to/config.json" } ``` From fce78ca2ac484c84bb47b9efcb758ef6d3b01fea Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 16 Aug 2023 14:49:35 -0300 Subject: [PATCH 19/25] Remove AAA comments from tests --- .../jest-config/src/__tests__/resolveConfigPath.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 44c17e3ee57a..f2cd0765df01 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -46,7 +46,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); test('file path from "jest" key', () => { - // Arrange const anyFileName = `anyJestConfigfile${extension}`; const relativePackageJsonPath = 'a/b/c/package.json'; const relativeAnyFilePath = `a/b/c/conf/${anyFileName}`; @@ -61,18 +60,15 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); writeFiles(DIR, {[relativeAnyFilePath]: ''}); - // Act const result = resolveConfigPath( path.dirname(absolutePackageJsonPath), DIR, ); - // Assert expect(result).toBe(absoluteAnyFilePath); }); test('not a file path from "jest" key', () => { - // Arrange const anyFileName = `anyJestConfigfile${extension}`; const relativePackageJsonPath = 'a/b/c/package.json'; const relativeAnyFilePath = `a/b/c/conf/${anyFileName}`; @@ -86,13 +82,11 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); writeFiles(DIR, {[relativeAnyFilePath]: ''}); - // Act const result = resolveConfigPath( path.dirname(absolutePackageJsonPath), DIR, ); - // Assert expect(result).toBe(absolutePackageJsonPath); }); From 6149986dea489feac70705afe827074ebe5afbe5 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 16 Aug 2023 14:56:37 -0300 Subject: [PATCH 20/25] make resolveJestKey types well defined --- packages/jest-config/src/resolveConfigPath.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index e7baa7f2f754..b9c7616f16a8 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -118,7 +118,7 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (packageContent: any, packagePath: string) => { +const resolveJestKey = (packageContent: string, packagePath: string) => { if (hasPackageJsonJestKey(packageContent)) { const {jest} = JSON.parse(packageContent); From af8716bbe0c0c2f3f5439d4c8467e3faa8f4429c Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 16 Aug 2023 19:30:27 -0300 Subject: [PATCH 21/25] Aditional typing refactor --- packages/jest-config/src/resolveConfigPath.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index b9c7616f16a8..c83d3500ad34 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -132,7 +132,7 @@ const resolveJestKey = (packageContent: string, packagePath: string) => { return undefined; }; -const hasPackageJsonJestKey = (packageContent: any) => { +const hasPackageJsonJestKey = (packageContent: string) => { try { return 'jest' in JSON.parse(packageContent); } catch { From 78c0ba5e6bdfd7e1e8b28c5d6d93edf3f4867b07 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 16 Aug 2023 19:32:46 -0300 Subject: [PATCH 22/25] Test case for when jest key is not a valid file --- .../src/__tests__/resolveConfigPath.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index f2cd0765df01..a0e00f5f074b 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -90,6 +90,28 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( expect(result).toBe(absolutePackageJsonPath); }); + test('not a valid file when "jest" key is a path', () => { + const anyFileName = `anyJestConfigfile${extension}`; + const relativePackageJsonPath = 'a/b/c/package.json'; + const relativeAnyFilePath = `a/b/c/conf/${anyFileName}`; + const absolutePackageJsonPath = path.resolve( + DIR, + relativePackageJsonPath, + ); + + writeFiles(DIR, { + 'a/b/c/package.json': '{ "jest": "conf/nonExistentConfigfile.json" }', + }); + writeFiles(DIR, {[relativeAnyFilePath]: ''}); + + const result = resolveConfigPath( + path.dirname(absolutePackageJsonPath), + DIR, + ); + + expect(result).toBe(absolutePackageJsonPath); + }); + test(`directory path with "${extension}"`, () => { const relativePackageJsonPath = 'a/b/c/package.json'; const absolutePackageJsonPath = path.resolve( From b552e1901669f64be7f147c700f13e2751b82d29 Mon Sep 17 00:00:00 2001 From: Rafael Rabelo Date: Wed, 16 Aug 2023 21:27:14 -0300 Subject: [PATCH 23/25] Optmize Parse calls --- packages/jest-config/src/resolveConfigPath.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index c83d3500ad34..a440b7b7df90 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -77,11 +77,12 @@ const resolveConfigPathByTraversing = ( const packageJson = findPackageJson(pathToResolve); if (packageJson) { - const packageContent = fs.readFileSync(packageJson, 'utf8'); const packagePath = path.dirname(packageJson); - const resolvedKey = resolveJestKey(packageContent, packagePath); + const jestKey = getPackageJsonJestKey(packageJson); + + if (jestKey) { + const resolvedKey = resolveJestKey(jestKey, packagePath); - if (hasPackageJsonJestKey(packageContent)) { configFiles.push(resolvedKey || packageJson); } } @@ -118,23 +119,22 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (packageContent: string, packagePath: string) => { - if (hasPackageJsonJestKey(packageContent)) { - const {jest} = JSON.parse(packageContent); - - if (jest && typeof jest === 'string') { - const resolvedConfigFile = path.resolve(packagePath, jest); +const resolveJestKey = (jestKeyContent: any, packagePath: string) => { + if (jestKeyContent && typeof jestKeyContent === 'string') { + const resolvedConfigFile = path.resolve(packagePath, jestKeyContent); - return isFile(resolvedConfigFile) ? resolvedConfigFile : undefined; - } + return isFile(resolvedConfigFile) ? resolvedConfigFile : undefined; } return undefined; }; -const hasPackageJsonJestKey = (packageContent: string) => { +const getPackageJsonJestKey = (packageJsonPath: string) => { try { - return 'jest' in JSON.parse(packageContent); + const packageContent = fs.readFileSync(packageJsonPath, 'utf8'); + const parsed = JSON.parse(packageContent); + + if ('jest' in parsed) return parsed.jest ?? false; } catch { // If package is not a valid JSON return false; From 00167aff90c7a5ed9290ecbcc212fe2c3970855f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 27 Nov 2023 09:24:11 +0100 Subject: [PATCH 24/25] do not support directory --- CHANGELOG.md | 2 +- .../src/__tests__/resolveConfigPath.test.ts | 75 +------------------ packages/jest-config/src/resolveConfigPath.ts | 56 ++++++++------ 3 files changed, 37 insertions(+), 96 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc86aabda2f..25b3a5e1e402 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - `[jest-circus, jest-cli, jest-config]` Add `waitNextEventLoopTurnForUnhandledRejectionEvents` flag to minimise performance impact of correct detection of unhandled promise rejections introduced in [#14315](https://github.com/jestjs/jest/pull/14315) ([#14681](https://github.com/jestjs/jest/pull/14681)) - `[jest-config]` [**BREAKING**] Add `mts` and `cts` to default `moduleFileExtensions` config ([#14369](https://github.com/facebook/jest/pull/14369)) - `[jest-config]` [**BREAKING**] Update `testMatch` and `testRegex` default option for supporting `mjs`, `cjs`, `mts`, and `cts` ([#14584](https://github.com/jestjs/jest/pull/14584)) -- `[jest-config]` Loads `.json` config file from provided path in package.json ([#14044](https://github.com/facebook/jest/pull/14044)) +- `[jest-config]` Loads config file from provided path in `package.json` ([#14044](https://github.com/facebook/jest/pull/14044)) - `[@jest/core]` [**BREAKING**] Group together open handles with the same stack trace ([#13417](https://github.com/jestjs/jest/pull/13417), & [#14543](https://github.com/jestjs/jest/pull/14543)) - `[@jest/core]` Add `perfStats` to surface test setup overhead ([#14622](https://github.com/jestjs/jest/pull/14622)) - `[@jest/core]` [**BREAKING**] Changed `--filter` to accept an object with shape `{ filtered: Array }` to match [documentation](https://jestjs.io/docs/cli#--filterfile) ([#13319](https://github.com/jestjs/jest/pull/13319)) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index a0e00f5f074b..199ea60f8585 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -104,80 +104,11 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); writeFiles(DIR, {[relativeAnyFilePath]: ''}); - const result = resolveConfigPath( - path.dirname(absolutePackageJsonPath), - DIR, - ); - - expect(result).toBe(absolutePackageJsonPath); - }); - - test(`directory path with "${extension}"`, () => { - const relativePackageJsonPath = 'a/b/c/package.json'; - const absolutePackageJsonPath = path.resolve( - DIR, - relativePackageJsonPath, - ); - const relativeJestConfigPath = `a/b/c/jest.config${extension}`; - const absoluteJestConfigPath = path.resolve(DIR, relativeJestConfigPath); - - // no configs yet. should throw - writeFiles(DIR, {[`a/b/c/some_random_file${extension}`]: ''}); - - expect(() => - // absolute - resolveConfigPath(path.dirname(absoluteJestConfigPath), DIR), - ).toThrow(ERROR_PATTERN); - - expect(() => - // relative - resolveConfigPath(path.dirname(relativeJestConfigPath), DIR), - ).toThrow(ERROR_PATTERN); - - writeFiles(DIR, {[relativePackageJsonPath]: ''}); - - // absolute - expect( - resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), - ).toBe(absolutePackageJsonPath); - - // relative - expect( - resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), - ).toBe(absolutePackageJsonPath); - - // jest.config.js takes precedence - writeFiles(DIR, {[relativeJestConfigPath]: ''}); - - // absolute - expect( - resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), - ).toBe(absoluteJestConfigPath); - - // relative - expect( - resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), - ).toBe(absoluteJestConfigPath); - - // jest.config.js and package.json with 'jest' cannot be used together - writeFiles(DIR, {[relativePackageJsonPath]: JSON.stringify({jest: {}})}); - - // absolute expect(() => resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), - ).toThrow(MULTIPLE_CONFIGS_ERROR_PATTERN); - - // relative - expect(() => - resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), - ).toThrow(MULTIPLE_CONFIGS_ERROR_PATTERN); - - expect(() => { - resolveConfigPath( - path.join(path.dirname(relativePackageJsonPath), 'j/x/b/m/'), - DIR, - ); - }).toThrow(NO_ROOT_DIR_ERROR_PATTERN); + ).toThrow( + 'Jest expects the string configuration to point to a file, but it does not.', + ); }); }, ); diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index a440b7b7df90..4843fd94f3c2 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -81,9 +81,27 @@ const resolveConfigPathByTraversing = ( const jestKey = getPackageJsonJestKey(packageJson); if (jestKey) { - const resolvedKey = resolveJestKey(jestKey, packagePath); - - configFiles.push(resolvedKey || packageJson); + if (typeof jestKey === 'string') { + const absolutePath = path.isAbsolute(jestKey) + ? jestKey + : path.resolve(packagePath, jestKey); + + if (!isFile(absolutePath)) { + throw new ValidationError( + `${BULLET}Validation Error`, + ` Configuration in ${chalk.bold(packageJson)} is not valid. ` + + 'Jest expects the string configuration to point to a file, but it does not. ' + + `Please check your Jest configuration in ${chalk.bold( + packageJson, + )}.`, + DOCUMENTATION_NOTE, + ); + } + + configFiles.push(absolutePath); + } else { + configFiles.push(packageJson); + } } } @@ -91,8 +109,8 @@ const resolveConfigPathByTraversing = ( throw new ValidationError(...makeMultipleConfigsErrorMessage(configFiles)); } - if (configFiles.length > 0 || packageJson) { - return configFiles[0] ?? packageJson; + if (configFiles.length > 0) { + return configFiles[0]; } // This is the system root. @@ -119,26 +137,18 @@ const findPackageJson = (pathToResolve: string) => { return undefined; }; -const resolveJestKey = (jestKeyContent: any, packagePath: string) => { - if (jestKeyContent && typeof jestKeyContent === 'string') { - const resolvedConfigFile = path.resolve(packagePath, jestKeyContent); - - return isFile(resolvedConfigFile) ? resolvedConfigFile : undefined; - } - - return undefined; -}; - -const getPackageJsonJestKey = (packageJsonPath: string) => { +const getPackageJsonJestKey = ( + packagePath: string, +): Record | string | undefined => { try { - const packageContent = fs.readFileSync(packageJsonPath, 'utf8'); - const parsed = JSON.parse(packageContent); + const content = fs.readFileSync(packagePath, 'utf8'); + const parsedContent = JSON.parse(content); - if ('jest' in parsed) return parsed.jest ?? false; - } catch { - // If package is not a valid JSON - return false; - } + if ('jest' in parsedContent) { + return parsedContent.jest; + } + } catch {} + return undefined; }; const makeResolutionErrorMessage = (initialPath: string, cwd: string) => From 886420cb49d6011136017b84714ddae20b480dde Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 27 Nov 2023 09:27:42 +0100 Subject: [PATCH 25/25] bring test back, and simplify --- .../src/__tests__/resolveConfigPath.test.ts | 70 ++++++++++++++++++- packages/jest-config/src/resolveConfigPath.ts | 9 ++- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 199ea60f8585..a1d9b51a1987 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -45,6 +45,74 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( ); }); + test(`directory path with "${extension}"`, () => { + const relativePackageJsonPath = 'a/b/c/package.json'; + const absolutePackageJsonPath = path.resolve( + DIR, + relativePackageJsonPath, + ); + const relativeJestConfigPath = `a/b/c/jest.config${extension}`; + const absoluteJestConfigPath = path.resolve(DIR, relativeJestConfigPath); + + // no configs yet. should throw + writeFiles(DIR, {[`a/b/c/some_random_file${extension}`]: ''}); + + expect(() => + // absolute + resolveConfigPath(path.dirname(absoluteJestConfigPath), DIR), + ).toThrow(ERROR_PATTERN); + + expect(() => + // relative + resolveConfigPath(path.dirname(relativeJestConfigPath), DIR), + ).toThrow(ERROR_PATTERN); + + writeFiles(DIR, {[relativePackageJsonPath]: ''}); + + // absolute + expect( + resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), + ).toBe(absolutePackageJsonPath); + + // relative + expect( + resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), + ).toBe(absolutePackageJsonPath); + + // jest.config.js takes precedence + writeFiles(DIR, {[relativeJestConfigPath]: ''}); + + // absolute + expect( + resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), + ).toBe(absoluteJestConfigPath); + + // relative + expect( + resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), + ).toBe(absoluteJestConfigPath); + + // jest.config.js and package.json with 'jest' cannot be used together + writeFiles(DIR, {[relativePackageJsonPath]: JSON.stringify({jest: {}})}); + + // absolute + expect(() => + resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), + ).toThrow(MULTIPLE_CONFIGS_ERROR_PATTERN); + + // relative + expect(() => + resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), + ).toThrow(MULTIPLE_CONFIGS_ERROR_PATTERN); + + expect(() => { + resolveConfigPath( + path.join(path.dirname(relativePackageJsonPath), 'j/x/b/m/'), + DIR, + ); + }).toThrow(NO_ROOT_DIR_ERROR_PATTERN); + }); + test('file path from "jest" key', () => { const anyFileName = `anyJestConfigfile${extension}`; const relativePackageJsonPath = 'a/b/c/package.json'; @@ -107,7 +175,7 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( expect(() => resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), ).toThrow( - 'Jest expects the string configuration to point to a file, but it does not.', + /Jest expects the string configuration to point to a file, but .* not\./, ); }); }, diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index 4843fd94f3c2..d6cd21da82d2 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -77,20 +77,19 @@ const resolveConfigPathByTraversing = ( const packageJson = findPackageJson(pathToResolve); if (packageJson) { - const packagePath = path.dirname(packageJson); const jestKey = getPackageJsonJestKey(packageJson); if (jestKey) { if (typeof jestKey === 'string') { const absolutePath = path.isAbsolute(jestKey) ? jestKey - : path.resolve(packagePath, jestKey); + : path.resolve(pathToResolve, jestKey); if (!isFile(absolutePath)) { throw new ValidationError( `${BULLET}Validation Error`, ` Configuration in ${chalk.bold(packageJson)} is not valid. ` + - 'Jest expects the string configuration to point to a file, but it does not. ' + + `Jest expects the string configuration to point to a file, but ${absolutePath} is not. ` + `Please check your Jest configuration in ${chalk.bold( packageJson, )}.`, @@ -109,8 +108,8 @@ const resolveConfigPathByTraversing = ( throw new ValidationError(...makeMultipleConfigsErrorMessage(configFiles)); } - if (configFiles.length > 0) { - return configFiles[0]; + if (configFiles.length > 0 || packageJson) { + return configFiles[0] ?? packageJson; } // This is the system root.