diff --git a/CHANGELOG.md b/CHANGELOG.md index 917db93ebb8c..1bc7bedde190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Fixes - `[jest-runtime]` Fix issue where user cannot utilize dynamic import despite specifying `--experimental-vm-modules` Node option ([#15842](https://github.com/jestjs/jest/pull/15842)) +- `[jest-config]` Fix issue where custom reporters not loaded from legacy global module folder, i.e. `$HOME/.node_libraries` ([#15852](https://github.com/jestjs/jest/pull/15852)) ## 30.2.0 diff --git a/e2e/__tests__/customReporters.test.ts b/e2e/__tests__/customReporters.test.ts index bdd4b6c2063f..3f8db443d1c9 100644 --- a/e2e/__tests__/customReporters.test.ts +++ b/e2e/__tests__/customReporters.test.ts @@ -179,4 +179,36 @@ describe('Custom Reporters Integration', () => { expect(stderr).toMatch(/ON_RUN_START_ERROR/); expect(exitCode).toBe(1); }); + + test('supports custom reporter stored in legacy module path, i.e. $HOME/.node_libraries', () => { + writeFiles(DIR, { + '__tests__/test.test.js': "test('test', () => {});", + 'fakeHome/.node_libraries/@org/custom-reporter/index.js': ` + 'use strict'; + module.exports = class Reporter { + onRunStart() { + throw new Error('ON_RUN_START_ERROR'); + } + }; + `, + 'package.json': JSON.stringify({ + jest: { + reporters: ['@org/custom-reporter'], + }, + }), + }); + + const {stderr, exitCode} = runJest(DIR, undefined, { + env: { + HOME: path.resolve(DIR, 'fakeHome'), + // For Windows testing + USERPROFILE: + process.platform === 'win32' + ? path.resolve(DIR, 'fakeHome') + : undefined, + }, + }); + expect(stderr).toMatch(/ON_RUN_START_ERROR/); + expect(exitCode).toBe(1); + }); }); diff --git a/packages/jest-config/src/normalize.ts b/packages/jest-config/src/normalize.ts index e2ed840cf020..936f84374d53 100644 --- a/packages/jest-config/src/normalize.ts +++ b/packages/jest-config/src/normalize.ts @@ -26,6 +26,7 @@ import { clearLine, replacePathSepForGlob, requireOrImportModule, + specialChars, tryRealpath, } from 'jest-util'; import {ValidationError, validate} from 'jest-validate'; @@ -169,7 +170,9 @@ const setupPreset = async ( ); } throw createConfigError( - ` Preset ${chalk.bold(presetPath)} not found relative to rootDir ${chalk.bold(options.rootDir)}.`, + ` Preset ${chalk.bold( + presetPath, + )} not found relative to rootDir ${chalk.bold(options.rootDir)}.`, ); } throw createConfigError( @@ -378,8 +381,17 @@ const normalizeReporters = ({ ); if (!['default', 'github-actions', 'summary'].includes(reporterPath)) { + // There's a chance that users store custom reporter in legacy module paths + // such as $HOME/.node_libraries + const homeDir = specialChars.isWindows + ? process.env.USERPROFILE + : process.env.HOME; + const legacyModulePaths = homeDir + ? [path.resolve(homeDir, '.node_libraries')] + : undefined; const reporter = Resolver.findNodeModule(reporterPath, { basedir: rootDir, + paths: legacyModulePaths, }); if (!reporter) { throw new Resolver.ModuleNotFoundError( diff --git a/packages/jest-util/src/specialChars.ts b/packages/jest-util/src/specialChars.ts index e3dc1f561313..580777af26cb 100644 --- a/packages/jest-util/src/specialChars.ts +++ b/packages/jest-util/src/specialChars.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -const isWindows = process.platform === 'win32'; +export const isWindows = process.platform === 'win32'; export const ARROW = ' \u203A '; export const ICONS = {