Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
([#5154](https://github.com/facebook/jest/pull/5154))
* `[jest-jasmine2]` Support generator functions as specs.
([#5166](https://github.com/facebook/jest/pull/5166))
* `[jest-config]` Allow configuration objects inside `projects` array
([#5176](https://github.com/facebook/jest/pull/5176))

### Chore & Maintenance

Expand Down
25 changes: 25 additions & 0 deletions integration_tests/__tests__/multi_project_runner.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,31 @@ test('"No tests found" message for projects', () => {
);
});

test('objects in project configuration', () => {
writeFiles(DIR, {
'__tests__/file1.test.js': `
test('foo', () => {});
`,
'__tests__/file2.test.js': `
test('foo', () => {});
`,
'jest.config.js': `module.exports = {
projects: [
{ testMatch: ['<rootDir>/__tests__/file1.test.js$'] },
{ testMatch: ['<rootDir>/__tests__/file2.test.js$'] },
]
};`,
'package.json': '{}',
});

const {stdout, stderr} = runJest(DIR);
expect(stderr).toEqual('');
expect(stdout).toContain(
' 2 files checked across 2 projects. ' +
'Run with `--verbose` for more details.',
);
});

test('resolves projects and their <rootDir> properly', () => {
writeFiles(DIR, {
'.watchmanconfig': '',
Expand Down
10 changes: 8 additions & 2 deletions packages/jest-cli/src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ const ensureNoDuplicateConfigs = (parsedConfigs, projects) => {
});
throw new Error(message);
}
configPathSet.add(configPath);
if (configPath !== null) {
configPathSet.add(configPath);
}
}
};

Expand All @@ -225,9 +227,11 @@ const getConfigs = (
let hasDeprecationWarnings;
let configs: Array<ProjectConfig> = [];
let projects = projectsFromCLIArgs;
let configPath: ?Path;

if (projectsFromCLIArgs.length === 1) {
const parsedConfig = readConfig(argv, projects[0]);
configPath = parsedConfig.configPath;

if (parsedConfig.globalConfig.projects) {
// If this was a single project, and its config has `projects`
Expand All @@ -246,7 +250,9 @@ const getConfigs = (
}

if (projects.length > 1) {
const parsedConfigs = projects.map(root => readConfig(argv, root, true));
const parsedConfigs = projects.map(root =>
readConfig(argv, root, true, configPath),
);
ensureNoDuplicateConfigs(parsedConfigs, projects);
configs = parsedConfigs.map(({projectConfig}) => projectConfig);
if (!hasDeprecationWarnings) {
Expand Down
14 changes: 14 additions & 0 deletions packages/jest-config/src/__tests__/read_config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {readConfig} from '../index';

test('readConfig() throws when an object is passed without a file path', () => {
expect(() => {
readConfig(
null /* argv */,
{} /* packageRootOrConfig */,
false /* skipArgvConfigOption */,
null /* parentConfigPath */,
);
}).toThrowError(
'Jest: Cannot use configuration as an object without a file path',
);
});
46 changes: 29 additions & 17 deletions packages/jest-config/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,52 @@
*/

import type {Argv} from 'types/Argv';
import type {GlobalConfig, Path, ProjectConfig} from 'types/Config';
import type {
GlobalConfig,
InitialOptions,
Path,
ProjectConfig,
} from 'types/Config';

import {getTestEnvironment, isJSONString} from './utils';
import path from 'path';
import {isJSONString} from './utils';
import normalize from './normalize';
import resolveConfigPath from './resolve_config_path';
import readConfigFileAndSetRootDir from './read_config_file_and_set_root_dir';

function readConfig(
export {getTestEnvironment, isJSONString} from './utils';
export {default as normalize} from './normalize';

export function readConfig(
argv: Argv,
packageRoot: string,
packageRootOrConfig: Path | InitialOptions,
// Whether it needs to look into `--config` arg passed to CLI.
// It only used to read initial config. If the initial config contains
// `project` property, we don't want to read `--config` value and rather
// read individual configs for every project.
skipArgvConfigOption?: boolean,
parentConfigPath: ?Path,
): {
configPath: ?Path,
globalConfig: GlobalConfig,
hasDeprecationWarnings: boolean,
projectConfig: ProjectConfig,
} {
let rawOptions;
let configPath;
let configPath = null;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anywhere that requires a configPath to be set other than readConfigFileAndSetRootDir?


// A JSON string was passed to `--config` argument and we can parse it
// and use as is.
if (isJSONString(argv.config)) {
if (typeof packageRootOrConfig !== 'string') {
if (parentConfigPath) {
rawOptions = packageRootOrConfig;
rawOptions.rootDir = path.dirname(parentConfigPath);
} else {
throw new Error(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a test for this (mostly for coverage)?

'Jest: Cannot use configuration as an object without a file path.',
);
}
} else if (isJSONString(argv.config)) {
// A JSON string was passed to `--config` argument and we can parse it
// and use as is.
let config;
try {
config = JSON.parse(argv.config);
Expand All @@ -45,7 +64,7 @@ function readConfig(
}

// NOTE: we might need to resolve this dir to an absolute path in the future
config.rootDir = config.rootDir || packageRoot;
config.rootDir = config.rootDir || packageRootOrConfig;
rawOptions = config;
// A string passed to `--config`, which is either a direct path to the config
// or a path to directory containing `package.json` or `jest.conf.js`
Expand All @@ -54,7 +73,7 @@ function readConfig(
rawOptions = readConfigFileAndSetRootDir(configPath);
} else {
// Otherwise just try to find config in the current rootDir.
configPath = resolveConfigPath(packageRoot, process.cwd());
configPath = resolveConfigPath(packageRootOrConfig, process.cwd());
rawOptions = readConfigFileAndSetRootDir(configPath);
}

Expand Down Expand Up @@ -166,10 +185,3 @@ const getConfigs = (
}),
};
};

module.exports = {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this on purpose?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is, you export instead. Cool! 🙂

getTestEnvironment,
isJSONString,
normalize,
readConfig,
};
3 changes: 2 additions & 1 deletion packages/jest-config/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ export default function normalize(options: InitialOptions, argv: Argv) {
// Project can be specified as globs. If a glob matches any files,
// We expand it to these paths. If not, we keep the original path
// for the future resolution.
const globMatches = glob.sync(project);
const globMatches =
typeof project === 'string' ? glob.sync(project) : [];
return projects.concat(globMatches.length ? globMatches : project);
}, []);
break;
Expand Down