From 5dce53d4e2ef9e11e8cdf99d104b4baecf9446c1 Mon Sep 17 00:00:00 2001 From: Phillip Wirth Date: Fri, 20 Dec 2024 16:00:16 +0100 Subject: [PATCH] added complicated test to reach 100% --- .../helpers/request-logger-middleware.spec.ts | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 apps/server/src/apps/helpers/request-logger-middleware.spec.ts diff --git a/apps/server/src/apps/helpers/request-logger-middleware.spec.ts b/apps/server/src/apps/helpers/request-logger-middleware.spec.ts new file mode 100644 index 00000000000..cfc887b5134 --- /dev/null +++ b/apps/server/src/apps/helpers/request-logger-middleware.spec.ts @@ -0,0 +1,99 @@ +import { createRequestLoggerMiddleware } from './request-logger-middleware'; +import { Configuration } from '@hpi-schul-cloud/commons/lib'; +import { Logger } from '@nestjs/common'; +import { Request, Response, NextFunction } from 'express'; + +jest.mock('@hpi-schul-cloud/commons/lib', () => { + return { + Configuration: { + get: jest.fn(), + }, + }; +}); + +describe('RequestLoggerMiddleware', () => { + let mockRequest: Partial; + let mockResponse: Partial; + let nextFunction: NextFunction; + let loggerSpy: jest.SpyInstance; + let errorLoggerSpy: jest.SpyInstance; + + beforeEach(() => { + mockRequest = { + method: 'GET', + originalUrl: '/test', + }; + + mockResponse = { + statusCode: 200, + get: jest.fn(), + on: jest.fn(), + }; + + nextFunction = jest.fn(); + + loggerSpy = jest.spyOn(Logger.prototype, 'log'); + errorLoggerSpy = jest.spyOn(Logger.prototype, 'error'); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should call next() when logging is disabled', () => { + jest.spyOn(Configuration, 'get').mockReturnValue(false); + + const middleware = createRequestLoggerMiddleware(); + middleware(mockRequest as Request, mockResponse as Response, nextFunction); + + expect(nextFunction).toHaveBeenCalled(); + expect(mockResponse.on).not.toHaveBeenCalled(); + }); + + it('should log request details when logging is enabled', () => { + jest.spyOn(Configuration, 'get').mockReturnValue(true); + + jest.spyOn(process, 'hrtime').mockReturnValueOnce([0, 0]); + jest.spyOn(mockResponse, 'get').mockImplementation().mockReturnValue('100'); + + // eslint-disable-next-line @typescript-eslint/ban-types + let finishCallback: Function | undefined; + // eslint-disable-next-line @typescript-eslint/ban-types + mockResponse.on = jest.fn().mockImplementation((event: string, callback: Function) => { + finishCallback = callback; + }); + + const middleware = createRequestLoggerMiddleware(); + middleware(mockRequest as Request, mockResponse as Response, nextFunction); + + expect(nextFunction).toHaveBeenCalled(); + expect(mockResponse.on).toHaveBeenCalledWith('finish', expect.any(Function)); + + // Simulate response finish + jest.spyOn(process, 'hrtime').mockReturnValueOnce([1, 0]); + + // Make sure callback was set before calling it + expect(finishCallback).toBeDefined(); + finishCallback?.(); + + expect(loggerSpy).toHaveBeenCalledWith('GET /test 200 1000ms 100'); + }); + + it('should handle errors during logging', () => { + jest.spyOn(Configuration, 'get').mockReturnValue(true); + // eslint-disable-next-line @typescript-eslint/ban-types + mockResponse.on = jest.fn().mockImplementation((event: string, callback: Function) => { + callback(); + }); + + // Force an error by making response.get throw + mockResponse.get = jest.fn().mockImplementation(() => { + throw new Error('Test error'); + }); + + const middleware = createRequestLoggerMiddleware(); + middleware(mockRequest as Request, mockResponse as Response, nextFunction); + + expect(errorLoggerSpy).toHaveBeenCalledWith('unable to write accesslog', Error('Test error')); + }); +});