diff --git a/test/unit/fix-request-body.spec.ts b/test/unit/fix-request-body.spec.ts new file mode 100644 index 00000000..6ea56ba0 --- /dev/null +++ b/test/unit/fix-request-body.spec.ts @@ -0,0 +1,66 @@ +import { ClientRequest } from 'http'; +import * as querystring from 'querystring'; + +import { fixRequestBody } from '../../src/handlers/fix-request-body'; +import type { Request } from '../../src/types'; + +const fakeProxyRequest = () => { + const proxyRequest = new ClientRequest('http://some-host'); + proxyRequest.emit = jest.fn(); + + return proxyRequest; +}; + +describe('fixRequestBody', () => { + it('should not write when body is undefined', () => { + const proxyRequest = fakeProxyRequest(); + + jest.spyOn(proxyRequest, 'setHeader'); + jest.spyOn(proxyRequest, 'write'); + + fixRequestBody(proxyRequest, { body: undefined } as Request); + + expect(proxyRequest.setHeader).not.toHaveBeenCalled(); + expect(proxyRequest.write).not.toHaveBeenCalled(); + }); + + it('should not write when body is empty', () => { + const proxyRequest = fakeProxyRequest(); + + jest.spyOn(proxyRequest, 'setHeader'); + jest.spyOn(proxyRequest, 'write'); + + fixRequestBody(proxyRequest, { body: {} } as Request); + + expect(proxyRequest.setHeader).not.toHaveBeenCalled(); + expect(proxyRequest.write).not.toHaveBeenCalled(); + }); + + it('should write when body is not empty and Content-Type is application/json', () => { + const proxyRequest = fakeProxyRequest(); + proxyRequest.setHeader('content-type', 'application/json; charset=utf-8'); + + jest.spyOn(proxyRequest, 'setHeader'); + jest.spyOn(proxyRequest, 'write'); + + fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as Request); + + const expectedBody = JSON.stringify({ someField: 'some value' }); + expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length); + expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody); + }); + + it('should write when body is not empty and Content-Type is application/x-www-form-urlencoded', () => { + const proxyRequest = fakeProxyRequest(); + proxyRequest.setHeader('content-type', 'application/x-www-form-urlencoded'); + + jest.spyOn(proxyRequest, 'setHeader'); + jest.spyOn(proxyRequest, 'write'); + + fixRequestBody(proxyRequest, { body: { someField: 'some value' } } as Request); + + const expectedBody = querystring.stringify({ someField: 'some value' }); + expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length); + expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody); + }); +}); diff --git a/test/unit/response-interceptor.spec.ts b/test/unit/response-interceptor.spec.ts new file mode 100644 index 00000000..09bfc548 --- /dev/null +++ b/test/unit/response-interceptor.spec.ts @@ -0,0 +1,63 @@ +import { IncomingMessage, ServerResponse } from 'http'; + +import { responseInterceptor } from '../../src/handlers/response-interceptor'; + +const fakeProxyResponse = () => { + const httpIncomingMessage = new IncomingMessage(null); + httpIncomingMessage._read = () => ({}); + return httpIncomingMessage; +}; + +const fakeResponse = () => { + const httpIncomingMessage = fakeProxyResponse(); + + const response = new ServerResponse(httpIncomingMessage); + response.setHeader = jest.fn(); + response.write = jest.fn(); + response.end = jest.fn(); + + return response; +}; + +const waitInterceptorHandler = (ms = 1): Promise => + new Promise((resolve) => setTimeout(resolve, ms)); + +describe('responseInterceptor', () => { + it('should write body on end proxy event', async () => { + const httpIncomingMessage = fakeProxyResponse(); + const response = fakeResponse(); + + responseInterceptor(async () => JSON.stringify({ someField: '' }))( + httpIncomingMessage, + null, + response + ); + + httpIncomingMessage.emit('end'); + await waitInterceptorHandler(); + + const expectedBody = JSON.stringify({ someField: '' }); + expect(response.setHeader).toHaveBeenCalledWith('content-length', expectedBody.length); + expect(response.write).toHaveBeenCalledWith(Buffer.from(expectedBody)); + expect(response.end).toHaveBeenCalledWith(); + }); + + it('should end with error when receive a proxy error event', async () => { + const httpIncomingMessage = fakeProxyResponse(); + const response = fakeResponse(); + + responseInterceptor(async () => JSON.stringify({ someField: '' }))( + httpIncomingMessage, + null, + response + ); + + httpIncomingMessage.emit('error', new Error('some error meessage')); + + expect(response.setHeader).not.toHaveBeenCalled(); + expect(response.write).not.toHaveBeenCalled(); + expect(response.end).toHaveBeenCalledWith( + 'Error fetching proxied request: some error meessage' + ); + }); +});