diff --git a/packages/babel-plugin-jest-hoist/src/__tests__/__snapshots__/hoistPlugin.test.ts.snap b/packages/babel-plugin-jest-hoist/src/__tests__/__snapshots__/hoistPlugin.test.ts.snap
index 0c1a8424ff4f..4ce0fdde3291 100644
--- a/packages/babel-plugin-jest-hoist/src/__tests__/__snapshots__/hoistPlugin.test.ts.snap
+++ b/packages/babel-plugin-jest-hoist/src/__tests__/__snapshots__/hoistPlugin.test.ts.snap
@@ -1,5 +1,42 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`babel-plugin-jest-hoist automatic react runtime: automatic react runtime 1`] = `
+
+jest.mock('./App', () => () =>
Hello world
);
+
+ ↓ ↓ ↓ ↓ ↓ ↓
+
+_getJestObj().mock("./App", () => () =>
+ /*#__PURE__*/ _jsxDEV(
+ "div",
+ {
+ children: "Hello world"
+ },
+ void 0,
+ false,
+ {
+ fileName: _jsxFileName,
+ lineNumber: 1,
+ columnNumber: 32
+ },
+ this
+ )
+);
+
+import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
+var _jsxFileName = "";
+
+function _getJestObj() {
+ const { jest } = require("@jest/globals");
+
+ _getJestObj = () => jest;
+
+ return jest;
+}
+
+
+`;
+
exports[`babel-plugin-jest-hoist top level mocking: top level mocking 1`] = `
require('x');
diff --git a/packages/babel-plugin-jest-hoist/src/__tests__/hoistPlugin.test.ts b/packages/babel-plugin-jest-hoist/src/__tests__/hoistPlugin.test.ts
index a2a7fead5459..70a47f154a47 100644
--- a/packages/babel-plugin-jest-hoist/src/__tests__/hoistPlugin.test.ts
+++ b/packages/babel-plugin-jest-hoist/src/__tests__/hoistPlugin.test.ts
@@ -23,7 +23,7 @@ pluginTester({
],
},
code: `
- jest.mock('./App', () => () => Hello world
, {virtual: true});
+ jest.mock('./App', () => () => Hello world
);
`,
snapshot: true,
},
diff --git a/packages/babel-plugin-jest-hoist/src/index.ts b/packages/babel-plugin-jest-hoist/src/index.ts
index 15e2c5bf5ae7..28c2b07819d5 100644
--- a/packages/babel-plugin-jest-hoist/src/index.ts
+++ b/packages/babel-plugin-jest-hoist/src/index.ts
@@ -120,41 +120,45 @@ FUNCTIONS.mock = args => {
moduleFactory.traverse(IDVisitor, {ids});
for (const id of ids) {
const {name} = id.node;
- let found = false;
let scope = id.scope;
while (scope !== parentScope) {
if (scope.bindings[name]) {
- found = true;
- break;
+ return true;
}
scope = scope.parent;
}
- if (!found) {
- const isAllowedIdentifier =
- (scope.hasGlobal(name) && ALLOWED_IDENTIFIERS.has(name)) ||
- /^mock/i.test(name) ||
- // Allow istanbul's coverage variable to pass.
- /^(?:__)?cov/.test(name);
-
- if (!isAllowedIdentifier) {
- throw id.buildCodeFrameError(
- 'The module factory of `jest.mock()` is not allowed to ' +
- 'reference any out-of-scope variables.\n' +
- 'Invalid variable access: ' +
- name +
- '\n' +
- 'Allowed objects: ' +
- Array.from(ALLOWED_IDENTIFIERS).join(', ') +
- '.\n' +
- 'Note: This is a precaution to guard against uninitialized mock ' +
- 'variables. If it is ensured that the mock is required lazily, ' +
- 'variable names prefixed with `mock` (case insensitive) are permitted.\n',
- ReferenceError,
- );
- }
+ const binding = scope.bindings[name];
+
+ // @ts-expect-error `init` does not exist
+ if (binding?.constant && scope.isPure(binding.path.node.init, true)) {
+ // how to hoist???
+ return true;
+ }
+
+ const isAllowedIdentifier =
+ (scope.hasGlobal(name) && ALLOWED_IDENTIFIERS.has(name)) ||
+ /^mock/i.test(name) ||
+ // Allow istanbul's coverage variable to pass.
+ /^(?:__)?cov/.test(name);
+
+ if (!isAllowedIdentifier) {
+ throw id.buildCodeFrameError(
+ 'The module factory of `jest.mock()` is not allowed to ' +
+ 'reference any out-of-scope variables.\n' +
+ 'Invalid variable access: ' +
+ name +
+ '\n' +
+ 'Allowed objects: ' +
+ Array.from(ALLOWED_IDENTIFIERS).join(', ') +
+ '.\n' +
+ 'Note: This is a precaution to guard against uninitialized mock ' +
+ 'variables. If it is ensured that the mock is required lazily, ' +
+ 'variable names prefixed with `mock` (case insensitive) are permitted.\n',
+ ReferenceError,
+ );
}
}