Skip to content

Commit 79cc0a4

Browse files
fix: allow mocking of fetch proxy (#552)
* fix: allow proxied fetch to be mocked in beforeAll * test: confirm that beforeEach mocking works
1 parent 76d2b57 commit 79cc0a4

File tree

4 files changed

+78
-16
lines changed

4 files changed

+78
-16
lines changed

packages/dom-evaluator/src/dom-test-evaluator.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ const removeTestScripts = () => {
5858
document.addEventListener("submit", (e) => {
5959
e.preventDefault();
6060
});
61-
const originalFetch = globalThis.fetch;
61+
62+
// @ts-expect-error The proxy doesn't fully implement the fetch API
63+
globalThis.fetch = createFetchProxy(parent);
6264

6365
export class DOMTestEvaluator implements TestEvaluator {
6466
#runTest?: TestEvaluator["runTest"];
@@ -136,8 +138,6 @@ export class DOMTestEvaluator implements TestEvaluator {
136138

137139
this.#runTest = async function (rawTest: string): Promise<Fail | Pass> {
138140
this.#proxyConsole.on();
139-
// @ts-expect-error The proxy doesn't fully implement the fetch API
140-
globalThis.fetch = createFetchProxy(parent);
141141

142142
try {
143143
const testWithBefore = `${opts.hooks?.beforeEach ?? ""};
@@ -168,8 +168,6 @@ ${rawTest}`;
168168
// eslint-disable-next-line no-unsafe-finally
169169
return this.#createErrorResponse(afterEachErr as TestError);
170170
}
171-
172-
globalThis.fetch = originalFetch;
173171
}
174172
};
175173

packages/javascript-evaluator/src/javascript-test-evaluator.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ import { createAsyncIife } from "../../shared/src/async-iife";
1919
import { ProxyConsole } from "../../shared/src/proxy-console";
2020
import { createFetchProxy } from "../../shared/src/proxy-fetch";
2121

22-
const originalFetch = globalThis.fetch;
23-
2422
const READY_MESSAGE: ReadyEvent["data"] = { type: "ready" };
2523
declare global {
2624
var assert: typeof chaiAssert;
@@ -58,13 +56,14 @@ export class JavascriptTestEvaluator implements TestEvaluator {
5856
}
5957

6058
init(opts: InitWorkerOptions) {
59+
// @ts-expect-error The proxy doesn't fully implement the fetch API
60+
globalThis.fetch = createFetchProxy(globalThis);
61+
6162
eval(opts.hooks?.beforeAll ?? "");
6263

6364
this.#runTest = async (rawTest) => {
6465
this.#proxyConsole.on();
6566

66-
// @ts-expect-error The proxy doesn't fully implement the fetch API
67-
globalThis.fetch = createFetchProxy(globalThis);
6867
const test = createAsyncIife(rawTest);
6968
// This can be reassigned by the eval inside the try block, so it should be declared as a let
7069
// eslint-disable-next-line prefer-const
@@ -110,8 +109,6 @@ ${test};`);
110109
// eslint-disable-next-line no-unsafe-finally
111110
return this.#createErrorResponse(afterEachErr as TestError);
112111
}
113-
114-
globalThis.fetch = originalFetch;
115112
}
116113
};
117114
}

packages/python-evaluator/src/python-test-evaluator.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ type EvaluatedTeststring = {
3333
test: () => Promise<unknown>;
3434
};
3535

36-
const originalFetch = globalThis.fetch;
3736
const READY_MESSAGE: ReadyEvent["data"] = { type: "ready" };
3837

3938
function isProxy(raw: unknown): raw is PyProxy {
@@ -71,6 +70,8 @@ class PythonTestEvaluator implements TestEvaluator {
7170

7271
async init(opts: InitWorkerOptions) {
7372
const pyodide = await this.#setupPyodide();
73+
// @ts-expect-error The proxy doesn't fully implement the fetch API
74+
globalThis.fetch = createFetchProxy(globalThis);
7475
eval(opts.hooks?.beforeAll ?? "");
7576

7677
this.#runTest = async (rawTestString): Promise<Pass | Fail> => {
@@ -117,9 +118,6 @@ def __fake_input(arg=None):
117118
input = __fake_input
118119
`);
119120

120-
// @ts-expect-error The proxy doesn't fully implement the fetch API
121-
globalThis.fetch = createFetchProxy(globalThis);
122-
123121
try {
124122
const testString = `${opts.hooks?.beforeEach ?? ""};
125123
${rawTestString}`;
@@ -200,7 +198,6 @@ ${rawTestString}`;
200198
}
201199

202200
__userGlobals.destroy();
203-
globalThis.fetch = originalFetch;
204201
}
205202
};
206203
}

packages/tests/integration-tests/index.test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,76 @@ new Promise((resolve) => {
592592
});
593593
});
594594

595+
it("should be possible to mock fetch in tests", async () => {
596+
const beforeAll = `
597+
globalThis.originalFetch = globalThis.fetch;
598+
globalThis.fetch = () => Promise.resolve( { json: () => Promise.resolve({ message: 'Mocked fetch!' }) } );
599+
`;
600+
601+
const afterAll = `
602+
globalThis.fetch = originalFetch;
603+
`;
604+
605+
const result = await page.evaluate(
606+
async (type, beforeAll, afterAll) => {
607+
const runner = await window.FCCTestRunner.createTestRunner({
608+
type,
609+
hooks: {
610+
beforeAll,
611+
afterAll,
612+
},
613+
});
614+
return runner.runAllTests([
615+
`
616+
const response = await fetch('https://any.url');
617+
const data = await response.json();
618+
assert.deepEqual(data, { message: 'Mocked fetch!' });
619+
`,
620+
]);
621+
},
622+
type,
623+
beforeAll,
624+
afterAll,
625+
);
626+
627+
expect(result).toEqual([{ pass: true }]);
628+
});
629+
630+
it("should be possible to mock fetch in the beforeEach hook", async () => {
631+
const beforeEach = `
632+
globalThis.originalFetch = globalThis.fetch;
633+
globalThis.fetch = () => Promise.resolve( { json: () => Promise.resolve({ message: 'Mocked fetch in beforeEach!' }) } );
634+
`;
635+
636+
const afterEach = `
637+
globalThis.fetch = originalFetch;
638+
`;
639+
640+
const result = await page.evaluate(
641+
async (type, beforeEach, afterEach) => {
642+
const runner = await window.FCCTestRunner.createTestRunner({
643+
type,
644+
hooks: {
645+
beforeEach,
646+
afterEach,
647+
},
648+
});
649+
return runner.runAllTests([
650+
`
651+
const response = await fetch('https://any.url');
652+
const data = await response.json();
653+
assert.deepEqual(data, { message: 'Mocked fetch in beforeEach!' });
654+
`,
655+
]);
656+
},
657+
type,
658+
beforeEach,
659+
afterEach,
660+
);
661+
662+
expect(result).toEqual([{ pass: true }]);
663+
});
664+
595665
it("should make fetch requests from the browsing context of the test runner", async () => {
596666
const result = await page.evaluate(async (type) => {
597667
// Create spy

0 commit comments

Comments
 (0)