Skip to content

Commit

Permalink
Validate config with jest-validate package (jestjs#2524)
Browse files Browse the repository at this point in the history
* WIP validate.js

* Add validate.js to handle config validation

* Validate before normalizing

* Add deprecated config handling

* Fix lint errors

* Fix Runtime-NODE_PATH-test

* Fix linting on validate-test

* Adjust tests

* Move config validation to jest-validate package

* Update readme

* Make 'deprecated' configurable

* Fix normalize and add test for preset

* Move helper functions outside normalize()

* Further simplify normalize.js

* Add copyright to jest-validate types

* Make normalize() a little more declarative

* New Validation Errors for normalize

* Fix extra quotation mark

* Remove scripts from jest-validate's package.json

* Update snapshots

* Simplify condition

* chalk.white -> chalk.reset

* Sort config keys

* Simplify footer condition

* deprecatedWarning -> deprecationWarning

* use getType() from jest-matcher-utils instead of prettyPrintType()

* Adjust README

* Remove preset.preprocessorIgnorePatterns check

* Adjust jest-validate to be more generic

* Update yarn.lock

* Add missing 'testResultsProcessor' to validConfig

* Update types with testResultsProcessor

* Rename runtimeConfigError -> createConfigError

* Rename footer -> comment

* Rename validationError -> createValidationError

* Remove scripts form jest-config package.json

* Add defaultConfig and exampleConfig for self-validation check

* Furhter refine the API of jest-validate

* Adjust validate() usage in normalize.js

* Update README.md

* Update types.js
  • Loading branch information
thymikee authored and cpojer committed Jan 16, 2017
1 parent 07b4bf7 commit a30c9d7
Show file tree
Hide file tree
Showing 26 changed files with 1,423 additions and 365 deletions.
4 changes: 3 additions & 1 deletion packages/jest-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"jest-mock": "^18.0.0",
"jest-resolve": "^18.1.0",
"jest-util": "^18.1.0",
"json-stable-stringify": "^1.0.0"
"jest-validate": "^18.1.0",
"json-stable-stringify": "^1.0.0",
"pretty-format": "^18.1.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
exports[`Upgrade help logs a warning when \`scriptPreprocessor\` and/or \`preprocessorIgnorePatterns\` are used 1`] = `
"[33m[1m● [22mThe settings \`scriptPreprocessor\` and \`preprocessorIgnorePatterns\` were replaced by \`transform\` and \`transformIgnorePatterns\` which support multiple preprocessors.
"[33m[1m[1m●[1m Deprecation Warning[22m:
Jest now treats your current settings as:
Option [1mpreprocessorIgnorePatterns[22m was replaced by [1mtransformIgnorePatterns[22m, which support multiple preprocessors.
\"transform\": {\".*\": \"bar/baz\"}
\"transformIgnorePatterns\": \"bar/baz,qux/quux\"
Jest now treats your current configuration as:
{
\"transformIgnorePatterns\": [\"bar/baz\", \"qux/quux\"]
}
Please update your configuration.
Jest changed the default configuration for tests.
Configuration Documentation: https://facebook.github.io/jest/docs/configuration.html
Jest Issue Tracker: https://github.com/facebook/jest/issues
Configuration Documentation:
https://facebook.github.io/jest/docs/configuration.html
"
`;
exports[`transform throws for invalid value 1`] = `
"Configuration option \`transform\` must be an object. Use it like this:
 \"transform\": {
\"^.+\\\\.js$\": \"string\"
}
exports[`preset throws when preset not found 1`] = `
"● Validation Error:
Jest changed the default configuration for tests.
Preset [1mdoesnt-exist[22m not found.
[1mConfiguration Documentation:[22m https://facebook.github.io/jest/docs/configuration.html
[1mJest Issue Tracker:[22m https://github.com/facebook/jest/issues
[1mConfiguration Documentation:[22m
https://facebook.github.io/jest/docs/configuration.html
"
`;
exports[`transform throws for invalid value 2`] = `
"Configuration option \`transform\` must be an object. Use it like this:
exports[`rootDir throws if the config is missing a rootDir property 1`] = `
"● Validation Error:
Configuration option rootDir must be specified.
Configuration Documentation:
https://facebook.github.io/jest/docs/configuration.html
"
`;
 \"transform\": {
\"^.+\\\\.js$\": \"<rootDir>/node_modules/babel-jest\"
}
exports[`testEnvironment throws on invalid environment names 1`] = `
"● Validation Error:
Jest changed the default configuration for tests.
Test environment [1mphantom[22m cannot be found. Make sure the [1mtestEnvironment[22m configuration option points to an existing node module.
[1mConfiguration Documentation:[22m https://facebook.github.io/jest/docs/configuration.html
[1mJest Issue Tracker:[22m https://github.com/facebook/jest/issues
[1mConfiguration Documentation:[22m
https://facebook.github.io/jest/docs/configuration.html
"
`;
88 changes: 49 additions & 39 deletions packages/jest-config/src/__tests__/normalize-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,6 @@ beforeEach(() => {
expectedPathAbsAnother = path.join(root, 'another', 'abs', 'path');
});

it('errors when an invalid config option is passed in', () => {
const error = console.error;
console.error = jest.fn();
normalize({
rootDir: '/root/path/foo',
thisIsAnInvalidConfigKey: 'with a value even!',
});

expect(console.error).toBeCalledWith(
'Error: Unknown config option "thisIsAnInvalidConfigKey" with value ' +
'"with a value even!". This is either a typing error or a user ' +
'mistake and fixing it will remove this message.',
);

console.error = error;
});

it('picks a name based on the rootDir', () => {
const rootDir = '/root/path/foo';
const expected = crypto.createHash('md5')
Expand Down Expand Up @@ -88,7 +71,7 @@ describe('rootDir', () => {
it('throws if the config is missing a rootDir property', () => {
expect(() => {
normalize({});
}).toThrow(new Error(`Jest: 'rootDir' config value must be specified.`));
}).toThrowErrorMatchingSnapshot();
});
});

Expand Down Expand Up @@ -234,22 +217,6 @@ describe('transform', () => {
['abs-path', '/qux/quux'],
]);
});

it('throws for invalid value', () => {
expect(() => {
normalize({
rootDir: '/root/',
transform: 'string',
}, '/root/path');
}).toThrowErrorMatchingSnapshot();

expect(() => {
normalize({
rootDir: '/root/',
transform: ['string'],
}, '/root/path');
}).toThrowErrorMatchingSnapshot();
});
});

describe('setupTestFrameworkScriptFile', () => {
Expand Down Expand Up @@ -503,11 +470,7 @@ describe('testEnvironment', () => {
expect(() => normalize({
rootDir: '/root',
testEnvironment: 'phantom',
})).toThrow(new Error(
`Jest: test environment "phantom" cannot be found. Make sure the ` +
`"testEnvironment" configuration option points to an existing node ` +
`module.`,
));
})).toThrowErrorMatchingSnapshot();
});
});

Expand Down Expand Up @@ -607,3 +570,50 @@ describe('Upgrade help', () => {
expect(console.warn.mock.calls[0][0]).toMatchSnapshot();
});
});

