diff --git a/packages/core/lib/rest/http-server/response.ts b/packages/core/lib/rest/http-server/response.ts index f9949d1..c1d43c4 100644 --- a/packages/core/lib/rest/http-server/response.ts +++ b/packages/core/lib/rest/http-server/response.ts @@ -86,13 +86,7 @@ export class Response { /** * Set the status code of the response */ - if (!this.statusCode && method === 'POST') { - res.status(HttpStatus.CREATED); - } else if (this.statusCode) { - res.status(this.statusCode); - } else { - res.status(HttpStatus.OK); - } + res.status(this.statusCode ?? (method === 'POST' ? HttpStatus.CREATED : HttpStatus.OK)); /** * Set the headers diff --git a/packages/core/tests/unit/rest/http-server/response.test.ts b/packages/core/tests/unit/rest/http-server/response.test.ts new file mode 100644 index 0000000..be227d6 --- /dev/null +++ b/packages/core/tests/unit/rest/http-server/response.test.ts @@ -0,0 +1,110 @@ +import { Response } from '../../../../lib/rest/http-server/response'; +import { HttpStatus } from '../../../../lib/rest/http-server/status-codes'; +import { StreamableFile } from '../../../../lib/rest/http-server/streamable-file'; + +describe('Response', () => { + let response: Response; + + beforeEach(() => { + response = new Response(); + }); + + describe('status', () => { + it('should set status code and return response instance', () => { + const result = response.status(HttpStatus.CREATED); + expect(result).toBe(response); + expect((response as any).statusCode).toBe(HttpStatus.CREATED); + }); + }); + + describe('header', () => { + it('should set header and return response instance', () => { + const result = response.header('Content-Type', 'application/json'); + expect(result).toBe(response); + expect((response as any).responseHeaders.get('Content-Type')).toBe('application/json'); + }); + }); + + describe('type', () => { + it('should set content type header for json', () => { + const result = response.type('json'); + expect(result).toBe(response); + expect((response as any).responseHeaders.get('Content-Type')).toBe('application/json'); + }); + + it('should set content type header for text', () => { + response.type('text'); + expect((response as any).responseHeaders.get('Content-Type')).toBe('text/plain'); + }); + }); + + describe('body', () => { + it('should set json body and content type', () => { + const data = { message: 'test' }; + response.body(data); + expect((response as any).bodyData).toBe(JSON.stringify(data)); + expect((response as any).responseHeaders.get('Content-Type')).toBe('application/json'); + }); + + it('should set plain body without transformation', () => { + response.body('plain text'); + expect((response as any).bodyData).toBe('plain text'); + }); + }); + + describe('text', () => { + it('should set text body with correct content type', () => { + response.text('hello world'); + expect((response as any).bodyData).toBe('hello world'); + expect((response as any).responseHeaders.get('Content-Type')).toBe('text/plain'); + }); + }); + + describe('json', () => { + it('should set json body with correct content type', () => { + const data = { message: 'test' }; + response.json(data); + expect((response as any).bodyData).toBe(JSON.stringify(data)); + expect((response as any).responseHeaders.get('Content-Type')).toBe('application/json'); + }); + }); + + describe('html', () => { + it('should set html body with correct content type', () => { + response.html('
unit test
'); + expect((response as any).bodyData).toBe('unit test
'); + expect((response as any).responseHeaders.get('Content-Type')).toBe('text/html'); + }); + }); + + describe('notFound', () => { + it('should set 404 status code', () => { + response.notFound(); + expect((response as any).statusCode).toBe(HttpStatus.NOT_FOUND); + }); + }); + + describe('redirect', () => { + it('should set redirect status and location header', () => { + const redirectUrl = '/unit-test'; + response.redirect(redirectUrl); + expect((response as any).statusCode).toBe(HttpStatus.FOUND); + expect((response as any).responseHeaders.get('location')).toBe(redirectUrl); + }); + }); + + describe('reply', () => { + it('should properly set status, headers and body', () => { + const mockReq = { method: 'GET' }; + + response + .status(HttpStatus.OK) + .header('Content-Type', 'application/json') + .json({ message: 'success' }); + + expect((response as any).statusCode).toBe(HttpStatus.OK); + expect((response as any).responseHeaders.get('Content-Type')).toBe('application/json'); + expect((response as any).bodyData).toBe(JSON.stringify({ message: 'success' })); + }); + }); +}); \ No newline at end of file diff --git a/packages/core/tests/unit/rest/http-server/server.test.ts b/packages/core/tests/unit/rest/http-server/server.test.ts new file mode 100644 index 0000000..7f7c15a --- /dev/null +++ b/packages/core/tests/unit/rest/http-server/server.test.ts @@ -0,0 +1,122 @@ +import { MiddlewareNext } from 'hyper-express'; +import { IntentMiddleware } from '../../../../lib/rest'; +import { HyperServer } from '../../../../lib/rest/http-server/server'; +import { Request, Response } from '@intentjs/hyper-express'; +import { ConfigService } from '../../../../lib/config'; + +jest.mock('../../../../lib/config', () => ({ + ConfigService: { + get: (key: string) => ({}) + } +})); + +describe('HyperServer', () => { + let server: HyperServer; + + beforeEach(() => { + server = new HyperServer(); + }); + + describe('useGlobalMiddlewares', () => { + it('should register global middleware', async () => { + const mockMiddleware = async (req: Request, res: Response, next: MiddlewareNext) => {}; + + server.useGlobalMiddlewares([mockMiddleware as unknown as IntentMiddleware]); + + expect(server.globalMiddlewares).toHaveLength(1); + expect(server.globalMiddlewares[0]).toBe(mockMiddleware); + }); + }); + + describe('build', () => { + it('should register GET route', async () => { + const mockRoute = { + method: 'GET', + path: '/test', + httpHandler: jest.fn() + }; + + const routeMiddlewares = new Map(); + routeMiddlewares.set('GET:/test', []); + + server.useRouteMiddlewares(routeMiddlewares); + await server.build([mockRoute], {}); + + const routes = ((server as any).hyper).routes; + + expect(routes).toMatchObject({ + get: { + '/test': expect.objectContaining({ + path: '/test', + method: 'GET', + }) + }, + post: {}, + put: {}, + del: {} + }); + }); + + it('should register different HTTP method routes', async () => { + const mockRoutes = [ + { + method: 'GET', + path: '/test', + httpHandler: jest.fn() + }, + { + method: 'POST', + path: '/test', + httpHandler: jest.fn() + }, + { + method: 'PUT', + path: '/test', + httpHandler: jest.fn() + }, + { + method: 'DELETE', + path: '/test', + httpHandler: jest.fn() + } + ]; + + const routeMiddlewares = new Map(); + routeMiddlewares.set('GET:/test', []); + routeMiddlewares.set('POST:/test', []); + routeMiddlewares.set('PUT:/test', []); + routeMiddlewares.set('DELETE:/test', []); + + server.useRouteMiddlewares(routeMiddlewares); + await server.build(mockRoutes, {}); + + const routes = ((server as any).hyper).routes; + expect(routes).toMatchObject({ + get: { + '/test': expect.objectContaining({ + path: '/test', + method: 'GET', + }) + }, + post: { + '/test': expect.objectContaining({ + path: '/test', + method: 'POST', + }) + }, + put: { + '/test': expect.objectContaining({ + path: '/test', + method: 'PUT', + }) + }, + del: { + '/test': expect.objectContaining({ + path: '/test', + method: 'DELETE', + }) + } + }); + }); + }); +}); \ No newline at end of file