Skip to content

Commit 1a48e4e

Browse files
authored
feat: throw when jest globals are used (#12)
Users might forget to replace all instances of the jest global with harness. We should remind them to do so as soon as we detect any usage. This pull request introduces the necessary changes to throw an error whenever the jest global is used or when @jest/globals is imported.
1 parent cfb2820 commit 1a48e4e

6 files changed

Lines changed: 79 additions & 4 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, it, expect } from 'react-native-harness';
2+
3+
describe('Jest globals warning', () => {
4+
it('should throw when accessing jest global', () => {
5+
expect(() => {
6+
// @ts-expect-error - jest is not available in Harness tests
7+
jest.fn();
8+
}).toThrow('Jest globals are not available in Harness tests');
9+
});
10+
11+
it('should throw when importing @jest/globals', () => {
12+
expect(() => require('@jest/globals')).toThrow(
13+
"Importing '@jest/globals' is not supported in Harness tests"
14+
);
15+
});
16+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Mock module for @jest/globals imports
2+
// This module throws immediately when imported to warn users about using Jest APIs
3+
4+
throw new Error(
5+
"Importing '@jest/globals' is not supported in Harness tests. Import from 'react-native-harness' instead."
6+
);

packages/metro/src/resolver.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ export const getHarnessResolver = (
3030
};
3131
}
3232

33+
// Intercept @jest/globals imports and redirect to mock module
34+
if (moduleName === '@jest/globals') {
35+
return {
36+
type: 'sourceFile',
37+
filePath: require.resolve('./jest-globals-mock'),
38+
};
39+
}
40+
3341
return resolvedModule;
3442
};
3543
};

packages/runtime/assets/moduleSystem.flow.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,14 @@ function loadModuleImplementation(
588588
// keep args in sync with with defineModuleCode in
589589
// metro/src/Resolver/index.js
590590
// and metro/src/ModuleGraph/worker.js
591+
const capturedRequire = (...args) => global.__r(...args);
592+
Object.assign(capturedRequire, global.__r);
593+
591594
factory(
592595
global,
593-
(...args) => global.__r(...args),
594-
(...args) => global.__r.importDefault(...args),
595-
(...args) => global.__r.importAll(...args),
596+
capturedRequire,
597+
capturedRequire.importDefault,
598+
capturedRequire.importAll,
596599
moduleObject,
597600
moduleObject.exports,
598601
dependencyMap

packages/runtime/src/initialize.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import { getDeviceDescriptor } from './client/getDeviceDescriptor.js';
22
import { getClient } from './client/index.js';
3+
import { setupJestMock } from './jest-mock.js';
34

45
// Polyfill for EventTarget
56
const Shim = require('event-target-shim');
67
globalThis.Event = Shim.Event;
78
globalThis.EventTarget = Shim.EventTarget;
89

10+
// Setup jest mock to warn users about using Jest APIs
11+
setupJestMock();
12+
913
// Turn off LogBox
1014
const { LogBox } = require('react-native');
1115
LogBox.ignoreAllLogs(true);
1216

1317
// Turn off HMR
1418
const HMRClientModule = require('react-native/Libraries/Utilities/HMRClient');
15-
const HMRClient = 'default' in HMRClientModule ? HMRClientModule.default : HMRClientModule;
19+
const HMRClient =
20+
'default' in HMRClientModule ? HMRClientModule.default : HMRClientModule;
1621

1722
// Wait for HMRClient to be initialized
1823
setTimeout(() => {
@@ -23,3 +28,8 @@ setTimeout(() => {
2328
client.rpc.reportReady(getDeviceDescriptor())
2429
);
2530
});
31+
32+
// Re-throw fatal errors
33+
ErrorUtils.setGlobalHandler((error) => {
34+
throw error;
35+
});

packages/runtime/src/jest-mock.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Mock jest global to warn users about using Jest APIs in Harness tests
2+
export const setupJestMock = (): void => {
3+
function throwError(): never {
4+
throw new Error(
5+
`Jest globals are not available in Harness tests. Import from 'react-native-harness' instead (e.g., import { harness } from 'react-native-harness'; harness.fn())`
6+
);
7+
}
8+
9+
const jestMock = new Proxy(
10+
{},
11+
{
12+
get() {
13+
throwError();
14+
},
15+
set() {
16+
throwError();
17+
},
18+
has() {
19+
throwError();
20+
},
21+
ownKeys() {
22+
throwError();
23+
},
24+
}
25+
);
26+
27+
Object.defineProperty(globalThis, 'jest', {
28+
value: jestMock,
29+
writable: false,
30+
configurable: false,
31+
});
32+
};

0 commit comments

Comments
 (0)