--- /dev/null
+/* eslint-env mocha */
+'use strict';
+
+const assert = require('assert');
+const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
+const Logger = require('../../lib/logger');
+const http = require('http');
+
+describe('Logger', function () {
+ let config, logger, scope, message;
+
+ beforeEach(function () {
+ config = {
+ nodeId: '3c100e84-9a7f-11ec-9b4e-0025905f714a',
+ logger: {},
+ };
+ logger = new Logger(config);
+ Object.keys(Logger.nullLogger).forEach((level) => sinon.stub(logger.backend, level));
+ scope = 'testScope';
+ message = 'message';
+ });
+ this.afterEach(function () {
+ sinon.restore();
+ });
+
+ it('logs a message', function () {
+ logger.info(scope, message, { baz: 'quux' }, { foo: 1 }, 'more other');
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes(message));
+ });
+
+ it('stubs missing levels', function () {
+ logger = new Logger(config);
+ assert.strictEqual(typeof logger.info, 'function');
+ });
+
+ it('logs BigInts', function () {
+ logger.info(scope, message, { aBigInteger: BigInt(2) });
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes('"2"'));
+ });
+
+ it('logs Errors', function () {
+ logger.error(scope, message, { e: new Error('an error') });
+ assert(logger.backend.error.called);
+ assert(logger.backend.error.args[0][0].includes('an error'));
+ });
+
+ it('covers config settings', function () {
+ config.logger.ignoreBelowLevel = 'info';
+ logger = new Logger(config);
+ logger.debug(scope, message, {});
+ assert(logger.backend.debug.notCalled);
+ });
+
+ it('covers config error', function () {
+ config.logger.ignoreBelowLevel = 'not a level';
+ try {
+ logger = new Logger(config);
+ assert.fail('expected RangeError here');
+ } catch (e) {
+ assert(e instanceof RangeError);
+ }
+ });
+
+ it('covers empty fields', function () {
+ logger.info();
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes('[unknown]'));
+ });
+
+ it('sanitizes', function () {
+ logger.dataSanitizers.push((data, sanitize = true) => {
+ let unclean = false;
+ const credentialLength = data && data.ctx && data.ctx.parsedBody && data.ctx.parsedBody.credential && data.ctx.parsedBody.credential.length;
+ if (credentialLength) {
+ unclean = true;
+ }
+ if (unclean && sanitize) {
+ data.ctx.parsedBody.credential = '*'.repeat(credentialLength);
+ }
+ return unclean;
+ });
+ logger.info(scope, message, {
+ ctx: {
+ parsedBody: {
+ credential: 'secret',
+ },
+ },
+ });
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes('******'));
+ });
+
+ it('logs http client requests', function () {
+ const incomingMessage = new http.IncomingMessage();
+ incomingMessage.method = 'GET';
+ incomingMessage.url = new URL('http://example.com/');
+ logger.info(scope, message, { incomingMessage });
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes('GET'));
+ assert(logger.backend.info.args[0][0].includes('http://example.com/'));
+ });
+
+ it('logs http client requests with scrubbed auth', function () {
+ const incomingMessage = Object.create(http.IncomingMessage.prototype);
+ incomingMessage.headers = {
+ authorization: 'Basic eW8=',
+ };
+ logger.info(scope, message, { incomingMessage });
+ assert(logger.backend.info.called);
+ assert(logger.backend.info.args[0][0].includes('****'));
+ });
+
+ it('logs http server responses', function () {
+ const serverResponse = Object.create(http.ServerResponse.prototype);
+ logger.info(scope, message, { serverResponse });
+ assert(logger.backend.info.args[0][0].includes('"statusCode":200'));
+ });
+
+ it('follows expected level ordering', function () {
+ const levels = Object.keys(Logger.nullLogger);
+ const expected = ['error', 'warn', 'info', 'log', 'debug'];
+ assert.deepStrictEqual(levels, expected);
+ });
+
+}); // Logger
\ No newline at end of file