diff --git a/CHANGELOG.md b/CHANGELOG.md index 46792cc676dc..7ac88e9f12f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - `[jest-leak-detector]` [**BREAKING**] Use `weak-napi` instead of `weak` package ([#8686](https://github.com/facebook/jest/pull/8686)) - `[jest-mock]` Fix for mockReturnValue overriding mockImplementationOnce ([#8398](https://github.com/facebook/jest/pull/8398)) - `[jest-reporters]` Make node-notifer an optional dependency ([#8918](https://github.com/facebook/jest/pull/8918)) +- `[jest-resolve-dependencies]` Resolve mocks as dependencies ([#8952](https://github.com/facebook/jest/pull/8952)) - `[jest-snapshot]` Remove only the added newlines in multiline snapshots ([#8859](https://github.com/facebook/jest/pull/8859)) - `[jest-snapshot]` Distinguish empty string from external snapshot not written ([#8880](https://github.com/facebook/jest/pull/8880)) - `[jest-snapshot]` [**BREAKING**] Distinguish empty string from internal snapshot not written ([#8898](https://github.com/facebook/jest/pull/8898)) diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/__mocks__/file.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/__mocks__/file.js new file mode 100644 index 000000000000..b64851b9b271 --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/__mocks__/file.js @@ -0,0 +1,9 @@ +/** + * 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. + * + */ + +module.exports = jest.fn(); diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.js new file mode 100644 index 000000000000..f7294048510d --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.js @@ -0,0 +1,9 @@ +/** + * 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. + * + */ + +module.exports = str => str; diff --git a/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.test.js b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.test.js new file mode 100644 index 000000000000..c6e4163ee57f --- /dev/null +++ b/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/hasMocked/file.test.js @@ -0,0 +1,9 @@ +/** + * 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. + * + */ + +require('./file'); diff --git a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts index 7efd09980a9e..f0b2dc019794 100644 --- a/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts +++ b/packages/jest-resolve-dependencies/src/__tests__/dependency_resolver.test.ts @@ -58,6 +58,17 @@ test('resolves dependencies for existing path', () => { ]); }); +test('includes the mocks of dependencies as dependencies', () => { + const resolved = dependencyResolver.resolve( + path.resolve(__dirname, '__fixtures__/hasMocked/file.test.js'), + ); + + expect(resolved).toEqual([ + expect.stringContaining(path.join('hasMocked', 'file.js')), + expect.stringContaining(path.join('hasMocked', '__mocks__', 'file.js')), + ]); +}); + test('resolves dependencies for scoped packages', () => { const resolved = dependencyResolver.resolve( path.resolve(__dirname, '__fixtures__', 'scoped.js'), @@ -89,6 +100,19 @@ test('resolves inverse dependencies for existing path', () => { ]); }); +test('resolves inverse dependencies of mock', () => { + const paths = new Set([ + path.resolve(__dirname, '__fixtures__/hasMocked/__mocks__/file.js'), + ]); + const resolved = dependencyResolver.resolveInverse(paths, filter); + + expect(resolved).toEqual([ + expect.stringContaining( + path.join('__tests__', '__fixtures__', 'hasMocked', 'file.test.js'), + ), + ]); +}); + test('resolves inverse dependencies from available snapshot', () => { const paths = new Set([ path.resolve(__dirname, '__fixtures__/file.js'), diff --git a/packages/jest-resolve-dependencies/src/index.ts b/packages/jest-resolve-dependencies/src/index.ts index 1a6345e565c9..28f26a4f5925 100644 --- a/packages/jest-resolve-dependencies/src/index.ts +++ b/packages/jest-resolve-dependencies/src/index.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import * as path from 'path'; import {Config} from '@jest/types'; // eslint-disable-next-line import/no-extraneous-dependencies import {FS as HasteFS} from 'jest-haste-map'; @@ -51,7 +52,9 @@ class DependencyResolver { if (this._resolver.isCoreModule(dependency)) { return acc; } + let resolvedDependency; + let resolvedMockDependency; try { resolvedDependency = this._resolver.resolveModule( file, @@ -59,11 +62,37 @@ class DependencyResolver { options, ); } catch (e) { - resolvedDependency = this._resolver.getMockModule(file, dependency); + // TODO: This snippet might not be necessary, should be investigated later. + const mockDependency = this._resolver.getMockModule(file, dependency); + mockDependency && acc.push(mockDependency); + return acc; + } + + if (!resolvedDependency) { + return acc; } - if (resolvedDependency) { - acc.push(resolvedDependency); + acc.push(resolvedDependency); + + // If we resolve a dependency, then look for a mock dependency + // of the same name in that dependency's directory. + resolvedMockDependency = this._resolver.getMockModule( + path.dirname(resolvedDependency), + path.basename(dependency), + ); + + if (resolvedMockDependency) { + const dependencyMockDir = path.join( + path.dirname(resolvedDependency), + '__mocks__', + ); + + resolvedMockDependency = path.resolve(resolvedMockDependency); + + // make sure mock is in the correct directory + if (dependencyMockDir === path.dirname(resolvedMockDependency)) { + acc.push(resolvedMockDependency); + } } return acc; @@ -127,8 +156,9 @@ class DependencyResolver { } const modules: Array = []; for (const file of this._hasteFS.getAbsoluteFileIterator()) { + const res = this.resolve(file, options); modules.push({ - dependencies: this.resolve(file, options), + dependencies: res, file, }); }