Support "free" mocks.

Summary:
It's possible that a mock doesn't have an associated real module that it maps to. This is actually very common in www, where we have JS mocks for dynamic PHP JS modules. The implementation I chose seems like the smartest one for now: if a module cannot be resolved, we look up whether we have a mock with the same id. If we do, we just resolve it. That's it! And it also only does the minimum amount of resolution necessary.

public

Reviewed By: martinbigio

Differential Revision: D2822277

fb-gh-sync-id: 7c9fbb6f69a0c0c85157c0650f5719d94a02410e
This commit is contained in:
Christoph Pojer 2016-01-12 15:33:00 -08:00 committed by facebook-github-bot-1
parent e35b8f1724
commit 91fb94b5ce
2 changed files with 88 additions and 10 deletions

View File

@ -135,15 +135,25 @@ class ResolutionRequest {
const filteredPairs = [];
dependencies.forEach((modDep, i) => {
const name = depNames[i];
if (modDep == null) {
// It is possible to require mocks that don't have a real
// module backing them. If a dependency cannot be found but there
// exists a mock with the desired ID, resolve it and add it as
// a dependency.
if (mocks && mocks[name]) {
const mockModule = this._moduleCache.getModule(mocks[name]);
return filteredPairs.push([name, mockModule]);
}
debug(
'WARNING: Cannot find required module `%s` from module `%s`',
depNames[i],
name,
mod.path
);
return false;
}
return filteredPairs.push([depNames[i], modDep]);
return filteredPairs.push([name, modDep]);
});
response.setResolvedDependencyPairs(mod, filteredPairs);

View File

@ -10,13 +10,13 @@
jest.autoMockOff();
jest.mock('fs');
const Promise = require('promise');
const DependencyGraph = require('../index');
const fs = require('graceful-fs');
jest
.mock('fs');
var DependencyGraph = require('../index');
var fs = require('graceful-fs');
const mocksPattern = /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/;
describe('DependencyGraph', function() {
let defaults;
@ -4024,7 +4024,7 @@ describe('DependencyGraph', function() {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'__mocks': {
'__mocks__': {
'A.js': '',
},
'index.js': '',
@ -4061,7 +4061,7 @@ describe('DependencyGraph', function() {
var dgraph = new DependencyGraph({
...defaults,
roots: [root],
mocksPattern: /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/,
mocksPattern,
});
return dgraph.getDependencies('/root/b.js')
@ -4101,7 +4101,7 @@ describe('DependencyGraph', function() {
var dgraph = new DependencyGraph({
...defaults,
roots: [root],
mocksPattern: /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/,
mocksPattern,
});
return getOrderedDependenciesAsJSON(dgraph, '/root/A.js')
@ -4134,6 +4134,74 @@ describe('DependencyGraph', function() {
id: '/root/__mocks__/A.js',
dependencies: ['b'],
},
{
path: '/root/__mocks__/b.js',
isJSON: false,
isAsset: false,
isAsset_DEPRECATED: false,
isPolyfill: false,
id: '/root/__mocks__/b.js',
dependencies: [],
},
]);
});
});
pit('resolves mocks that do not have a real module associated with them', () => {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'__mocks__': {
'foo.js': [
'require("b");',
].join('\n'),
'b.js': '',
},
'A.js': [
'/**',
' * @providesModule A',
' */',
'require("foo");',
].join('\n'),
},
});
var dgraph = new DependencyGraph({
...defaults,
roots: [root],
mocksPattern,
});
return getOrderedDependenciesAsJSON(dgraph, '/root/A.js')
.then(deps => {
expect(deps).toEqual([
{
path: '/root/A.js',
isJSON: false,
isAsset: false,
isAsset_DEPRECATED: false,
isPolyfill: false,
id: 'A',
dependencies: ['foo'],
},
{
path: '/root/__mocks__/foo.js',
isJSON: false,
isAsset: false,
isAsset_DEPRECATED: false,
isPolyfill: false,
id: '/root/__mocks__/foo.js',
dependencies: ['b'],
},
{
path: '/root/__mocks__/b.js',
isJSON: false,
isAsset: false,
isAsset_DEPRECATED: false,
isPolyfill: false,
id: '/root/__mocks__/b.js',
dependencies: [],
},
]);
});
});