Skip to content

Commit 4a11230

Browse files
authored
Add concept of internal modules to jest-runtime. (#1322)
1 parent 58ab781 commit 4a11230

File tree

9 files changed

+127
-27
lines changed

9 files changed

+127
-27
lines changed

packages/jest-jasmine2/src/extendJasmineExpect.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
*/
88
'use strict';
99

10-
jest.deepUnmock('jest-matchers');
11-
1210
const jestExpect = require('jest-matchers').expect;
1311

1412
const jasmineExpect = global.expect;

packages/jest-jasmine2/src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ function jasmine2(
155155
'',
156156
'jest-check',
157157
() => {
158-
const jasmineCheck = runtime.requireModule(JASMINE_CHECK_PATH);
158+
const jasmineCheck = runtime.requireInternalModule(JASMINE_CHECK_PATH);
159159
return jasmineCheck(environment.global, config.testcheckOptions);
160160
},
161161
{virtual: true},
@@ -300,7 +300,9 @@ function jasmine2(
300300
// `jest-matchers` should be required inside test environment (vm).
301301
// Otherwise if they throw, the `Error` class will differ from the `Error`
302302
// class of the test and `error instanceof Error` will return `false`.
303-
runtime.requireModule(path.resolve(__dirname, './extendJasmineExpect.js'));
303+
runtime.requireInternalModule(
304+
path.resolve(__dirname, './extendJasmineExpect.js'),
305+
);
304306

305307
runtime.requireModule(testPath);
306308
env.execute();

packages/jest-jasmine2/src/jasmine-check.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
*/
88
'use strict';
99

10-
jest.unmock('jasmine-check');
11-
1210
const jasmineCheck = require('jasmine-check');
1311

1412
module.exports = (global, configOptions) => {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*
8+
* @emails oncall+jsinfra
9+
*/
10+
'use strict';
11+
12+
const path = require('path');
13+
14+
let createRuntime;
15+
16+
describe('Runtime', () => {
17+
beforeEach(() => {
18+
createRuntime = require('createRuntime');
19+
});
20+
21+
describe('internalModule', () => {
22+
it('loads modules and applies transforms', () =>
23+
createRuntime(__filename, {
24+
scriptPreprocessor: './test-preprocessor',
25+
}).then(runtime => {
26+
const modulePath = path.resolve(
27+
path.dirname(runtime.__mockRootPath),
28+
'internal-root.js',
29+
);
30+
expect(() => {
31+
runtime.requireModule(modulePath);
32+
}).toThrow(new Error('preprocessor must not run.'));
33+
}),
34+
);
35+
36+
it('loads internal modules without applying transforms', () =>
37+
createRuntime(__filename, {
38+
scriptPreprocessor: './test-preprocessor',
39+
}).then(runtime => {
40+
const modulePath = path.resolve(
41+
path.dirname(runtime.__mockRootPath),
42+
'internal-root.js',
43+
);
44+
const exports = runtime.requireInternalModule(modulePath);
45+
expect(exports()).toBe('internal-module-data');
46+
}),
47+
);
48+
});
49+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = () => 'internal-module-data';
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports = require('./internal-module');
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*/
8+
9+
'use strict';
10+
11+
module.exports.process = () => `throw new Error('preprocessor must not run.');`;

packages/jest-runtime/src/index.js

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ type HasteMapOptions = {
3838
resetCache: boolean,
3939
};
4040

41+
type InternalModuleOptions = {isInternalModule: boolean};
42+
4143
const NODE_MODULES = path.sep + 'node_modules' + path.sep;
4244
const SNAPSHOT_EXTENSION = 'snap';
4345

@@ -214,7 +216,11 @@ class Runtime {
214216
return require('./cli/args').options;
215217
}
216218

217-
requireModule(from: Path, moduleName?: string) {
219+
requireModule(
220+
from: Path,
221+
moduleName?: string,
222+
options: ?InternalModuleOptions,
223+
) {
218224
const moduleID = this._normalizeID(from, moduleName);
219225
let modulePath;
220226

@@ -225,6 +231,7 @@ class Runtime {
225231
moduleResource = moduleName && this._resolver.getModule(moduleName);
226232
manualMockResource = moduleName && this._resolver.getMockModule(moduleName);
227233
if (
234+
(!options || !options.isInternalModule) &&
228235
!moduleResource &&
229236
manualMockResource &&
230237
manualMockResource !== this._isCurrentlyExecutingManualMock &&
@@ -250,7 +257,6 @@ class Runtime {
250257
filename: modulePath,
251258
exports: {},
252259
};
253-
254260
this._moduleRegistry[modulePath] = localModule;
255261
if (path.extname(modulePath) === '.json') {
256262
localModule.exports = this._environment.global.JSON.parse(
@@ -260,12 +266,16 @@ class Runtime {
260266
// $FlowFixMe
261267
localModule.exports = require(modulePath);
262268
} else {
263-
this._execModule(localModule);
269+
this._execModule(localModule, options);
264270
}
265271
}
266272
return this._moduleRegistry[modulePath].exports;
267273
}
268274

275+
requireInternalModule(from: Path, to?: string) {
276+
return this.requireModule(from, to, {isInternalModule: true});
277+
}
278+
269279
requireMock(from: Path, moduleName: string) {
270280
const moduleID = this._normalizeID(from, moduleName);
271281

@@ -380,28 +390,30 @@ class Runtime {
380390
return to ? this._resolver.resolveModule(from, to) : from;
381391
}
382392

383-
_shouldCollectCoverage(filename: Path) {
393+
_shouldCollectCoverage(filename: Path): boolean {
384394
const collectOnlyFrom = this._config.collectCoverageOnlyFrom;
385395
const shouldCollectCoverage = (
386396
(this._config.collectCoverage && !collectOnlyFrom) ||
387397
(collectOnlyFrom && collectOnlyFrom[filename])
388398
);
389-
return (
399+
return !!(
390400
shouldCollectCoverage &&
391401
!this._coverageRegex.test(filename) &&
392402
!(this._mocksPattern && this._mocksPattern.test(filename)) &&
393403
!this._testRegex.test(filename)
394404
);
395405
}
396406

397-
_execModule(localModule: Module) {
407+
_execModule(localModule: Module, options: ?InternalModuleOptions) {
398408
// If the environment was disposed, prevent this module from being executed.
399409
if (!this._environment.global) {
400410
return;
401411
}
402412

403413
const filename = localModule.filename;
404-
const shouldCollectCoverage = this._shouldCollectCoverage(filename);
414+
const shouldCollectCoverage =
415+
(!options || !options.isInternalModule) &&
416+
this._shouldCollectCoverage(filename);
405417
const collectors = this._coverageCollectors;
406418
if (shouldCollectCoverage && !collectors[filename]) {
407419
collectors[filename] = new this._CoverageCollector();
@@ -418,17 +430,19 @@ class Runtime {
418430
localModule.children = [];
419431
localModule.parent = mockParentModule;
420432
localModule.paths = this._resolver.getModulePaths(dirname);
421-
localModule.require = this._createRequireImplementation(filename);
433+
localModule.require = this._createRequireImplementation(filename, options);
422434

423-
const script = transform(filename, this._config, {
424-
instrument: shouldCollectCoverage && (
425-
source => collectors[filename].getInstrumentedSource(
435+
const script = transform(
436+
filename,
437+
options && options.isInternalModule ? null : this._config,
438+
shouldCollectCoverage ? {
439+
instrument: source => collectors[filename].getInstrumentedSource(
426440
source,
427441
filename,
428442
'$JEST',
429-
)
430-
),
431-
});
443+
),
444+
} : null,
445+
);
432446
const wrapper = this._runScript(script, filename);
433447
wrapper.call(
434448
localModule.exports, // module context
@@ -645,13 +659,18 @@ class Runtime {
645659
return this._shouldMockModuleCache[moduleID] = true;
646660
}
647661

648-
_createRequireImplementation(from: Path) {
649-
const moduleRequire = this.requireModuleOrMock.bind(this, from);
650-
moduleRequire.requireMock = this.requireMock.bind(this, from);
651-
moduleRequire.requireActual = this.requireModule.bind(this, from);
652-
moduleRequire.resolve = moduleName => this._resolveModule(from, moduleName);
662+
_createRequireImplementation(
663+
from: Path,
664+
options: ?InternalModuleOptions,
665+
) {
666+
const moduleRequire = options && options.isInternalModule
667+
? (moduleName: string) => this.requireInternalModule(from, moduleName)
668+
: this.requireModuleOrMock.bind(this, from);
653669
moduleRequire.cache = Object.create(null);
654670
moduleRequire.extensions = Object.create(null);
671+
moduleRequire.requireActual = this.requireModule.bind(this, from);
672+
moduleRequire.requireMock = this.requireMock.bind(this, from);
673+
moduleRequire.resolve = moduleName => this._resolveModule(from, moduleName);
655674
return moduleRequire;
656675
}
657676

packages/jest-runtime/src/transform.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ const readCacheFile = (filePath: Path, cachePath: Path): ?string => {
112112

113113
module.exports = (
114114
filename: Path,
115-
config: Config,
115+
config: ?Config,
116116
options: ?TransformOptions,
117117
): vm.Script => {
118118
const mtime = fs.statSync(filename).mtime;
@@ -133,14 +133,15 @@ module.exports = (
133133
content = content.replace(/^#!.*/, '');
134134
}
135135

136-
if (!ignoreCache.has(config)) {
136+
if (config && !ignoreCache.has(config)) {
137137
ignoreCache.set(
138138
config,
139139
new RegExp(config.preprocessorIgnorePatterns.join('|')),
140140
);
141141
}
142142

143143
if (
144+
config &&
144145
config.scriptPreprocessor &&
145146
(
146147
!config.preprocessorIgnorePatterns.length ||

0 commit comments

Comments
 (0)