From 91fb94b5cea7f0754bc8ebed5aea9077656610a0 Mon Sep 17 00:00:00 2001 From: Christoph Pojer Date: Tue, 12 Jan 2016 15:33:00 -0800 Subject: [PATCH] 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 --- .../DependencyGraph/ResolutionRequest.js | 14 +++- .../__tests__/DependencyGraph-test.js | 84 +++++++++++++++++-- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js index 4414862f..50a59025 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js @@ -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); diff --git a/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js b/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js index 8f41d88c..b1126a4c 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js @@ -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: [], + }, ]); }); });