diff --git a/packages/dev-middleware/package.json b/packages/dev-middleware/package.json index 69086f84265e4c..12486a62d80d00 100644 --- a/packages/dev-middleware/package.json +++ b/packages/dev-middleware/package.json @@ -28,7 +28,6 @@ "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^2.2.0", - "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", diff --git a/packages/dev-middleware/src/__tests__/FetchUtils.js b/packages/dev-middleware/src/__tests__/FetchUtils.js index 9de0a10161bdc7..e5a266f4038555 100644 --- a/packages/dev-middleware/src/__tests__/FetchUtils.js +++ b/packages/dev-middleware/src/__tests__/FetchUtils.js @@ -10,9 +10,7 @@ */ import type {JSONSerializable} from '../inspector-proxy/types'; -import typeof * as NodeFetch from 'node-fetch'; -import https from 'https'; import {Agent} from 'undici'; /** @@ -46,25 +44,32 @@ export async function fetchJson(url: string): Promise { return response.json(); } -export function allowSelfSignedCertsInNodeFetch(): void { - jest.mock('node-fetch', () => { - const originalModule = jest.requireActual('node-fetch'); - const nodeFetch = originalModule.default; - return { - __esModule: true, - ...originalModule, - default: (url, options) => { - if ( - (url instanceof URL && url.protocol === 'https:') || - (typeof url === 'string' && url.startsWith('https:')) - ) { - const agent = new https.Agent({ - rejectUnauthorized: false, - }); - return nodeFetch(url.toString(), {agent, ...options}); - } - return nodeFetch(url, options); - }, - }; +/** + * Change the global fetch dispatcher to allow self-signed certificates. + * This runs with Jest's `beforeAll` and `afterAll`, and restores the original dispatcher. + */ +export function withFetchSelfSignedCertsForAllTests() { + const fetchOriginal = globalThis.fetch; + const selfSignedCertDispatcher = new Agent({ + connect: { + rejectUnauthorized: false, + }, + }); + + let fetchSpy; + + beforeAll(() => { + // For some reason, setting the `selfSignedCertDispatcher` with `setGlobalDispatcher` doesn't work. + // Instead of using `setGlobalDispatcher`, we'll use a spy to intercept the fetch calls and add the dispatcher. + fetchSpy = jest.spyOn(globalThis, 'fetch').mockImplementation((url, options) => ( + fetchOriginal(url, { + ...options, + dispatcher: options?.dispatcher ?? selfSignedCertDispatcher, + }) + )); + }); + + afterAll(() => { + fetchSpy.mockRestore(); }); } diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js index 969e7322ec81d0..94555a1f1da551 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpRewritingHacks-test.js @@ -8,8 +8,7 @@ * @format * @oncall react_native */ - -import {allowSelfSignedCertsInNodeFetch} from './FetchUtils'; +import {withFetchSelfSignedCertsForAllTests} from './FetchUtils'; import { createAndConnectTarget, parseJsonFromDataUri, @@ -33,16 +32,14 @@ jest.useRealTimers(); jest.setTimeout(10000); -beforeAll(() => { - // inspector-proxy uses node-fetch for source map fetching. - allowSelfSignedCertsInNodeFetch(); - - jest.resetModules(); -}); - describe.each(['HTTP', 'HTTPS'])( 'inspector proxy CDP rewriting hacks over %s', protocol => { + // Inspector proxy tests are using a self-signed certificate for HTTPS tests. + if (protocol === 'HTTPS') { + withFetchSelfSignedCertsForAllTests(); + } + const serverRef = withServerForEachTest({ logger: undefined, projectRoot: __dirname, diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 4d058de8dd203f..88b82f5995fed7 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -30,7 +30,6 @@ import type { import DeviceEventReporter from './DeviceEventReporter'; import * as fs from 'fs'; import invariant from 'invariant'; -import fetch from 'node-fetch'; import * as path from 'path'; import WS from 'ws';