http-logger.spec.ts 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
  2. // Mock pino-http before importing
  3. vi.mock('pino-http', () => {
  4. const pinoHttp = vi.fn((_opts: unknown) => {
  5. return (_req: unknown, _res: unknown, next: () => void) => next();
  6. });
  7. return { default: pinoHttp };
  8. });
  9. // Mock logger-factory
  10. vi.mock('./logger-factory', () => ({
  11. loggerFactory: vi.fn(() => ({
  12. level: 'info',
  13. info: vi.fn(),
  14. debug: vi.fn(),
  15. warn: vi.fn(),
  16. error: vi.fn(),
  17. trace: vi.fn(),
  18. fatal: vi.fn(),
  19. })),
  20. }));
  21. describe('createHttpLoggerMiddleware', () => {
  22. const originalEnv = process.env;
  23. beforeEach(() => {
  24. process.env = { ...originalEnv };
  25. vi.resetModules();
  26. });
  27. afterEach(() => {
  28. process.env = originalEnv;
  29. });
  30. it('returns an Express-compatible middleware function', async () => {
  31. const { createHttpLoggerMiddleware } = await import('./http-logger');
  32. const middleware = await createHttpLoggerMiddleware();
  33. expect(typeof middleware).toBe('function');
  34. });
  35. it('uses "express" as the default namespace', async () => {
  36. const { loggerFactory } = await import('./logger-factory');
  37. const { createHttpLoggerMiddleware } = await import('./http-logger');
  38. await createHttpLoggerMiddleware();
  39. expect(loggerFactory).toHaveBeenCalledWith('express');
  40. });
  41. it('accepts a custom namespace', async () => {
  42. const { loggerFactory } = await import('./logger-factory');
  43. const { createHttpLoggerMiddleware } = await import('./http-logger');
  44. await createHttpLoggerMiddleware({ namespace: 'custom-http' });
  45. expect(loggerFactory).toHaveBeenCalledWith('custom-http');
  46. });
  47. it('passes autoLogging options to pino-http', async () => {
  48. const pinoHttp = (await import('pino-http')).default;
  49. const { createHttpLoggerMiddleware } = await import('./http-logger');
  50. const ignoreFn = (req: { url?: string }) =>
  51. req.url?.startsWith('/_next/') ?? false;
  52. await createHttpLoggerMiddleware({ autoLogging: { ignore: ignoreFn } });
  53. expect(pinoHttp).toHaveBeenCalledWith(
  54. expect.objectContaining({
  55. autoLogging: { ignore: ignoreFn },
  56. }),
  57. );
  58. });
  59. it('applies morganLikeFormatOptions in development mode', async () => {
  60. process.env.NODE_ENV = 'development';
  61. const pinoHttp = (await import('pino-http')).default;
  62. const { createHttpLoggerMiddleware } = await import('./http-logger');
  63. await createHttpLoggerMiddleware();
  64. expect(pinoHttp).toHaveBeenCalledWith(
  65. expect.objectContaining({
  66. customSuccessMessage: expect.any(Function),
  67. customErrorMessage: expect.any(Function),
  68. customLogLevel: expect.any(Function),
  69. }),
  70. );
  71. });
  72. it('does not apply morganLikeFormatOptions in production mode', async () => {
  73. process.env.NODE_ENV = 'production';
  74. const pinoHttp = (await import('pino-http')).default;
  75. const { createHttpLoggerMiddleware } = await import('./http-logger');
  76. await createHttpLoggerMiddleware();
  77. const callArgs = (pinoHttp as ReturnType<typeof vi.fn>).mock
  78. .calls[0][0] as Record<string, unknown>;
  79. expect(callArgs.customSuccessMessage).toBeUndefined();
  80. expect(callArgs.customErrorMessage).toBeUndefined();
  81. expect(callArgs.customLogLevel).toBeUndefined();
  82. });
  83. });