import { LogProvider } from '../services/log-provider'; import { Request } from '../interfaces'; import { RequestLogger } from './request-logger'; import { RequestLoggerOpts } from './request-logger'; import { Response } from '../interfaces'; import { of } from 'rxjs'; const request: Request = { path: '/foo/bar', method: 'GET', remoteAddr: '::1', httpVersion: '1.2', timestamp: Date.now() }; const response: Response = { // eslint-disable-next-line @typescript-eslint/naming-convention headers: { 'Content-Length': '20' }, statusCode: 301 }; const error: Response = { body: JSON.stringify({ error: 'xxx', stack: 'y' }), // eslint-disable-next-line @typescript-eslint/naming-convention headers: { 'Content-Length': '20' }, statusCode: 500 }; describe('RequestLogger unit tests', () => { test('logs errors to console', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (_stuff) => {}, warn: (_stuff) => {}, error: (logLine) => { expect(logLine).toContain('xxx'); done(); } }; const opts: RequestLoggerOpts = { colorize: false, format: 'common' }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response: error })).subscribe(); }); test('silent mode logs nothing', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (_stuff) => {}, warn: (_stuff) => {}, error: (_logLine) => {} }; jest.spyOn(log, 'info'); const opts: RequestLoggerOpts = { silent: true }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response })).subscribe(() => { // eslint-disable-next-line @typescript-eslint/unbound-method expect(log.info).not.toBeCalled(); done(); }); }); test('"common" format correctly logs messages', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (logLine) => { expect(logLine).toMatch( /^::1 - - \[.*\] "GET \/foo\/bar HTTP\/1.2" 301 20$/ ); done(); }, warn: (_stuff) => {}, error: (_stuff) => {} }; const opts: RequestLoggerOpts = { colorize: false, format: 'common' }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response })).subscribe(); }); test('"dev" format correctly logs messages', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (logLine) => { expect(logLine).toMatch(/^GET \/foo\/bar 301 [0-9]+ms - 20$/); done(); }, warn: (_stuff) => {}, error: (_stuff) => {} }; const opts: RequestLoggerOpts = { colorize: false, format: 'dev' }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response })).subscribe(); }); test('"short" format correctly logs messages', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (logLine) => { expect(logLine).toMatch( /^::1 - GET \/foo\/bar HTTP\/1.2 301 20 - [0-9]+ms$/ ); done(); }, warn: (_stuff) => {}, error: (_stuff) => {} }; const opts: RequestLoggerOpts = { colorize: false, format: 'short' }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response })).subscribe(); }); test('"tiny" format correctly logs messages', (done) => { const log: LogProvider = { canColorize: () => false, log: (_stuff) => {}, info: (logLine) => { expect(logLine).toMatch(/^GET \/foo\/bar 301 20 - [0-9]+ms$/); done(); }, warn: (_stuff) => {}, error: (_stuff) => {} }; const opts: RequestLoggerOpts = { colorize: false, format: 'tiny' }; const logger = new RequestLogger(log, opts); logger.postcatch(of({ request, response })).subscribe(); }); });