import { FastifyInstance } from 'fastify'; import { describe, it, expect, beforeAll, afterAll, vi, } from 'vitest'; import { constants } from 'http2'; import { createServer } from '../src/server'; import { addRoutes } from '../src/routes'; import { AdderServiceImpl, ArgumentOutOfRangeError, InvalidArgumentTypeError, } from '../src/modules/adder'; describe('add', () => { let server: FastifyInstance; const body = { a: 1, b: 2 }; beforeAll(() => { server = createServer(); addRoutes(server); }); afterAll(async () => { await server.close(); }); it('returns result when successful', async () => { const response = await server .inject() .post('/add') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_OK); }); it('returns error when given invalid inputs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new InvalidArgumentTypeError('Invalid input'); }); const response = await server .inject() .post('/add') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_BAD_REQUEST); }); it('returns error when given out-of-range inputs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new ArgumentOutOfRangeError('Out of range'); }); const response = await server .inject() .post('/add') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_BAD_REQUEST); }); it('returns error when an unexpected error occurs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new Error('Unexpected error'); }); const response = await server .inject() .post('/add') .body({ a: 1, b: 2 }) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_INTERNAL_SERVER_ERROR); }); }); describe('subtract', () => { let server: FastifyInstance; const body = { a: 1, b: 2 }; beforeAll(() => { server = createServer(); addRoutes(server); }); afterAll(async () => { await server.close(); }); it('returns result when successful', async () => { const response = await server .inject() .post('/subtract') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_OK); }); it('returns error when given invalid inputs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new InvalidArgumentTypeError('Invalid input'); }); const response = await server .inject() .post('/subtract') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_BAD_REQUEST); }); it('returns error when given out-of-range inputs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new ArgumentOutOfRangeError('Out of range'); }); const response = await server .inject() .post('/subtract') .body(body) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_BAD_REQUEST); }); it('returns error when an unexpected error occurs', async () => { vi.spyOn(AdderServiceImpl.prototype, 'addNumbers').mockImplementationOnce(() => { throw new Error('Unexpected error'); }); const response = await server .inject() .post('/subtract') .body({ a: 1, b: 2 }) .headers({ 'Accept': 'application/json', }); expect(response.statusCode).toBe(constants.HTTP_STATUS_INTERNAL_SERVER_ERROR); }); });