describe('preset', () => {
jest.mock(
'/node_modules/react-native/jest-preset.json',
() => ({
moduleNameMapper: {b: 'b'},
modulePathIgnorePatterns: ['b'],
setupFiles: ['b'],
}),
{virtual: true}
);

test('throws when preset not found', () => {
expect(() => {
normalize({
preset: 'doesnt-exist',
rootDir: '/root/path/foo',
});
}).toThrowErrorMatchingSnapshot();
});

test('works with "react-native"', () => {
expect(() => {
normalize({
preset: 'react-native',
rootDir: '/root/path/foo',
});
}).not.toThrow();
});

test('merges with config', () => {
const config = normalize({
moduleNameMapper: {a: 'a'},
modulePathIgnorePatterns: ['a'],
preset: 'react-native',
rootDir: '/root/path/foo',
setupFiles: ['a'],
});
expect(config).toEqual(expect.objectContaining({
moduleNameMapper: expect.arrayContaining([['a', 'a'], ['b', 'b']]),
modulePathIgnorePatterns: expect.arrayContaining(['a', 'b']),
setupFiles: expect.arrayContaining(
['/node_modules/a', '/node_modules/b']
),
}));
});
});
40 changes: 40 additions & 0 deletions packages/jest-config/src/deprecated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/

'use strict';

const chalk = require('chalk');
const format = (value: string) => require('pretty-format')(value, {min: true});

/* eslint-disable max-len */
const deprecatedOptions = {
preprocessorIgnorePatterns: (config: Object) =>
` Option ${chalk.bold('preprocessorIgnorePatterns')} was replaced by ${chalk.bold('transformIgnorePatterns')}, which support multiple preprocessors.
Jest now treats your current configuration as:
{
${chalk.bold('"transformIgnorePatterns"')}: ${chalk.bold(`${format(config.preprocessorIgnorePatterns)}`)}
}
Please update your configuration.`,

scriptPreprocessor: (config: Object) =>
` Option ${chalk.bold('scriptPreprocessor')} was replaced by ${chalk.bold('transform')}, which support multiple preprocessors.
Jest now treats your current configuration as:
{
${chalk.bold('"transform"')}: ${chalk.bold(`{".*": ${format(config.scriptPreprocessor)}}`)}
}
Please update your configuration.`,
};
/* eslint-enable max-len */

module.exports = deprecatedOptions;
10 changes: 8 additions & 2 deletions packages/jest-config/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@

'use strict';

const path = require('path');
const loadFromFile = require('./loadFromFile');
const loadFromPackage = require('./loadFromPackage');
const normalize = require('./normalize');
const path = require('path');
const defaults = require('./defaults');
const validConfig = require('./validConfig');
const deprecatedConfig = require('./deprecated');
const setFromArgv = require('./setFromArgv');

const readConfig = (argv: any, packageRoot: string) =>
const readConfig = (argv: Object, packageRoot: string) =>
readRawConfig(argv, packageRoot)
.then(config => Object.freeze(setFromArgv(config, argv)));

Expand Down Expand Up @@ -48,6 +51,9 @@ const readRawConfig = (argv, root) => {
};

module.exports = {
defaults,
deprecatedConfig,
normalize,
readConfig,
validConfig,
};
Loading

0 comments on commit a30c9d7

Please sign in to comment.