Skip to content

Commit 27681db

Browse files
authored
Merge pull request #716 from thebuilder/fix/improve-is-mocking
2 parents f098c1e + 4e71f09 commit 27681db

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/__tests__/hooks.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ test("should handle defaultFallbackInView if unsupported", () => {
387387
);
388388
});
389389

390-
test("should restore the browser IntersectingObserver", () => {
390+
test("should restore the browser IntersectionObserver", () => {
391391
expect(vi.isMockFunction(window.IntersectionObserver)).toBe(true);
392392
destroyIntersectionMocking();
393393

src/test-utils.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,53 @@ type Item = {
77
created: number;
88
};
99

10-
let isMocking = false;
11-
1210
const observers = new Map<IntersectionObserver, Item>();
1311

1412
// Store a reference to the original `IntersectionObserver` so we can restore it later.
1513
// This can be relevant if testing in a browser environment, where you actually have a native `IntersectionObserver`.
1614
const originalIntersectionObserver =
1715
typeof window !== "undefined" ? window.IntersectionObserver : undefined;
1816

17+
/**
18+
* Get the test utility object, depending on the environment. This could be either `vi` (Vitest) or `jest`.
19+
* Type is mapped to Vitest, so we don't mix in Jest types when running in Vitest.
20+
*/
21+
function testLibraryUtil(): typeof vi | undefined {
22+
if (typeof vi !== "undefined") return vi;
23+
// @ts-expect-error We don't include the Jest types
24+
if (typeof jest !== "undefined") return jest;
25+
return undefined;
26+
}
27+
28+
/**
29+
* Check if the IntersectionObserver is currently being mocked.
30+
* @return boolean
31+
*/
32+
function isMocking() {
33+
const util = testLibraryUtil();
34+
if (util && typeof util.isMockFunction === "function") {
35+
return util.isMockFunction(window.IntersectionObserver);
36+
}
37+
return false;
38+
}
39+
1940
/*
2041
** If we are running in a valid testing environment, we can automate mocking the IntersectionObserver.
2142
*/
2243
if (
2344
typeof window !== "undefined" &&
24-
typeof beforeAll !== "undefined" &&
2545
typeof beforeEach !== "undefined" &&
2646
typeof afterEach !== "undefined"
2747
) {
28-
const initMocking = () => {
29-
// Use the exposed mock function. Currently, it supports Jest (`jest.fn`) and Vitest with globals (`vi.fn`).
30-
// @ts-ignore
31-
if (typeof jest !== "undefined") setupIntersectionMocking(jest.fn);
32-
else if (typeof vi !== "undefined") {
33-
setupIntersectionMocking(vi.fn);
48+
beforeEach(() => {
49+
const util = testLibraryUtil();
50+
if (util) {
51+
setupIntersectionMocking(util.fn);
3452
}
35-
};
53+
// Ensure there's no observers from previous tests
54+
observers.clear();
55+
});
3656

37-
beforeAll(initMocking);
38-
beforeEach(initMocking);
3957
afterEach(resetIntersectionMocking);
4058
}
4159

@@ -57,7 +75,7 @@ function getActFn() {
5775
}
5876

5977
function warnOnMissingSetup() {
60-
if (isMocking) return;
78+
if (isMocking()) return;
6179
console.error(
6280
`React Intersection Observer was not configured to handle mocking.
6381
Outside Jest and Vitest, you might need to manually configure it by calling setupIntersectionMocking() and resetIntersectionMocking() in your test setup file.
@@ -82,7 +100,6 @@ afterEach(() => {
82100
* @param mockFn The mock function to use. Defaults to `vi.fn`.
83101
*/
84102
export function setupIntersectionMocking(mockFn: typeof vi.fn) {
85-
if (isMocking) return;
86103
window.IntersectionObserver = mockFn((cb, options = {}) => {
87104
const item = {
88105
callback: cb,
@@ -111,8 +128,6 @@ export function setupIntersectionMocking(mockFn: typeof vi.fn) {
111128

112129
return instance;
113130
});
114-
115-
isMocking = true;
116131
}
117132

118133
/**
@@ -137,7 +152,6 @@ export function destroyIntersectionMocking() {
137152
resetIntersectionMocking();
138153
// @ts-ignore
139154
window.IntersectionObserver = originalIntersectionObserver;
140-
isMocking = false;
141155
}
142156

143157
function triggerIntersection(

0 commit comments

Comments
 (0)