diff --git a/test/third-party/axios.test.ts b/test/third-party/axios.test.ts index 33276599..7ae7700b 100644 --- a/test/third-party/axios.test.ts +++ b/test/third-party/axios.test.ts @@ -1,6 +1,4 @@ -/** - * @vitest-environment jsdom - */ +// @vitest-environment jsdom import { it, expect, beforeAll, afterEach, afterAll } from 'vitest' import axios from 'axios' import { HttpServer } from '@open-draft/test-server/http' @@ -114,7 +112,7 @@ it('bypass the interceptor and return the original response', async () => { /** * @see https://github.com/mswjs/interceptors/issues/564 */ -it('preserves "auth" (Authorization)', async () => { +it('preserves the "auth" options', async () => { const getRequestPromise = new DeferredPromise() interceptor.on('request', ({ request }) => { @@ -141,3 +139,45 @@ it('preserves "auth" (Authorization)', async () => { `Basic ${btoa('foo@bar.com:secret123')}` ) }) + +it('follows a mocked redirect response (xhr)', async () => { + interceptor.on('request', ({ request, controller }) => { + if (request.url.endsWith('/original')) { + return controller.respondWith( + Response.redirect('http://localhost:3000/redirected', 307) + ) + } + + if (request.url.endsWith('/redirected')) { + controller.respondWith(new Response('redirected response')) + } + }) + + const response = await axios.get('http://localhost:3000/original', { + adapter: 'xhr', + }) + + expect(response.status).toBe(200) + expect(response.data).toBe('redirected response') +}) + +it('follows a mocked redirect response (http)', async () => { + interceptor.on('request', ({ request, controller }) => { + if (request.url.endsWith('/original')) { + return controller.respondWith( + Response.redirect('http://localhost/redirected', 307) + ) + } + + if (request.url.endsWith('/redirected')) { + controller.respondWith(new Response('redirected response')) + } + }) + + const response = await axios.get('http://localhost/original', { + adapter: 'http', + }) + + expect(response.status).toBe(200) + expect(response.data).toBe('redirected response') +}) diff --git a/test/third-party/follow-redirect-http.test.ts b/test/third-party/follow-redirect-http.test.ts index f26bef11..5a805c11 100644 --- a/test/third-party/follow-redirect-http.test.ts +++ b/test/third-party/follow-redirect-http.test.ts @@ -1,15 +1,11 @@ -// @vitest-environment jsdom +// @vitest-environment node import { vi, it, expect, beforeAll, afterEach, afterAll } from 'vitest' import { https } from 'follow-redirects' import { HttpServer } from '@open-draft/test-server/http' import { ClientRequestInterceptor } from '../../src/interceptors/ClientRequest' -import type { HttpRequestEventMap } from '../../src/glossary' import { waitForClientRequest } from '../helpers' -const resolver = vi.fn() - const interceptor = new ClientRequestInterceptor() -interceptor.on('request', resolver) const server = new HttpServer((app) => { app.post('/resource', (req, res) => { @@ -24,6 +20,14 @@ const server = new HttpServer((app) => { app.post('/user', (req, res) => { res.status(200).send('hello from the server') }) + + app.get('/original', (req, res) => { + res.writeHead(307, { Location: server.https.url('/redirected') }) + }) + + app.get('/redirected', (req, res) => { + res.status(200).send('redirected response') + }) }) beforeAll(async () => { @@ -33,6 +37,7 @@ beforeAll(async () => { afterEach(() => { vi.resetAllMocks() + interceptor.removeAllListeners() }) afterAll(async () => { @@ -40,12 +45,15 @@ afterAll(async () => { await server.close() }) -it('intercepts a POST request issued by "follow-redirects"', async () => { +it('intercepts a request issued by "follow-redirects"', async () => { + const requestListener = vi.fn<[Request]>() + interceptor.on('request', ({ request }) => requestListener(request)) + const { address } = server.https const payload = JSON.stringify({ todo: 'Buy the milk' }) const catchResponseUrl = vi.fn() - const req = https.request( + const request = https.request( { method: 'POST', hostname: address.host, @@ -62,14 +70,16 @@ it('intercepts a POST request issued by "follow-redirects"', async () => { } ) - req.end(payload) + request.end(payload) - const { text } = await waitForClientRequest(req as any) + const { text } = await waitForClientRequest(request as any) - expect(resolver).toHaveBeenCalledTimes(2) + await vi.waitFor(() => { + expect(requestListener).toHaveBeenCalledTimes(2) + }) // Intercepted initial request. - const [{ request: initialRequest }] = resolver.mock.calls[0] + const [initialRequest] = requestListener.mock.calls[0] expect(initialRequest.method).toBe('POST') expect(initialRequest.url).toBe(server.https.url('/resource')) @@ -79,7 +89,7 @@ it('intercepts a POST request issued by "follow-redirects"', async () => { expect(await initialRequest.json()).toEqual({ todo: 'Buy the milk' }) // Intercepted redirect request (issued by "follow-redirects"). - const [{ request: redirectedRequest }] = resolver.mock.calls[1] + const [redirectedRequest] = requestListener.mock.calls[1] expect(redirectedRequest.method).toBe('POST') expect(redirectedRequest.url).toBe(server.https.url('/user')) @@ -92,3 +102,94 @@ it('intercepts a POST request issued by "follow-redirects"', async () => { expect(catchResponseUrl).toHaveBeenCalledWith(server.https.url('/user')) expect(await text()).toBe('hello from the server') }) + +it('supports mocking a redirect response to the original response', async () => { + const requestListener = vi.fn<[Request]>() + + interceptor.once('request', ({ request, controller }) => { + requestListener(request) + + if (request.url.endsWith('/original')) { + controller.respondWith( + Response.redirect(server.https.url('/redirected'), 307) + ) + } + }) + + const catchResponseUrl = vi.fn() + const request = https.request( + { + method: 'GET', + hostname: server.https.address.host, + port: server.https.address.port, + path: '/original', + rejectUnauthorized: false, + }, + (res) => { + catchResponseUrl(res.responseUrl) + } + ) + + request.end() + + const { text } = await waitForClientRequest(request as any) + + // Intercepted redirect request (issued by "follow-redirects"). + const [redirectedRequest] = requestListener.mock.calls[0] + + expect(redirectedRequest.method).toBe('GET') + expect(redirectedRequest.url).toBe(server.https.url('/original')) + + // Response (original). + expect(catchResponseUrl).toHaveBeenCalledWith(server.https.url('/redirected')) + expect(await text()).toBe('redirected response') +}) + +it('supports mocking a redirect response to a mocked response', async () => { + const requestListener = vi.fn<[Request]>() + + interceptor.on('request', ({ request, controller }) => { + requestListener(request) + + if (request.url.endsWith('/original')) { + return controller.respondWith( + Response.redirect('https://localhost:3000/redirected', 307) + ) + } + + if (request.url.endsWith('/redirected')) { + return controller.respondWith(new Response('mocked response')) + } + }) + + const catchResponseUrl = vi.fn() + const request = https.request( + { + method: 'GET', + hostname: server.https.address.host, + port: server.https.address.port, + path: '/original', + rejectUnauthorized: false, + }, + + (res) => { + catchResponseUrl(res.responseUrl) + } + ) + + request.end() + + const { text } = await waitForClientRequest(request as any) + + // Intercepted redirect request (issued by "follow-redirects"). + const [redirectedRequest] = requestListener.mock.calls[0] + + expect(redirectedRequest.method).toBe('GET') + expect(redirectedRequest.url).toBe(server.https.url('/original')) + + // Response (original). + expect(catchResponseUrl).toHaveBeenCalledWith( + 'https://localhost:3000/redirected' + ) + expect(await text()).toBe('mocked response') +})