Skip to content

Commit

Permalink
fix: config silently ignored in projects (#13565)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuibu authored Nov 7, 2022
1 parent 195cb4b commit f75a3aa
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

### Fixes

- `[jest-config]` Add config validation for `projects` option ([#13565](https://github.com/facebook/jest/pull/13565))
- `[jest-mock]` Treat cjs modules as objects so they can be mocked ([#13513](https://github.com/facebook/jest/pull/13513))
- `[jest-worker]` Throw an error instead of hanging when jest workers terminate unexpectedly ([#13566](https://github.com/facebook/jest/pull/13566))

Expand Down
115 changes: 113 additions & 2 deletions packages/jest-config/src/ValidConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {NODE_MODULES} from './constants';

const NODE_MODULES_REGEXP = replacePathSepForRegex(NODE_MODULES);

const initialOptions: Config.InitialOptions = {
export const initialOptions: Config.InitialOptions = {
automock: false,
bail: multipleValidOptions(false, 0),
cache: true,
Expand Down Expand Up @@ -188,4 +188,115 @@ const initialOptions: Config.InitialOptions = {
workerIdleMemoryLimit: multipleValidOptions(0.2, '50%'),
};

export default initialOptions;
export const initialProjectOptions: Config.InitialProjectOptions = {
automock: false,
cache: true,
cacheDirectory: '/tmp/user/jest',
clearMocks: false,
coveragePathIgnorePatterns: [NODE_MODULES_REGEXP],
dependencyExtractor: '<rootDir>/dependencyExtractor.js',
detectLeaks: false,
detectOpenHandles: false,
displayName: multipleValidOptions('test-config', {
color: 'blue',
name: 'test-config',
} as const),
errorOnDeprecated: false,
extensionsToTreatAsEsm: [],
fakeTimers: {
advanceTimers: multipleValidOptions(40, true),
doNotFake: [
'Date',
'hrtime',
'nextTick',
'performance',
'queueMicrotask',
'requestAnimationFrame',
'cancelAnimationFrame',
'requestIdleCallback',
'cancelIdleCallback',
'setImmediate',
'clearImmediate',
'setInterval',
'clearInterval',
'setTimeout',
'clearTimeout',
],
enableGlobally: true,
legacyFakeTimers: false,
now: 1483228800000,
timerLimit: 1000,
},
filter: '<rootDir>/filter.js',
forceCoverageMatch: ['**/*.t.js'],
globalSetup: 'setup.js',
globalTeardown: 'teardown.js',
globals: {__DEV__: true},
haste: {
computeSha1: true,
defaultPlatform: 'ios',
enableSymlinks: false,
forceNodeFilesystemAPI: true,
hasteImplModulePath: '<rootDir>/haste_impl.js',
hasteMapModulePath: '',
platforms: ['ios', 'android'],
retainAllFiles: false,
throwOnModuleCollision: false,
},
id: 'string',
injectGlobals: true,
moduleDirectories: ['node_modules'],
moduleFileExtensions: [
'js',
'mjs',
'cjs',
'json',
'jsx',
'ts',
'tsx',
'node',
],
moduleNameMapper: {
'^React$': '<rootDir>/node_modules/react',
},
modulePathIgnorePatterns: ['<rootDir>/build/'],
modulePaths: ['/shared/vendor/modules'],
prettierPath: '<rootDir>/node_modules/prettier',
resetMocks: false,
resetModules: false,
resolver: '<rootDir>/resolver.js',
restoreMocks: false,
rootDir: '/',
roots: ['<rootDir>'],
runner: 'jest-runner',
runtime: '<rootDir>',
sandboxInjectedGlobals: [],
setupFiles: ['<rootDir>/setup.js'],
setupFilesAfterEnv: ['<rootDir>/testSetupFile.js'],
skipFilter: false,
skipNodeResolution: false,
slowTestThreshold: 5,
snapshotFormat: PRETTY_FORMAT_DEFAULTS,
snapshotResolver: '<rootDir>/snapshotResolver.js',
snapshotSerializers: ['my-serializer-module'],
testEnvironment: 'jest-environment-node',
testEnvironmentOptions: {
url: 'http://localhost',
userAgent: 'Agent/007',
},
testLocationInResults: false,
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
testPathIgnorePatterns: [NODE_MODULES_REGEXP],
testRegex: multipleValidOptions(
'(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
['/__tests__/\\.test\\.[jt]sx?$', '/__tests__/\\.spec\\.[jt]sx?$'],
),
testRunner: 'circus',
transform: {
'\\.js$': '<rootDir>/preprocessor.js',
},
transformIgnorePatterns: [NODE_MODULES_REGEXP],
unmockedModulePathPatterns: ['mock'],
watchPathIgnorePatterns: ['<rootDir>/e2e/'],
workerIdleMemoryLimit: multipleValidOptions(0.2, '50%'),
};
17 changes: 17 additions & 0 deletions packages/jest-config/src/__tests__/normalize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ it('keeps custom project id based on the projects rootDir', async () => {
);
});

it('validation warning occurs when options not for projects is set', async () => {
const mockWarn = jest.mocked(console.warn).mockImplementation(() => {});
const rootDir = '/root/path/foo';
await normalize(
{
bail: true, // an option not for projects
rootDir,
},
{} as Config.Argv,
rootDir,
1,
true, // isProjectOptions
);

expect(mockWarn).toHaveBeenCalledTimes(1);
});

it('keeps custom ids based on the rootDir', async () => {
const {options} = await normalize(
{
Expand Down
5 changes: 5 additions & 0 deletions packages/jest-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,16 @@ export async function readConfig(
},
);

const packageRoot =
typeof packageRootOrConfig === 'string'
? path.resolve(packageRootOrConfig)
: undefined;
const {options, hasDeprecationWarnings} = await normalize(
initialOptions,
argv,
configPath,
projectIndex,
skipArgvConfigOption && !(packageRoot === parentConfigDirname),
);

const {globalConfig, projectConfig} = groupOptions(options);
Expand Down
8 changes: 6 additions & 2 deletions packages/jest-config/src/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ import {ValidationError, validate} from 'jest-validate';
import DEFAULT_CONFIG from './Defaults';
import DEPRECATED_CONFIG from './Deprecated';
import {validateReporters} from './ReporterValidationErrors';
import VALID_CONFIG from './ValidConfig';
import {
initialOptions as VALID_CONFIG,
initialProjectOptions as VALID_PROJECT_CONFIG,
} from './ValidConfig';
import {getDisplayNameColor} from './color';
import {DEFAULT_JS_PATTERN} from './constants';
import getMaxWorkers from './getMaxWorkers';
Expand Down Expand Up @@ -487,14 +490,15 @@ export default async function normalize(
argv: Config.Argv,
configPath?: string | null,
projectIndex = Infinity,
isProjectOptions?: boolean,
): Promise<{
hasDeprecationWarnings: boolean;
options: AllOptions;
}> {
const {hasDeprecationWarnings} = validate(initialOptions, {
comment: DOCUMENTATION_NOTE,
deprecatedConfig: DEPRECATED_CONFIG,
exampleConfig: VALID_CONFIG,
exampleConfig: isProjectOptions ? VALID_PROJECT_CONFIG : VALID_CONFIG,
recursiveDenylist: [
// 'coverageThreshold' allows to use 'global' and glob strings on the same
// level, there's currently no way we can deal with such config
Expand Down

0 comments on commit f75a3aa

Please sign in to comment.