Skip to content

Commit

Permalink
Remove providesModuleNodeModules from Jest. (#9583)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpojer committed May 2, 2020
1 parent 73acd08 commit 2b32fe6
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 222 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@
- `[jest-validate]` [**BREAKING**] Use ESM exports ([#8874](https://github.com/facebook/jest/pull/8874))
- `[jest-types]` Mark `InitialOptions` as `Partial` ([#8848](https://github.com/facebook/jest/pull/8848))
- `[jest-config]` Refactor `normalize` to be more type safe ([#8848](https://github.com/facebook/jest/pull/8848))
- `[jest-haste-map]` [**BREAKING**] removed `providesModuleNodeModules` ([#8535](https://github.com/facebook/jest/pull/8535))

## 24.9.0

Expand Down
4 changes: 1 addition & 3 deletions TestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ const DEFAULT_PROJECT_CONFIG: Config.ProjectConfig = {
globalSetup: null,
globalTeardown: null,
globals: {},
haste: {
providesModuleNodeModules: [],
},
haste: {},
moduleDirectories: [],
moduleFileExtensions: ['js'],
moduleLoader: '/test_module_loader_path',
Expand Down
1 change: 0 additions & 1 deletion e2e/__tests__/__snapshots__/showConfig.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ exports[`--showConfig outputs config info and exits 1`] = `
"globals": {},
"haste": {
"computeSha1": false,
"providesModuleNodeModules": [],
"throwOnModuleCollision": false
},
"moduleDirectories": [
Expand Down
1 change: 0 additions & 1 deletion packages/jest-config/src/Defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const defaultOptions: Config.DefaultOptions = {
globals: {},
haste: {
computeSha1: false,
providesModuleNodeModules: [],
throwOnModuleCollision: false,
},
maxConcurrency: 5,
Expand Down
1 change: 0 additions & 1 deletion packages/jest-config/src/ValidConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const initialOptions: Config.InitialOptions = {
defaultPlatform: 'ios',
hasteImplModulePath: '<rootDir>/haste_impl.js',
platforms: ['ios', 'android'],
providesModuleNodeModules: ['react', 'react-native'],
throwOnModuleCollision: false,
},
json: false,
Expand Down
1 change: 0 additions & 1 deletion packages/jest-core/src/__tests__/SearchSource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ describe('SearchSource', () => {
'__tests__',
'haste_impl.js',
),
providesModuleNodeModules: [],
},
name: 'SearchSource-findRelatedTests-tests',
rootDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ exports[`prints the config object 1`] = `
"globalSetup": null,
"globalTeardown": null,
"globals": {},
"haste": {
"providesModuleNodeModules": []
},
"haste": {},
"moduleDirectories": [],
"moduleFileExtensions": [
"js"
Expand Down
30 changes: 0 additions & 30 deletions packages/jest-haste-map/src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ describe('HasteMap', () => {
const hasteMap = new HasteMap({
...defaultConfig,
mocksPattern: '/__mocks__/',
providesModuleNodeModules: ['react', 'fbjs'],
});

return hasteMap.build().then(({__hasteMapForTest: data}) => {
Expand All @@ -341,23 +340,6 @@ describe('HasteMap', () => {
'fruits/Pear.js': ['Pear', 32, 42, 1, 'Banana\0Strawberry', null],
'fruits/Strawberry.js': ['Strawberry', 32, 42, 1, '', null],
'fruits/__mocks__/Pear.js': ['', 32, 42, 1, 'Melon', null],
// node modules
'fruits/node_modules/fbjs/lib/flatMap.js': [
'flatMap',
32,
42,
1,
'',
null,
],
'fruits/node_modules/react/React.js': [
'React',
32,
42,
1,
'Component',
null,
],
'vegetables/Melon.js': ['Melon', 32, 42, 1, '', null],
}),
);
Expand All @@ -367,21 +349,9 @@ describe('HasteMap', () => {
Banana: {[H.GENERIC_PLATFORM]: ['fruits/Banana.js', H.MODULE]},
Melon: {[H.GENERIC_PLATFORM]: ['vegetables/Melon.js', H.MODULE]},
Pear: {[H.GENERIC_PLATFORM]: ['fruits/Pear.js', H.MODULE]},
React: {
[H.GENERIC_PLATFORM]: [
'fruits/node_modules/react/React.js',
H.MODULE,
],
},
Strawberry: {
[H.GENERIC_PLATFORM]: ['fruits/Strawberry.js', H.MODULE],
},
flatMap: {
[H.GENERIC_PLATFORM]: [
'fruits/node_modules/fbjs/lib/flatMap.js',
H.MODULE,
],
},
}),
);

Expand Down
51 changes: 2 additions & 49 deletions packages/jest-haste-map/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ type Options = {
mocksPattern?: string;
name: string;
platforms: Array<string>;
providesModuleNodeModules?: Array<string>;
resetCache?: boolean;
retainAllFiles: boolean;
rootDir: string;
Expand Down Expand Up @@ -127,28 +126,6 @@ const canUseWatchman = ((): boolean => {
return false;
})();

const escapePathSeparator = (string: string) =>
path.sep === '\\' ? string.replace(/(\/|\\)/g, '\\\\') : string;

const getWhiteList = (list: Array<string> | undefined): RegExp | null => {
if (list && list.length) {
const newList = list.map(item =>
escapePathSeparator(item.replace(/(\/)/g, path.sep)),
);
return new RegExp(
'(' +
escapePathSeparator(NODE_MODULES) +
'(?:' +
newList.join('|') +
')(?=$|' +
escapePathSeparator(path.sep) +
'))',
'g',
);
}
return null;
};

function invariant(condition: unknown, message?: string): asserts condition {
if (!condition) {
throw new Error(message);
Expand Down Expand Up @@ -241,7 +218,6 @@ class HasteMap extends EventEmitter {
private _console: Console;
private _options: InternalOptions;
private _watchers: Array<Watcher>;
private _whitelist: RegExp | null;
private _worker: WorkerInterface | null;

constructor(options: Options) {
Expand Down Expand Up @@ -315,7 +291,6 @@ class HasteMap extends EventEmitter {
hasteImplHash,
dependencyExtractorHash,
);
this._whitelist = getWhiteList(options.providesModuleNodeModules);
this._buildPromise = null;
this._watchers = [];
this._worker = null;
Expand Down Expand Up @@ -550,7 +525,7 @@ class HasteMap extends EventEmitter {

// If we retain all files in the virtual HasteFS representation, we avoid
// reading them if they aren't important (node_modules).
if (this._options.retainAllFiles && this._isNodeModulesDir(filePath)) {
if (this._options.retainAllFiles && filePath.includes(NODE_MODULES)) {
if (computeSha1) {
return this._getWorker(workerOptions)
.getSha1({
Expand Down Expand Up @@ -1075,32 +1050,10 @@ class HasteMap extends EventEmitter {

return (
ignoreMatched ||
(!this._options.retainAllFiles && this._isNodeModulesDir(filePath))
(!this._options.retainAllFiles && filePath.includes(NODE_MODULES))
);
}

private _isNodeModulesDir(filePath: Config.Path): boolean {
if (!filePath.includes(NODE_MODULES)) {
return false;
}

if (this._whitelist) {
const whitelist = this._whitelist;
const match = whitelist.exec(filePath);
const matchEndIndex = whitelist.lastIndex;
whitelist.lastIndex = 0;

if (!match) {
return true;
}

const filePathInPackage = filePath.substr(matchEndIndex);
return filePathInPackage.startsWith(NODE_MODULES);
}

return true;
}

private _createEmptyMap(): InternalHasteMap {
return {
clocks: new Map(),
Expand Down
16 changes: 0 additions & 16 deletions packages/jest-runtime/src/__tests__/runtime_require_module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,22 +252,6 @@ describe('Runtime requireModule', () => {
expect(hastePackage.isHastePackage).toBe(true);
}));

it('resolves node modules properly when crawling node_modules', () =>
// While we are crawling a node module, we shouldn't put package.json
// files of node modules to resolve to `package.json` but rather resolve
// to whatever the package.json's `main` field says.
createRuntime(__filename, {
haste: {
providesModuleNodeModules: ['not-a-haste-package'],
},
}).then(runtime => {
const hastePackage = runtime.requireModule(
runtime.__mockRootPath,
'not-a-haste-package',
);
expect(hastePackage.isNodeModule).toBe(true);
}));

it('resolves platform extensions based on the default platform', () =>
Promise.all([
createRuntime(__filename).then(runtime => {
Expand Down
1 change: 0 additions & 1 deletion packages/jest-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ class Runtime {
mocksPattern: escapePathForRegex(path.sep + '__mocks__' + path.sep),
name: config.name,
platforms: config.haste.platforms || ['ios', 'android'],
providesModuleNodeModules: config.haste.providesModuleNodeModules,
resetCache: options && options.resetCache,
retainAllFiles: false,
rootDir: config.rootDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ Object {
"globalSetup": null,
"globalTeardown": null,
"globals": Object {},
"haste": Object {
"providesModuleNodeModules": Array [],
},
"haste": Object {},
"moduleDirectories": Array [],
"moduleFileExtensions": Array [
"js",
Expand Down Expand Up @@ -229,7 +227,7 @@ exports[`ScriptTransformer uses multiple preprocessors 1`] = `
const TRANSFORMED = {
filename: '/fruits/banana.js',
script: 'module.exports = "banana";',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"filter":null,"forceCoverageMatch":[],"globalSetup":null,"globalTeardown":null,"globals":{},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotResolver":null,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"],["^.+\\\\.css$","css-preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"unmockedModulePathPatterns":null,"watchPathIgnorePatterns":[]}',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"filter":null,"forceCoverageMatch":[],"globalSetup":null,"globalTeardown":null,"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotResolver":null,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"],["^.+\\\\.css$","css-preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"unmockedModulePathPatterns":null,"watchPathIgnorePatterns":[]}',
};
`;

Expand All @@ -246,7 +244,7 @@ exports[`ScriptTransformer uses the supplied preprocessor 1`] = `
const TRANSFORMED = {
filename: '/fruits/banana.js',
script: 'module.exports = "banana";',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"filter":null,"forceCoverageMatch":[],"globalSetup":null,"globalTeardown":null,"globals":{},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotResolver":null,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"unmockedModulePathPatterns":null,"watchPathIgnorePatterns":[]}',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"filter":null,"forceCoverageMatch":[],"globalSetup":null,"globalTeardown":null,"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotResolver":null,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"unmockedModulePathPatterns":null,"watchPathIgnorePatterns":[]}',
};
`;
Expand Down
1 change: 0 additions & 1 deletion packages/jest-types/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export type HasteConfig = {
defaultPlatform?: string | null;
hasteImplModulePath?: string;
platforms?: Array<string>;
providesModuleNodeModules: Array<string>;
throwOnModuleCollision?: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,7 @@ exports[`pretty prints valid config for Object 1`] = `
<red></>
<red> Example:</>
<red> {</>
<red> <bold>\\"haste\\"</>: <bold>{</></>
<red><bold> \\"providesModuleNodeModules\\": [</></>
<red><bold> \\"react\\",</></>
<red><bold> \\"react-native\\"</></>
<red><bold> ]</></>
<red><bold> }</></>
<red> <bold>\\"haste\\"</>: <bold>{}</></>
<red> }</>
<red></>"
`;
Expand Down
8 changes: 2 additions & 6 deletions packages/jest-validate/src/__tests__/fixtures/jestConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ const defaultConfig = {
coverageReporters: ['json', 'text', 'lcov', 'clover'],
expand: false,
globals: {},
haste: {
providesModuleNodeModules: [],
},
haste: {},
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'node'],
moduleNameMapper: {},
Expand Down Expand Up @@ -82,9 +80,7 @@ const validConfig = {
expand: false,
forceExit: false,
globals: {},
haste: {
providesModuleNodeModules: ['react', 'react-native'],
},
haste: {},
logHeapUsage: true,
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'node'],
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-validate/src/__tests__/validate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ test('omits null and undefined config values', () => {

test('recursively omits null and undefined config values', () => {
const config = {
haste: {
providesModuleNodeModules: null,
coverageThreshold: {
global: null,
},
};
expect(
Expand Down
19 changes: 0 additions & 19 deletions website/versioned_docs/version-22.x/TutorialReactNative.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,22 +201,3 @@ jest.mock('Text', () => {
In other cases you may want to mock a native module that isn't a React component. The same technique can be applied. We recommend inspecting the native module's source code and logging the module when running a react native app on a real device and then modeling a manual mock after the real module.

If you end up mocking the same modules over and over it is recommended to define these mocks in a separate file and add it to the list of `setupFiles`.

### `@providesModule`

If you'd like to use Facebook's `@providesModule` module system through an npm package, the default haste config option must be overwritten and npm modules must be added to `providesModuleNodeModules`:

```json
"haste": {
"defaultPlatform": "ios",
"platforms": ["android", "ios"],
"providesModuleNodeModules": [
"react",
"react-native",
"my-awesome-module",
"my-text-component"
]
},
```

If you'd like to test a different default platform or if you are building for other platforms, the `defaultPlatform` and `platforms` configuration option can be updated.
Loading

0 comments on commit 2b32fe6

Please sign in to comment.