From 17c6ca348473c28b6da4a2bb44c2905f86303713 Mon Sep 17 00:00:00 2001 From: Jean Lauliac Date: Thu, 2 Mar 2017 08:33:02 -0800 Subject: [PATCH] packager: DependencyGraph-test: fix tests Reviewed By: davidaurelio Differential Revision: D4635348 fbshipit-source-id: 0130496e20d54f5ddf6546823b7a6cba3118917d --- .../src/node-haste/__mocks__/graceful-fs.js | 7 +- .../__tests__/DependencyGraph-test.js | 585 +++++++++--------- 2 files changed, 303 insertions(+), 289 deletions(-) diff --git a/packages/metro-bundler/src/node-haste/__mocks__/graceful-fs.js b/packages/metro-bundler/src/node-haste/__mocks__/graceful-fs.js index 638b6c8f..41ad4f1c 100644 --- a/packages/metro-bundler/src/node-haste/__mocks__/graceful-fs.js +++ b/packages/metro-bundler/src/node-haste/__mocks__/graceful-fs.js @@ -110,7 +110,7 @@ function makeStatResult(node) { function statSync(filepath) { const node = getToNode(filepath); - if (node.SYMLINK) { + if (node != null && node.SYMLINK) { return statSync(node.SYMLINK); } return makeStatResult(node); @@ -295,6 +295,11 @@ function getToNode(filepath) { node = getToNode(node.SYMLINK); } node = node[part]; + if (node == null) { + const err = new Error('ENOENT: no such file or directory'); + err.code = 'ENOENT'; + throw err; + } }); return node; diff --git a/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js b/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js index a3718625..5316d0ea 100644 --- a/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js +++ b/packages/metro-bundler/src/node-haste/__tests__/DependencyGraph-test.js @@ -27,13 +27,8 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; const path = require('path'); -const mockStat = { - isDirectory: () => false, -}; - beforeEach(() => { jest.resetModules(); - jest.mock('path', () => path); }); @@ -3111,74 +3106,70 @@ describe('DependencyGraph', function() { filesystem.root['index.js'] = filesystem.root['index.js'] .replace('require("dontWork")', '') .replace('require("wontWork")', ''); - triggerWatchEvent('change', root + '/index.js'); - return new Promise(resolve => { - dgraph.once('change', () => { - return resolve(getOrderedDependenciesAsJSON(dgraph, '/root/index.js') - .then(deps => { - expect(deps).toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: [ - 'shouldWork', - 'ember', - 'internalVendoredPackage', - 'anotherIndex', - ], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'shouldWork', - path: '/root/node_modules/react-haste/main.js', - dependencies: ['submodule'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'submodule/main.js', - path: '/root/node_modules/react-haste/node_modules/submodule/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'ember/main.js', - path: '/root/node_modules/ember/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'internalVendoredPackage', - path: '/root/vendored_modules/a-vendored-package/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'anotherIndex', - path: '/anotherRoot/index.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - ]); - })); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/index.js') + .then(() => getOrderedDependenciesAsJSON(dgraph, '/root/index.js')) + .then(deps => { + expect(deps).toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: [ + 'shouldWork', + 'ember', + 'internalVendoredPackage', + 'anotherIndex', + ], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'shouldWork', + path: '/root/node_modules/react-haste/main.js', + dependencies: ['submodule'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'submodule/main.js', + path: '/root/node_modules/react-haste/node_modules/submodule/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'ember/main.js', + path: '/root/node_modules/ember/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'internalVendoredPackage', + path: '/root/vendored_modules/a-vendored-package/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'anotherIndex', + path: '/anotherRoot/index.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + ]); }); }); }); @@ -4582,30 +4573,31 @@ describe('DependencyGraph', function() { return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function() { filesystem.root['index.js'] = filesystem.root['index.js'].replace('require("foo")', ''); - dgraph.processFileChange('change', root + '/index.js', mockStat); - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { - expect(deps) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'aPackage/main.js', - path: '/root/aPackage/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/index.js') + .then(() => getOrderedDependenciesAsJSON(dgraph, '/root/index.js')) + .then(function(deps) { + expect(deps) + .toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['aPackage'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'aPackage/main.js', + path: '/root/aPackage/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + ]); + }); }); }); @@ -4643,34 +4635,36 @@ describe('DependencyGraph', function() { return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function() { filesystem.root['index.js'] = filesystem.root['index.js'].replace('require("foo")', ''); - dgraph.processFileChange('change', root + '/index.js', mockStat); - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { - expect(deps) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'aPackage/main.js', - path: '/root/aPackage/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/index.js') + .then(() => getOrderedDependenciesAsJSON(dgraph, '/root/index.js')) + .then(function(deps) { + expect(deps) + .toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['aPackage'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'aPackage/main.js', + path: '/root/aPackage/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + ]); + }); }); }); it('updates module dependencies on file delete', function() { + expect.assertions(1); var root = '/root'; var filesystem = setMockFileSystem({ 'root': { @@ -4702,16 +4696,15 @@ describe('DependencyGraph', function() { roots: [root], }); return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function() { - delete filesystem.root.foo; - dgraph.processFileChange('delete', root + '/foo.js'); - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js') - .catch(error => { - expect(error.type).toEqual('UnableToResolveError'); - }); + delete filesystem.root['foo.js']; + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/foo.js') + .then(() => getOrderedDependenciesAsJSON(dgraph, '/root/index.js')) + .catch(error => expect(error.type).toEqual('UnableToResolveError')); }); }); it('updates module dependencies on file add', function() { + expect.assertions(1); var root = '/root'; var filesystem = setMockFileSystem({ 'root': { @@ -4749,54 +4742,53 @@ describe('DependencyGraph', function() { ' */', 'require("foo")', ].join('\n'); - dgraph.processFileChange('add', root + '/bar.js', mockStat); - + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/bar.js'); + }).then(() => { filesystem.root.aPackage['main.js'] = 'require("bar")'; - dgraph.processFileChange('change', root + '/aPackage/main.js', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { - expect(deps) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['aPackage', 'foo'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'aPackage/main.js', - path: '/root/aPackage/main.js', - dependencies: ['bar'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - }, - { - id: 'bar', - path: '/root/bar.js', - dependencies: ['foo'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - { - id: 'foo', - path: '/root/foo.js', - dependencies: ['aPackage'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/aPackage/main.js'); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps) { + expect(deps).toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['aPackage', 'foo'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'aPackage/main.js', + path: '/root/aPackage/main.js', + dependencies: ['bar'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { + id: 'bar', + path: '/root/bar.js', + dependencies: ['foo'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + { + id: 'foo', + path: '/root/foo.js', + dependencies: ['aPackage'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + ]); }); }); @@ -4829,9 +4821,10 @@ describe('DependencyGraph', function() { ).then(() => { filesystem.root['foo.png'] = ''; dgraph._hasteFS._files[root + '/foo.png'] = ['', 8648460, 1, []]; - dgraph.processFileChange('add', root + '/foo.png', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps2) { + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/foo.png'); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps2) { expect(deps2) .toEqual([ { @@ -4855,11 +4848,11 @@ describe('DependencyGraph', function() { resolveDependency: undefined, }, ]); - }); }); }); it('changes to browser field', function() { + expect.assertions(1); var root = '/root'; var filesystem = setMockFileSystem({ 'root': { @@ -4890,33 +4883,32 @@ describe('DependencyGraph', function() { main: 'main.js', browser: 'browser.js', }); - dgraph.processFileChange('change', root + '/aPackage/package.json', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { - expect(deps) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['aPackage'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - { - id: 'aPackage/browser.js', - path: '/root/aPackage/browser.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/aPackage/package.json'); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps) { + expect(deps).toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['aPackage'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + { + id: 'aPackage/browser.js', + path: '/root/aPackage/browser.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + ]); }); }); @@ -4956,37 +4948,40 @@ describe('DependencyGraph', function() { name: 'bPackage', main: 'main.js', }); - dgraph.processFileChange('change', root + '/index.js', mockStat); - dgraph.processFileChange('change', root + '/aPackage/package.json', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { - expect(deps) - .toEqual([ - { - dependencies: ['bPackage'], - id: 'index', - isAsset: false, - isJSON: false, - isPolyfill: false, - path: '/root/index.js', - resolution: undefined, - resolveDependency: undefined, - }, - { - dependencies: [], - id: 'aPackage/main.js', - isAsset: false, - isJSON: false, - isPolyfill: false, - path: '/root/aPackage/main.js', - resolution: undefined, - }, - ]); + return new Promise(resolve => { + dgraph.once('change', () => resolve()); + triggerWatchEvent('change', root + '/index.js'); + triggerWatchEvent('change', root + '/aPackage/package.json'); }); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps) { + expect(deps).toEqual([ + { + dependencies: ['bPackage'], + id: 'index', + isAsset: false, + isJSON: false, + isPolyfill: false, + path: '/root/index.js', + resolution: undefined, + resolveDependency: undefined, + }, + { + dependencies: [], + id: 'aPackage/main.js', + isAsset: false, + isJSON: false, + isPolyfill: false, + path: '/root/aPackage/main.js', + resolution: undefined, + }, + ]); }); }); it('should update node package changes', function() { + expect.assertions(2); var root = '/root'; var filesystem = setMockFileSystem({ 'root': { @@ -5057,37 +5052,37 @@ describe('DependencyGraph', function() { ]); filesystem.root.node_modules.foo['main.js'] = 'lol'; - dgraph.processFileChange('change', root + '/node_modules/foo/main.js', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps2) { - expect(deps2) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['foo'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - { - id: 'foo/main.js', - path: '/root/node_modules/foo/main.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent(dgraph, 'change', root + '/node_modules/foo/main.js'); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps2) { + expect(deps2).toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['foo'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + { + id: 'foo/main.js', + path: '/root/node_modules/foo/main.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + ]); }); }); it('should update node package main changes', function() { + expect.assertions(1); var root = '/root'; var filesystem = setMockFileSystem({ 'root': { @@ -5120,37 +5115,41 @@ describe('DependencyGraph', function() { main: 'main.js', browser: 'browser.js', }); - dgraph.processFileChange('change', root + '/node_modules/foo/package.json', mockStat); - - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps2) { - expect(deps2) - .toEqual([ - { - id: 'index', - path: '/root/index.js', - dependencies: ['foo'], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - { - id: 'foo/browser.js', - path: '/root/node_modules/foo/browser.js', - dependencies: [], - isAsset: false, - isJSON: false, - isPolyfill: false, - resolution: undefined, - resolveDependency: undefined, - }, - ]); - }); + return triggerAndProcessWatchEvent( + dgraph, + 'change', + root + '/node_modules/foo/package.json', + ); + }).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(function(deps2) { + expect(deps2).toEqual([ + { + id: 'index', + path: '/root/index.js', + dependencies: ['foo'], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + { + id: 'foo/browser.js', + path: '/root/node_modules/foo/browser.js', + dependencies: [], + isAsset: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + resolveDependency: undefined, + }, + ]); }); }); it('should not error when the watcher reports a known file as added', function() { + expect.assertions(1); var root = '/root'; setMockFileSystem({ 'root': { @@ -5174,9 +5173,12 @@ describe('DependencyGraph', function() { roots: [root], }); - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function() { - dgraph.processFileChange('add', root + '/index.js', mockStat); - return getOrderedDependenciesAsJSON(dgraph, '/root/index.js'); + return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then( + () => triggerAndProcessWatchEvent(dgraph, 'change', root + '/index.js'), + ).then( + () => getOrderedDependenciesAsJSON(dgraph, '/root/index.js'), + ).then(deps => { + expect(deps).toBeDefined(); }); }); }); @@ -5460,6 +5462,13 @@ describe('DependencyGraph', function() { return require('graceful-fs').__setMockFilesystem(object); } + function triggerAndProcessWatchEvent(dgraph, eventType, filename) { + return new Promise(resolve => { + dgraph.once('change', () => resolve()); + triggerWatchEvent(eventType, filename); + }); + } + function triggerWatchEvent(eventType, filename) { return require('graceful-fs').__triggerWatchEvent(eventType, filename); }