Skip to content

Commit

Permalink
Add option to map module names to stub modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpojer committed Oct 7, 2015
1 parent 05a0c3d commit bc4e4a1
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 6 deletions.
45 changes: 41 additions & 4 deletions src/HasteModuleLoader/HasteModuleLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ var NODE_CORE_MODULES = {

var VENDOR_PATH = path.resolve(__dirname, '../../vendor');

const hasOwnProperty = Object.prototype.hasOwnProperty;

var _configUnmockListRegExpCache = null;

function _buildLoadersList(config) {
Expand Down Expand Up @@ -152,6 +154,15 @@ function Loader(config, environment, resourceMap) {
}
}

// Workers communicate the config as JSON so we have to create a regex object
// in the module loader instance.
this._mappedModuleNames = Object.create(null);
if (this._config.moduleNameMapper.length) {
this._config.moduleNameMapper.forEach(
map => this._mappedModuleNames[map[1]] = new RegExp(map[0])
);
}

this.resetModuleRegistry();
}

Expand Down Expand Up @@ -321,6 +332,16 @@ Loader.prototype._getResource = function(resourceType, resourceName) {
);
}

if (
resource === undefined &&
resourceType === 'JSMock'
) {
var moduleName = this._resolveStubModuleName(resourceName);
if (moduleName) {
resource = this._resourceMap.getResource('JS', moduleName);
}
}

return resource;
};

Expand Down Expand Up @@ -556,17 +577,16 @@ Loader.prototype._nodeModuleNameToPath = function(currPath, moduleName) {
*/
Loader.prototype._shouldMock = function(currPath, moduleName) {
var moduleID = this._getNormalizedModuleID(currPath, moduleName);
if (this._builtInModules.hasOwnProperty(moduleName)) {
if (hasOwnProperty.call(this._builtInModules, moduleName)) {
return false;
} else if (this._explicitShouldMock.hasOwnProperty(moduleID)) {
} else if (hasOwnProperty.call(this._explicitShouldMock, moduleID)) {
return this._explicitShouldMock[moduleID];
} else if (NODE_CORE_MODULES[moduleName]) {
return false;
} else if (this._shouldAutoMock) {

// See if the module is specified in the config as a module that should
// never be mocked
if (this._configShouldMockModuleNames.hasOwnProperty(moduleName)) {
if (hasOwnProperty.call(this._configShouldMockModuleNames, moduleName)) {
return this._configShouldMockModuleNames[moduleName];
} else if (this._unmockListRegExps.length > 0) {
this._configShouldMockModuleNames[moduleName] = true;
Expand Down Expand Up @@ -906,6 +926,23 @@ Loader.prototype.requireModule = function(currPath, moduleName,
return moduleObj.exports;
};

/**
* If the moduleNameMapper config is set, go through all the mappings
* and resolve the module name.
*
* @param string moduleName
* @param string the resolved module name
*/
Loader.prototype._resolveStubModuleName = function(moduleName) {
var nameMapper = this._mappedModuleNames;
for (let mappedModuleName in nameMapper) {
var regex = nameMapper[mappedModuleName];
if (regex.test(moduleName)) {
return mappedModuleName;
}
}
};

/**
* Given a module name, return either the real module or the mock version of
* that module -- depending on the mocking state of the loader (and, perhaps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ describe('nodeHasteModuleLoader', function() {
var mockEnvironment;
var resources;
var mockConfig = {
coverageCollector: '../IstanbulCollector'
coverageCollector: '../IstanbulCollector',
moduleNameMapper: [],
};

var mockResourceMap = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ describe('HasteModuleLoader', function() {

var CONFIG = utils.normalizeConfig({
name: 'HasteModuleLoader-tests',
rootDir: path.resolve(__dirname, 'test_root')
rootDir: path.resolve(__dirname, 'test_root'),
moduleNameMapper: {
'^image![a-zA-Z0-9$_-]+$': 'GlobalImageStub',
'^[./a-zA-Z0-9$_-]+\.png$': 'RelativeImageStub',
},
});

function buildLoader() {
Expand Down Expand Up @@ -92,5 +96,20 @@ describe('HasteModuleLoader', function() {
expect(exports.isManualMockModule).toBe(false);
});
});

pit('resolves mapped module names and unmocks them by default', function() {
return buildLoader().then(function(loader) {
loader.requireModuleOrMock(__filename, 'jest-runtime');
var exports =
loader.requireModuleOrMock(__filename, 'image!not-really-a-module');
expect(exports.isGlobalImageStub).toBe(true);

exports = loader.requireModuleOrMock(__filename, 'cat.png');
expect(exports.isRelativeImageStub).toBe(true);

exports = loader.requireModuleOrMock(__filename, 'dog.png');
expect(exports.isRelativeImageStub).toBe(true);
});
});
});
});
13 changes: 13 additions & 0 deletions src/HasteModuleLoader/__tests__/test_root/GlobalImageStub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2014, 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.
*
* @providesModule GlobalImageStub
*/

'use strict';

exports.isGlobalImageStub = true;
13 changes: 13 additions & 0 deletions src/HasteModuleLoader/__tests__/test_root/RelativeImageStub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2014, 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.
*
* @providesModule RelativeImageStub
*/

'use strict';

exports.isRelativeImageStub = true;
8 changes: 8 additions & 0 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var DEFAULT_CONFIG_VALUES = {
moduleLoader: require.resolve('../HasteModuleLoader/HasteModuleLoader'),
preprocessorIgnorePatterns: [],
modulePathIgnorePatterns: [],
moduleNameMapper: [],
testDirectoryName: '__tests__',
testEnvironment: require.resolve('../JSDomEnvironment'),
testEnvData: {},
Expand Down Expand Up @@ -207,6 +208,13 @@ function normalizeConfig(config) {
));
break;

case 'moduleNameMapper':
value = Object.keys(config[key]).map(regex => [
regex,
_replaceRootDirTags(config.rootDir, config[key][regex])
]);
break;

case 'preprocessorIgnorePatterns':
case 'testPathIgnorePatterns':
case 'modulePathIgnorePatterns':
Expand Down

0 comments on commit bc4e4a1

Please sign in to comment.