Skip to content

Commit

Permalink
Merge branch 'main' into maxRelatedTestsDepth
Browse files Browse the repository at this point in the history
  • Loading branch information
lewibs authored Feb 19, 2025
2 parents 787ac67 + 93ca9d3 commit c81e69a
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 40 deletions.
7 changes: 5 additions & 2 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"lockFileMaintenance": {"enabled": true, "automerge": false},
"extends": ["config:recommended"],
"lockFileMaintenance": {
"enabled": true,
"automerge": false
},
"rangeStrategy": "replace",
"postUpdateOptions": ["yarnDedupeHighest"],
"packageRules": [
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- `[jest-mock]` Add support for the Explicit Resource Management proposal to use the `using` keyword with `jest.spyOn(object, methodName)` ([#14895](https://github.com/jestjs/jest/pull/14895))
- `[jest-reporters]` Add support for [DEC mode 2026](https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036) ([#15008](https://github.com/jestjs/jest/pull/15008))
- `[jest-resolver]` Support `file://` URLs as paths ([#15154](https://github.com/jestjs/jest/pull/15154))
- `[jest-resolve,jest-runtime,jest-resolve-dependencies]` Pass the conditions when resolving stub modules ([#15489](https://github.com/jestjs/jest/pull/15489))
- `[jest-runtime]` Exposing new modern timers function `jest.advanceTimersToFrame()` from `@jest/fake-timers` ([#14598](https://github.com/jestjs/jest/pull/14598))
- `[jest-runtime]` Support `import.meta.filename` and `import.meta.dirname` (available from [Node 20.11](https://nodejs.org/en/blog/release/v20.11.0)) ([#14854](https://github.com/jestjs/jest/pull/14854))
- `[jest-runtime]` Support `import.meta.resolve` ([#14930](https://github.com/jestjs/jest/pull/14930))
Expand Down
4 changes: 2 additions & 2 deletions e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ exports[`moduleNameMapper wrong array configuration 1`] = `
12 | module.exports = () => 'test';
13 |
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:1182:17)
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:1184:17)
at Object.require (index.js:10:1)
at Object.require (__tests__/index.js:10:20)"
`;
Expand Down Expand Up @@ -71,7 +71,7 @@ exports[`moduleNameMapper wrong configuration 1`] = `
12 | module.exports = () => 'test';
13 |
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:1182:17)
at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:1184:17)
at Object.require (index.js:10:1)
at Object.require (__tests__/index.js:10:20)"
`;
14 changes: 14 additions & 0 deletions e2e/resolve-conditions/__tests__/module-name-mapper.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @jest-environment jest-environment-jsdom
*/

import {fn} from 'fake-dual-dep2';

test('returns correct message', () => {
expect(fn()).toBe('from browser');
});
10 changes: 10 additions & 0 deletions e2e/resolve-conditions/node_modules/fake-dual-dep2/browser.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions e2e/resolve-conditions/node_modules/fake-dual-dep2/node.mjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions e2e/resolve-conditions/node_modules/fake-dual-dep2/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions e2e/resolve-conditions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"testMatch": [
"<rootDir>/**/*.test.*"
],
"moduleNameMapper": {
"^fake-dual-dep2$": "fake-dual-dep2"
},
"transform": {}
}
}
10 changes: 8 additions & 2 deletions packages/jest-resolve-dependencies/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class DependencyResolver {

resolve(file: string, options?: ResolveModuleConfig): Array<string> {
const dependencies = this._hasteFS.getDependencies(file);
const fallbackOptions: ResolveModuleConfig = {conditions: undefined};
if (!dependencies) {
return [];
}
Expand All @@ -51,11 +52,15 @@ export class DependencyResolver {
resolvedDependency = this._resolver.resolveModule(
file,
dependency,
options,
options ?? fallbackOptions,
);
} catch {
try {
resolvedDependency = this._resolver.getMockModule(file, dependency);
resolvedDependency = this._resolver.getMockModule(
file,
dependency,
options ?? fallbackOptions,
);
} catch {
// leave resolvedDependency as undefined if nothing can be found
}
Expand All @@ -73,6 +78,7 @@ export class DependencyResolver {
resolvedMockDependency = this._resolver.getMockModule(
resolvedDependency,
path.basename(dependency),
options ?? fallbackOptions,
);
} catch {
// leave resolvedMockDependency as undefined if nothing can be found
Expand Down
8 changes: 7 additions & 1 deletion packages/jest-resolve/src/__tests__/resolve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,9 @@ describe('getMockModuleAsync', () => {
} as ResolverConfig);
const src = require.resolve('../');

await resolver.resolveModuleAsync(src, 'dependentModule');
await resolver.resolveModuleAsync(src, 'dependentModule', {
conditions: ['browser'],
});

expect(mockUserResolverAsync.async).toHaveBeenCalled();
expect(mockUserResolverAsync.async.mock.calls[0][0]).toBe(
Expand All @@ -752,6 +754,10 @@ describe('getMockModuleAsync', () => {
'basedir',
path.dirname(src),
);
expect(mockUserResolverAsync.async.mock.calls[0][1]).toHaveProperty(
'conditions',
['browser'],
);
});
});

Expand Down
76 changes: 53 additions & 23 deletions packages/jest-resolve/src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,11 @@ export default class Resolver {
resolveModule(
from: string,
moduleName: string,
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): string {
const dirname = path.dirname(from);
const module =
this.resolveStubModuleName(from, moduleName) ||
this.resolveStubModuleName(from, moduleName, options) ||
this.resolveModuleFromDirIfExists(dirname, moduleName, options);
if (module) return module;

Expand All @@ -363,7 +363,7 @@ export default class Resolver {
): Promise<string> {
const dirname = path.dirname(from);
const module =
(await this.resolveStubModuleNameAsync(from, moduleName)) ||
(await this.resolveStubModuleNameAsync(from, moduleName, options)) ||
(await this.resolveModuleFromDirIfExistsAsync(
dirname,
moduleName,
Expand Down Expand Up @@ -483,25 +483,37 @@ export default class Resolver {
);
}

getMockModule(from: string, name: string): string | null {
getMockModule(
from: string,
name: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): string | null {
const mock = this._moduleMap.getMockModule(name);
if (mock) {
return mock;
} else {
const moduleName = this.resolveStubModuleName(from, name);
const moduleName = this.resolveStubModuleName(from, name, options);
if (moduleName) {
return this.getModule(moduleName) || moduleName;
}
}
return null;
}

async getMockModuleAsync(from: string, name: string): Promise<string | null> {
async getMockModuleAsync(
from: string,
name: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): Promise<string | null> {
const mock = this._moduleMap.getMockModule(name);
if (mock) {
return mock;
} else {
const moduleName = await this.resolveStubModuleNameAsync(from, name);
const moduleName = await this.resolveStubModuleNameAsync(
from,
name,
options,
);
if (moduleName) {
return this.getModule(moduleName) || moduleName;
}
Expand Down Expand Up @@ -537,7 +549,7 @@ export default class Resolver {
virtualMocks: Map<string, boolean>,
from: string,
moduleName = '',
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): string {
const stringifiedOptions = options ? JSON.stringify(options) : '';
const key = from + path.delimiter + moduleName + stringifiedOptions;
Expand All @@ -553,7 +565,7 @@ export default class Resolver {
moduleName,
options,
);
const mockPath = this._getMockPath(from, moduleName);
const mockPath = this._getMockPath(from, moduleName, options);

const sep = path.delimiter;
const id =
Expand All @@ -571,7 +583,7 @@ export default class Resolver {
virtualMocks: Map<string, boolean>,
from: string,
moduleName = '',
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): Promise<string> {
const stringifiedOptions = options ? JSON.stringify(options) : '';
const key = from + path.delimiter + moduleName + stringifiedOptions;
Expand All @@ -590,7 +602,7 @@ export default class Resolver {
moduleName,
options,
);
const mockPath = await this._getMockPathAsync(from, moduleName);
const mockPath = await this._getMockPathAsync(from, moduleName, options);

const sep = path.delimiter;
const id =
Expand All @@ -612,15 +624,15 @@ export default class Resolver {
virtualMocks: Map<string, boolean>,
from: string,
moduleName: string,
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): string | null {
if (this.isCoreModule(moduleName)) {
return moduleName;
}
if (moduleName.startsWith('data:')) {
return moduleName;
}
return this._isModuleResolved(from, moduleName)
return this._isModuleResolved(from, moduleName, options)
? this.getModule(moduleName)
: this._getVirtualMockPath(virtualMocks, from, moduleName, options);
}
Expand All @@ -629,7 +641,7 @@ export default class Resolver {
virtualMocks: Map<string, boolean>,
from: string,
moduleName: string,
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): Promise<string | null> {
if (this.isCoreModule(moduleName)) {
return moduleName;
Expand All @@ -640,32 +652,38 @@ export default class Resolver {
const isModuleResolved = await this._isModuleResolvedAsync(
from,
moduleName,
options,
);
return isModuleResolved
? this.getModule(moduleName)
: this._getVirtualMockPathAsync(virtualMocks, from, moduleName, options);
}

private _getMockPath(from: string, moduleName: string): string | null {
private _getMockPath(
from: string,
moduleName: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): string | null {
return this.isCoreModule(moduleName)
? null
: this.getMockModule(from, moduleName);
: this.getMockModule(from, moduleName, options);
}

private async _getMockPathAsync(
from: string,
moduleName: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): Promise<string | null> {
return this.isCoreModule(moduleName)
? null
: this.getMockModuleAsync(from, moduleName);
: this.getMockModuleAsync(from, moduleName, options);
}

private _getVirtualMockPath(
virtualMocks: Map<string, boolean>,
from: string,
moduleName: string,
options?: ResolveModuleConfig,
options: ResolveModuleConfig,
): string {
const virtualMockPath = this.getModulePath(from, moduleName);
return virtualMocks.get(virtualMockPath)
Expand All @@ -689,23 +707,33 @@ export default class Resolver {
: from;
}

private _isModuleResolved(from: string, moduleName: string): boolean {
private _isModuleResolved(
from: string,
moduleName: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): boolean {
return !!(
this.getModule(moduleName) || this.getMockModule(from, moduleName)
this.getModule(moduleName) ||
this.getMockModule(from, moduleName, options)
);
}

private async _isModuleResolvedAsync(
from: string,
moduleName: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): Promise<boolean> {
return !!(
this.getModule(moduleName) ||
(await this.getMockModuleAsync(from, moduleName))
(await this.getMockModuleAsync(from, moduleName, options))
);
}

resolveStubModuleName(from: string, moduleName: string): string | null {
resolveStubModuleName(
from: string,
moduleName: string,
options: Pick<ResolveModuleConfig, 'conditions'>,
): string | null {
const dirname = path.dirname(from);

const {extensions, moduleDirectory, paths} = this._prepareForResolution(
Expand All @@ -728,11 +756,11 @@ export default class Resolver {
let module: string | null = null;
for (const possibleModuleName of possibleModuleNames) {
const updatedName = mapModuleName(possibleModuleName);

module =
this.getModule(updatedName) ||
Resolver.findNodeModule(updatedName, {
basedir: dirname,
conditions: options?.conditions,
extensions,
moduleDirectory,
paths,
Expand Down Expand Up @@ -764,6 +792,7 @@ export default class Resolver {
async resolveStubModuleNameAsync(
from: string,
moduleName: string,
options?: Pick<ResolveModuleConfig, 'conditions'>,
): Promise<string | null> {
const dirname = path.dirname(from);

Expand Down Expand Up @@ -792,6 +821,7 @@ export default class Resolver {
this.getModule(updatedName) ||
(await Resolver.findNodeModuleAsync(updatedName, {
basedir: dirname,
conditions: options?.conditions,
extensions,
moduleDirectory,
paths,
Expand Down
Loading

0 comments on commit c81e69a

Please sign in to comment.