From 570af86ed16642310085e6e31b4fd4c702f9dab0 Mon Sep 17 00:00:00 2001 From: Tim Seckinger Date: Wed, 26 Dec 2018 14:28:04 +0100 Subject: [PATCH] add DependencyResolver.resolveRecursive() --- CHANGELOG.md | 1 + .../src/__tests__/__fixtures__/circular/a.js | 10 ++++++ .../src/__tests__/__fixtures__/circular/b.js | 10 ++++++ .../src/__tests__/__fixtures__/circular/c.js | 10 ++++++ .../src/__tests__/__fixtures__/recursive/a.js | 10 ++++++ .../src/__tests__/__fixtures__/recursive/b.js | 11 ++++++ .../__tests__/__fixtures__/recursive/c1.js | 8 +++++ .../__tests__/__fixtures__/recursive/c2.js | 8 +++++ .../src/__tests__/dependency_resolver.test.js | 34 +++++++++++++++++-- .../jest-resolve-dependencies/src/index.js | 21 ++++++++++-- 10 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/a.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/b.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/c.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/a.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/b.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c1.js create mode 100644 packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c2.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 66062e923d47..08bd7515cc5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - `[jest-haste-map]` [**BREAKING**] Remove name from hash in `HasteMap.getCacheFilePath` ([#7218](https://github.com/facebook/jest/pull/7218)) - `[babel-preset-jest]` [**BREAKING**] Export a function instead of an object for Babel 7 compatibility ([#7203](https://github.com/facebook/jest/pull/7203)) - `[jest-haste-map]` [**BREAKING**] Expose relative paths when getting the file iterator ([#7321](https://github.com/facebook/jest/pull/7321)) +- `[jest-resolve-dependencies]` Add `DependencyResolver.resolveRecursive` ([#7553](https://github.com/facebook/jest/pull/7553)) - `[jest-cli]` Add Support for `globalSetup` and `globalTeardown` in projects ([#6865](https://github.com/facebook/jest/pull/6865)) - `[jest-runtime]` Add `extraGlobals` to config to load extra global variables into the execution vm ([#7454](https://github.com/facebook/jest/pull/7454)) - `[jest-util]` Export `specialChars` containing Unicode characters and ANSI escapes for console output ([#7532](https://github.com/facebook/jest/pull/7532)) diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/a.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/a.js new file mode 100644 index 000000000000..4e8641565ea4 --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/a.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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('./b'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/b.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/b.js new file mode 100644 index 000000000000..b4d81046bace --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/b.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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('./c'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/c.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/c.js new file mode 100644 index 000000000000..700760b038bd --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/circular/c.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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('./a'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/a.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/a.js new file mode 100644 index 000000000000..4e8641565ea4 --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/a.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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('./b'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/b.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/b.js new file mode 100644 index 000000000000..d76ebffcbdcf --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/b.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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('./c1'); +require('./c2'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c1.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c1.js new file mode 100644 index 000000000000..dfdad4c91d22 --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c1.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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'; diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c2.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c2.js new file mode 100644 index 000000000000..dfdad4c91d22 --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/recursive/c2.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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'; diff --git a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.js b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.js index eaf5b0ac5718..3033e3146adf 100644 --- a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.js +++ b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.js @@ -42,7 +42,7 @@ beforeEach(() => { describe('resolve', () => { test('resolves no dependencies for non-existent path', () => { const resolved = dependencyResolver.resolve('/non/existent/path'); - expect(resolved.length).toEqual(0); + expect(resolved).toHaveLength(0); }); test('resolves dependencies for existing path', () => { @@ -65,17 +65,45 @@ describe('resolve', () => { }); }); +describe('resolveRecursive', () => { + test('resolves no dependencies for non-existent path', () => { + const resolved = dependencyResolver.resolveRecursive('/non/existent/path'); + expect(Array.from(resolved)).toHaveLength(0); + }); + + test('resolves dependencies for existing path', () => { + const resolved = dependencyResolver.resolveRecursive( + path.resolve(__dirname, '__fixtures__', 'recursive', 'a.js'), + ); + expect(Array.from(resolved)).toEqual([ + expect.stringContaining('/b.js'), + expect.stringContaining('/c1.js'), + expect.stringContaining('/c2.js'), + ]); + }); + + test('resolves circular dependencies', () => { + const resolved = dependencyResolver.resolveRecursive( + path.resolve(__dirname, '__fixtures__', 'circular', 'a.js'), + ); + expect(Array.from(resolved)).toEqual([ + expect.stringContaining('/b.js'), + expect.stringContaining('/c.js'), + ]); + }); +}); + describe('resolveInverse', () => { test('resolves no inverse dependencies for empty paths set', () => { const paths = new Set(); const resolved = dependencyResolver.resolveInverse(paths, filter); - expect(resolved.length).toEqual(0); + expect(resolved).toHaveLength(0); }); test('resolves no inverse dependencies for set of non-existent paths', () => { const paths = new Set(['/non/existent/path', '/another/one']); const resolved = dependencyResolver.resolveInverse(paths, filter); - expect(resolved.length).toEqual(0); + expect(resolved).toHaveLength(0); }); test('resolves inverse dependencies for existing path', () => { diff --git a/packages/jest-resolve-dependencies/src/index.js b/packages/jest-resolve-dependencies/src/index.js index 5667958346ee..5e7a05d5afc5 100644 --- a/packages/jest-resolve-dependencies/src/index.js +++ b/packages/jest-resolve-dependencies/src/index.js @@ -14,8 +14,10 @@ import type {SnapshotResolver} from 'types/SnapshotResolver'; import {isSnapshotPath} from 'jest-snapshot'; /** - * DependencyResolver is used to resolve the direct dependencies of a module or - * to retrieve a list of all transitive inverse dependencies. + * DependencyResolver is used + * to resolve the direct dependencies of a module (resolve) or + * to resolve the transitive (direct and indirect) dependencies of a module (resolveRecursive) or + * to retrieve a list of all transitive inverse dependencies (resolveInverse). */ export default class DependencyResolver { _hasteFS: HasteFS; @@ -61,6 +63,21 @@ export default class DependencyResolver { }, []); } + resolveRecursive(rootFile: Path, options?: ResolveModuleConfig): Set { + const known = new Set(); + const recurse = (file: Path) => { + if (known.has(file)) { + return; + } + if (file !== rootFile) { + known.add(file); + } + this.resolve(file, options).forEach(recurse); + }; + recurse(rootFile); + return known; + } + resolveInverse( paths: Set, filter: (file: Path) => boolean,