import { jest } from '@jest/globals' import { APIGatewayProxyEvent, Context } from 'aws-lambda' import { expect as c_expect } from 'chai' import request from 'supertest' import Globals from '../../../../src/Globals.js' import Proxy from '../../../../src/Server/lib/container/Proxy.js' import { defaultUrl } from '../../../Test.utils.js' describe('Proxy configs', () => { // @ts-ignore let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) beforeAll(() => { // @ts-ignore mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) }) afterAll(() => { mockExit.mockRestore() }) beforeEach(() => { mockExit.mockReset() }) test('Empty config url & unload with error', async () => { const proxy = new Proxy({ routes: [] }, async () => {}) await proxy.load() await proxy.unload('Error') expect(mockExit).toBeCalledWith(1) }) test('Simple port config', async () => { const proxy = new Proxy({ routes: [], port: 56562 }, async () => {}) await proxy.load() await proxy.unload() expect(mockExit).toBeCalledWith(0) }) test('Simple timeout config', async () => { const proxy = new Proxy({ routes: [], timeout: 1000 }, async () => {}) await proxy.load() await proxy.unload() expect(mockExit).toBeCalledWith(0) }) test('Simple cors config', async () => { const proxy = new Proxy( { routes: [], cors: { origin: '*', headers: ['Authorization'], allowCredentials: true, }, }, async () => {} ) await proxy.load() await proxy.unload() expect(mockExit).toBeCalledWith(0) }) test('Empty cors config', async () => { const proxy = new Proxy( { routes: [], cors: {}, }, async () => {} ) await proxy.load() await proxy.unload() expect(mockExit).toBeCalledWith(0) }) }) describe('Proxy behaviour', () => { // @ts-ignore let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) beforeAll(() => { // @ts-ignore mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) }) afterAll(() => { mockExit.mockRestore() }) beforeEach(() => { mockExit.mockReset() }) test('Stop twice', async () => { const proxy = new Proxy({ routes: [] }, async () => {}) await proxy.load() await Promise.all([proxy.unload('Error'), proxy.unload('Error')]) expect(mockExit).toHaveBeenCalledTimes(1) expect(mockExit).toBeCalledWith(1) }) }) describe('Proxy routing', () => { // @ts-ignore let mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) beforeAll(() => { // @ts-ignore mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {}) }) afterAll(() => { mockExit.mockRestore() }) beforeEach(() => { mockExit.mockReset() }) test('Health & Default handler', async () => { let count = 0 const proxy = new Proxy( { routes: [] }, async (event: APIGatewayProxyEvent, context: Context) => { count++ context.succeed({ body: JSON.stringify({ name: '123' }), statusCode: 200, }) } ) await proxy.load() // Health check const res = await request(defaultUrl) .get(Globals.Listener_HTTP_DefaultHealthCheckRoute) .expect('Content-Type', 'text/html; charset=utf-8') .expect(200) c_expect(res.text).to.be.equals('Healthy!') // Generic handler const resG = await request(defaultUrl) .get(`/abc`) .expect('Content-Type', 'application/json; charset=utf-8') .expect(200) c_expect(resG.body).to.be.deep.equals({ name: '123' }) // Expected count c_expect(count).to.be.equals(1) // Unload await proxy.unload('Error') expect(mockExit).toHaveBeenCalledTimes(1) expect(mockExit).toBeCalledWith(1) }) test('Proxy on custom port', async () => { let count = 0 const port = 56542 const url = defaultUrl.replace(String(Globals.Listener_HTTP_DefaultPort), String(port)) const proxy = new Proxy( { routes: [], port }, async (event: APIGatewayProxyEvent, context: Context) => { count++ context.succeed({ body: JSON.stringify({ name: '123' }), statusCode: 200, }) } ) await proxy.load() // Health check const res = await request(url) .get(Globals.Listener_HTTP_DefaultHealthCheckRoute) .expect('Content-Type', 'text/html; charset=utf-8') .expect(200) c_expect(res.text).to.be.equals('Healthy!') // Generic handler const resG = await request(url) .get(`/abc`) .expect('Content-Type', 'application/json; charset=utf-8') .expect(200) c_expect(resG.body).to.be.deep.equals({ name: '123' }) // Expected count c_expect(count).to.be.equals(1) // Unload await proxy.unload() expect(mockExit).toHaveBeenCalledTimes(1) expect(mockExit).toBeCalledWith(0) }) test('Proxy does timeout', async () => { let count = 0 const timeout = 1000 const proxy = new Proxy( { routes: [], timeout }, async (event: APIGatewayProxyEvent, context: Context) => { count++ setTimeout(() => { context.succeed({ body: JSON.stringify({ name: '123' }), statusCode: 200, }) }, timeout * 2) } ) await proxy.load() // Health check const res = await request(defaultUrl) .get(Globals.Listener_HTTP_DefaultHealthCheckRoute) .expect('Content-Type', 'text/html; charset=utf-8') .expect(200) c_expect(res.text).to.be.equals('Healthy!') // Generic handler let err: any = null try { await request(defaultUrl) .get(`/abc`) .expect('Content-Type', 'application/json; charset=utf-8') .expect(200) } catch (e) { err = e } c_expect(err?.message).to.be.equals('socket hang up') // Expected count c_expect(count).to.be.equals(1) // Unload await proxy.unload('Error') expect(mockExit).toHaveBeenCalledTimes(1) expect(mockExit).toBeCalledWith(1) // return new Promise(resolve => { setTimeout(resolve, timeout * 2) }) }) test('Proxy respects cors', async () => { let count = 0 const proxy = new Proxy( { routes: [], cors: { origin: '*', headers: ['Authorization'], allowCredentials: true, }, }, async (event: APIGatewayProxyEvent, context: Context) => { count++ context.succeed({ body: JSON.stringify({ name: '123' }), statusCode: 200, }) } ) await proxy.load() // White-listed header is allowed const resWH = await request(defaultUrl).options(`/abc`).set('Authorization', '123').expect(204) c_expect(resWH.header['access-control-allow-origin']).to.equal('*') c_expect(resWH.header['access-control-allow-credentials']).to.equal('true') c_expect(resWH.header['access-control-allow-headers']).to.equal('Authorization') // Non white-listed header is allowed const resNWH = await request(defaultUrl) .options(`/abc`) .set('2Authorization2', '123') .expect(204) c_expect(resNWH.header['access-control-allow-origin']).to.equal('*') c_expect(resNWH.header['access-control-allow-credentials']).to.equal('true') c_expect(resNWH.header['access-control-allow-headers']).to.equal('Authorization') // Expected count c_expect(count).to.be.equals(0) // Unload await proxy.unload() expect(mockExit).toHaveBeenCalledTimes(1) expect(mockExit).toBeCalledWith(0) }) }) export {}