diff --git a/src/interceptors/ClientRequest/agents.ts b/src/interceptors/ClientRequest/agents.ts index 994e084e..5436f94c 100644 --- a/src/interceptors/ClientRequest/agents.ts +++ b/src/interceptors/ClientRequest/agents.ts @@ -39,7 +39,11 @@ export class MockAgent extends http.Agent { const socket = new MockHttpSocket({ connectionOptions: options, - createConnection: createConnection.bind(this, options, callback), + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), onRequest: this.onRequest.bind(this), onResponse: this.onResponse.bind(this), }) @@ -68,7 +72,11 @@ export class MockHttpsAgent extends https.Agent { const socket = new MockHttpSocket({ connectionOptions: options, - createConnection: createConnection.bind(this, options, callback), + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), onRequest: this.onRequest.bind(this), onResponse: this.onResponse.bind(this), }) diff --git a/test/modules/http/compliance/http-custom-agent.test.ts b/test/modules/http/compliance/http-custom-agent.test.ts new file mode 100644 index 00000000..1a69ed5a --- /dev/null +++ b/test/modules/http/compliance/http-custom-agent.test.ts @@ -0,0 +1,64 @@ +// @vitest-environment node +import { vi, it, expect, beforeAll, afterAll, afterEach } from 'vitest' +import http from 'node:http' +import https from 'node:https' +import { HttpServer } from '@open-draft/test-server/http' +import { ClientRequestInterceptor } from '../../../../src/interceptors/ClientRequest/index' +import { waitForClientRequest } from '../../../../test/helpers' + +const interceptor = new ClientRequestInterceptor() + +const httpServer = new HttpServer((app) => { + app.get('/resource', (req, res) => res.send('hello world')) +}) + +beforeAll(async () => { + interceptor.apply() + await httpServer.listen() +}) + +afterEach(() => { + interceptor.removeAllListeners() +}) + +afterAll(async () => { + interceptor.dispose() + await httpServer.close() +}) + +it('preserves the context of the "createConnection" function in a custom http agent', async () => { + const createConnectionContextSpy = vi.fn() + class CustomHttpAgent extends http.Agent { + createConnection(options: any, callback: any) { + createConnectionContextSpy(this) + return super.createConnection(options, callback) + } + } + const agent = new CustomHttpAgent() + + const request = http.get(httpServer.http.url('/resource'), { agent }) + await waitForClientRequest(request) + + const [context] = createConnectionContextSpy.mock.calls[0] + expect(context.constructor.name).toBe('CustomHttpAgent') +}) + +it('preserves the context of the "createConnection" function in a custom https agent', async () => { + const createConnectionContextSpy = vi.fn() + class CustomHttpsAgent extends https.Agent { + createConnection(options: any, callback: any) { + createConnectionContextSpy(this) + return super.createConnection(options, callback) + } + } + const agent = new CustomHttpsAgent() + + const request = https.get(httpServer.https.url('/resource'), { + agent, + rejectUnauthorized: false, + }) + await waitForClientRequest(request) + + const [context] = createConnectionContextSpy.mock.calls[0] + expect(context.constructor.name).toBe('CustomHttpsAgent') +})