-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Support array of paths for moduleNameMapper
aliases
#9465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
60f69e7
d4fd74f
0a625c3
37ee6d7
a51a4bf
b21ebe3
f85ab41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,6 @@ | |
'use strict'; | ||
|
||
require('./style.css'); | ||
require('./style.sass'); | ||
|
||
module.exports = () => 'test'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
{ | ||
"jest": { | ||
"moduleNameMapper": { | ||
"\\.(css|less)$": "./__mocks__/styleMock.js" | ||
"\\.(css|less)$": "./__mocks__/styleMock.js", | ||
"\\.(sass)$": ["./__mocks__/nonExistentMock.js", "./__mocks__/styleMock.js"] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const importedFn = require('../'); | ||
|
||
test('moduleNameMapping wrong configuration', () => { | ||
expect(importedFn).toBeDefined(); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
require('./style.css'); | ||
|
||
module.exports = () => 'test'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"jest": { | ||
"moduleNameMapper": { | ||
"\\.(css|less)$": ["no-such-module", "no-such-module-2"] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -377,28 +377,42 @@ class Resolver { | |
// Note: once a moduleNameMapper matches the name, it must result | ||
// in a module, or else an error is thrown. | ||
const matches = moduleName.match(regex); | ||
const updatedName = matches | ||
? mappedModuleName.replace( | ||
/\$([0-9]+)/g, | ||
(_, index) => matches[parseInt(index, 10)], | ||
) | ||
: mappedModuleName; | ||
|
||
const module = | ||
this.getModule(updatedName) || | ||
Resolver.findNodeModule(updatedName, { | ||
basedir: dirname, | ||
browser: this._options.browser, | ||
extensions, | ||
moduleDirectory, | ||
paths, | ||
resolver, | ||
rootDir: this._options.rootDir, | ||
}); | ||
const mapModuleName = matches | ||
? (moduleName: string) => | ||
moduleName.replace( | ||
/\$([0-9]+)/g, | ||
(_, index) => matches[parseInt(index, 10)], | ||
) | ||
: (moduleName: string) => moduleName; | ||
|
||
const possibleModuleNames = Array.isArray(mappedModuleName) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make it into an array in Thinking about it, that might be a breaking change... Hmm There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When an error happens we need to properly format error message based on whether it was set as an array or string in configuration. If we normalize it, we will probably lose that information and not be able to properly format error message There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't be too bad to show There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could normalize to an array in the constructor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SimenB Not sure I understood that. Is there anything for me to do apart from updating docs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jeysal Aren't resolved module paths cached? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this._possibleModuleNames = Array.isArray(mappedModuleName) ? mappedModuleName : [mappedModuleName]; in the constructor of this class There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SimenB The problem is we need both the original config entry for the error message and the array one to iterate over here. As long as we don't want to compromise on the correctness of the error message I think this is as good as it gets 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Even with caching often running a single test will need to resolve a large dependency tree, just want to be on the safe side as far as perf goes 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the error message can be passed the original config, but in the happy case it won't have to check if array or not |
||
? mappedModuleName | ||
: [mappedModuleName]; | ||
let module: string | null = null; | ||
for (const possibleModuleName of possibleModuleNames) { | ||
const updatedName = mapModuleName(possibleModuleName); | ||
|
||
module = | ||
this.getModule(updatedName) || | ||
Resolver.findNodeModule(updatedName, { | ||
basedir: dirname, | ||
browser: this._options.browser, | ||
extensions, | ||
moduleDirectory, | ||
paths, | ||
resolver, | ||
rootDir: this._options.rootDir, | ||
}); | ||
|
||
if (module) { | ||
break; | ||
} | ||
} | ||
|
||
if (!module) { | ||
throw createNoMappedModuleFoundError( | ||
moduleName, | ||
updatedName, | ||
mapModuleName, | ||
mappedModuleName, | ||
regex, | ||
resolver, | ||
|
@@ -414,21 +428,29 @@ class Resolver { | |
|
||
const createNoMappedModuleFoundError = ( | ||
moduleName: string, | ||
updatedName: string, | ||
mappedModuleName: string, | ||
mapModuleName: (moduleName: string) => string, | ||
mappedModuleName: string | Array<string>, | ||
regex: RegExp, | ||
resolver?: Function | string | null, | ||
) => { | ||
const mappedAs = Array.isArray(mappedModuleName) | ||
? JSON.stringify(mappedModuleName.map(mapModuleName), null, 2) | ||
: mappedModuleName; | ||
const original = Array.isArray(mappedModuleName) | ||
? JSON.stringify(mappedModuleName, null, 6) // using 6 because of misalignment when nested below | ||
.slice(0, -1) + ' ]' /// align last bracket correctly as well | ||
: mappedModuleName; | ||
|
||
const error = new Error( | ||
chalk.red(`${chalk.bold('Configuration error')}: | ||
|
||
Could not locate module ${chalk.bold(moduleName)} mapped as: | ||
${chalk.bold(updatedName)}. | ||
${chalk.bold(mappedAs)}. | ||
|
||
Please check your configuration for these entries: | ||
{ | ||
"moduleNameMapper": { | ||
"${regex.toString()}": "${chalk.bold(mappedModuleName)}" | ||
"${regex.toString()}": "${chalk.bold(original)}" | ||
}, | ||
"resolver": ${chalk.bold(String(resolver))} | ||
}`), | ||
|
Uh oh!
There was an error while loading. Please reload this page.