Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: set MODULE_NOT_FOUND code when module is not resolved from paths #8487

Merged
merged 13 commits into from
Nov 9, 2019
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
- `[jest-fake-timers]` `getTimerCount` will not include cancelled immediates ([#8764](https://github.com/facebook/jest/pull/8764))
- `[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-reporters]` Make node-notifier an optional dependency ([#8918](https://github.com/facebook/jest/pull/8918))
- `[jest-resolve]`: Set MODULE_NOT_FOUND as error code when module is not resolved from paths ([#8487](https://github.com/facebook/jest/pull/8487))
- `[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))
Expand Down
2 changes: 1 addition & 1 deletion e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ FAIL __tests__/index.js
12 | module.exports = () => 'test';
13 |

at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:483:17)
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:487:17)
at Object.require (index.js:10:1)
`;
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ FAIL __tests__/test.js
| ^
9 |

at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:272:17)
at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:276:11)
at Object.require (index.js:8:18)
`;
6 changes: 6 additions & 0 deletions e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ test('throws an error if the module cannot be found from given paths', () => {
"Cannot resolve module './mod.js' from paths ['..'] from "
);
});

test('throws module not found error if the module cannot be found from given paths', () => {
expect(() => require.resolve('./mod.js', {paths: ['..']})).toThrow(
expect.objectContaining({code: 'MODULE_NOT_FOUND'})
);
});
9 changes: 9 additions & 0 deletions e2e/resolve/__tests__/resolve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,12 @@ test('should require resolve haste mocks correctly', () => {

expect(require('Test6').key).toBe('mock');
});

test('should throw module not found error if the module cannot be found', () => {
expect(() => require('Test7')).toThrow(
expect.objectContaining({
code: 'MODULE_NOT_FOUND',
message: "Cannot find module 'Test7' from 'resolve.test.js'",
})
);
});
10 changes: 10 additions & 0 deletions packages/jest-resolve/src/ModuleNotFoundError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* 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.
*/

export default class ModuleNotFoundError extends Error {
Copy link
Collaborator

@thymikee thymikee May 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Node 6 snapshot failures show pretty important change (not sure why it's different on higher versions though), since now we don't point to the place error happened, but to the error itself. We have a utility Error class called ErrorWithStack – maybe you could play with it and extend it directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like jest-resolve doesn't depend jest-utils, so can I use Error.captureStackTrace instead of extend ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I can add dependency for jest-resolve, maybe we can move ModuleNotFoundError to jest-util as well

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about that, @SimenB?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/cc @SimenB

code = 'MODULE_NOT_FOUND';
}
5 changes: 2 additions & 3 deletions packages/jest-resolve/src/defaultResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import pnpResolver from 'jest-pnp-resolver';
import {Config} from '@jest/types';
import isBuiltinModule from './isBuiltinModule';
import nodeModulesPaths from './nodeModulesPaths';
import ModuleNotFoundError from './ModuleNotFoundError';

type ResolverOptions = {
basedir: Config.Path;
Expand Down Expand Up @@ -84,11 +85,9 @@ function resolveSync(
return target;
}

const err: Error & {code?: string} = new Error(
throw new ModuleNotFoundError(
"Cannot find module '" + target + "' from '" + basedir + "'",
);
err.code = 'MODULE_NOT_FOUND';
throw err;

/*
* contextual helper functions
Expand Down
8 changes: 5 additions & 3 deletions packages/jest-resolve/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import nodeModulesPaths from './nodeModulesPaths';
import isBuiltinModule from './isBuiltinModule';
import defaultResolver, {clearDefaultResolverCache} from './defaultResolver';
import {ResolverConfig} from './types';
import ModuleNotFoundError from './ModuleNotFoundError';

type FindNodeModuleConfig = {
basedir: Config.Path;
Expand Down Expand Up @@ -79,6 +80,8 @@ class Resolver {
this._modulePathCache = new Map();
}

static ModuleNotFoundError = ModuleNotFoundError;

static clearDefaultResolverCache() {
clearDefaultResolverCache();
}
Expand Down Expand Up @@ -209,11 +212,10 @@ class Resolver {
// produces an error based on the dirname but we have the actual current
// module name available.
const relativePath = path.relative(dirname, from);
const err: Error & {code?: string} = new Error(

throw new ModuleNotFoundError(
`Cannot find module '${moduleName}' from '${relativePath || '.'}'`,
);
err.code = 'MODULE_NOT_FOUND';
throw err;
}

isCoreModule(moduleName: string): boolean {
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@ class Runtime {
return module;
}
}
throw new Error(

throw new Resolver.ModuleNotFoundError(
`Cannot resolve module '${moduleName}' from paths ['${paths.join(
"', '",
)}'] from ${from}`,
Expand Down