From 22aab6de1d5dbe0b7e07ca853c55492ae7d53b5c Mon Sep 17 00:00:00 2001 From: Phred Lane Date: Fri, 27 Sep 2024 19:45:54 -0500 Subject: [PATCH] Unified Handler Tests (#2020) * cleaning up * added some debug * fixed typo * refactored tests to show they are almost identical * fixed rejection trigger * removed debug code * cleaning up * replaced hack with Mocha setting * removed unreferenced variable --- .mocharc.yml | 1 + test/helpers/handler-tests.js | 101 ++++++++++++++++ test/helpers/index.js | 8 +- test/unit/winston/exception-handler.test.js | 119 ++----------------- test/unit/winston/rejection-handler.test.js | 121 ++------------------ 5 files changed, 124 insertions(+), 226 deletions(-) create mode 100644 test/helpers/handler-tests.js diff --git a/.mocharc.yml b/.mocharc.yml index 2d4ed8a59..458b14f26 100644 --- a/.mocharc.yml +++ b/.mocharc.yml @@ -1,3 +1,4 @@ +allow-uncaught: true exclude: - test/helpers/scripts/*.js exit: true diff --git a/test/helpers/handler-tests.js b/test/helpers/handler-tests.js new file mode 100644 index 000000000..8dbfeeb98 --- /dev/null +++ b/test/helpers/handler-tests.js @@ -0,0 +1,101 @@ +const assume = require('assume'); + +const helpers = require('.'); +const winston = require('../../lib/winston'); + +module.exports = function ({ helper, listener, name, setup, toggleSetting, trigger }) { + describe('basics', function () { + var handler; + + beforeEach(function () { + handler = helpers[helper](); + }); + + it('has expected methods', function () { + assume(handler.handle).is.a('function'); + assume(handler.unhandle).is.a('function'); + assume(handler.getAllInfo).is.a('function'); + assume(handler.getProcessInfo).is.a('function'); + assume(handler.getOsInfo).is.a('function'); + assume(handler.getTrace).is.a('function'); + }); + + it(`new ${name}()`, function () { + assume(function () { + // eslint-disable-next-line no-new + new winston[name](); + }).throws(/Logger is required/); + }); + + it(`new ${name}(logger)`, function () { + var logger = winston.createLogger(); + var handler_ = new winston[name](logger); + assume(handler_.logger).equals(logger); + }); + + it('.getProcessInfo()', function () { + helpers.assertProcessInfo(handler.getProcessInfo()); + }); + + it('.getOsInfo()', function () { + helpers.assertOsInfo(handler.getOsInfo()); + }); + + it('.getTrace(new Error)', function () { + helpers.assertTrace(handler.getTrace(new Error())); + }); + + it('.getTrace()', function () { + helpers.assertTrace(handler.getTrace()); + }); + + it('.getAllInfo(undefined)', function () { + // eslint-disable-next-line no-undefined + handler.getAllInfo(undefined); + }); + }); + + describe('when error case is triggered', function () { + beforeEach(function () { + this.listeners = helpers[setup](); + }); + + afterEach(function () { + this.listeners.restore(); + }); + + it('.handle()', function (done) { + var msg = new Date().toString(); + var writeable = helpers.writeable(function (info) { + assume(info).is.an('object'); + assume(info.error).is.an('error'); + assume(info.error.message).equals(msg); + assume(info.message).includes(`${listener}: ${msg}`); + assume(info.stack).is.a('string'); + assume(info.process).is.an('object'); + assume(info.os).is.an('object'); + assume(info.trace).is.an('array'); + + done(); + }); + + var transport = new winston.transports.Stream({ stream: writeable }); + var handler = helpers[helper]({ + exitOnError: false, + transports: [transport] + }); + + assume(handler.catcher).is.a('undefined'); + + transport[toggleSetting] = true; + handler.handle(); + + assume(handler.catcher).is.a('function'); + assume(process.listeners(listener)).deep.equals([ + handler.catcher + ]); + + trigger(msg); + }); + }); +}; diff --git a/test/helpers/index.js b/test/helpers/index.js index fe51be9e3..7d68c086b 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -8,11 +8,9 @@ const assume = require('assume'), fs = require('fs'), - path = require('path'), through = require('through2'), spawn = require('child_process').spawn, stream = require('stream'), - util = require('util'), winston = require('../../lib/winston'), mockTransport = require('./mocks/mock-transport'); @@ -100,7 +98,7 @@ helpers.clearExceptions = function () { */ helpers.clearRejections = function () { var listeners = process.listeners('unhandledRejection'); - process.removeAllListeners('unhandledRejections'); + process.removeAllListeners('unhandledRejection'); return { restore: function () { @@ -125,9 +123,7 @@ helpers.throw = function (msg) { * @param {String} msg Error mesage to use */ helpers.reject = function (msg) { - return new Promise((resolve, reject) => { - reject(msg); - }); + return Promise.reject(msg); }; /** diff --git a/test/unit/winston/exception-handler.test.js b/test/unit/winston/exception-handler.test.js index 151e2931c..e10e7cd84 100644 --- a/test/unit/winston/exception-handler.test.js +++ b/test/unit/winston/exception-handler.test.js @@ -6,117 +6,18 @@ * */ -const stream = require('stream'); -const assume = require('assume'); -const mocha = require('mocha'); -const winston = require('../../../lib/winston'); +const baseHandlerTests = require('../../helpers/handler-tests'); const helpers = require('../../helpers'); -// -// This is an awful and fragile hack that -// needs to be changed ASAP. -// https://github.com/mochajs/mocha/issues/1985 -// -var _runTest = mocha.Runner.prototype.runTest; -mocha.Runner.prototype.runTest = function () { - this.allowUncaught = true; - _runTest.apply(this, arguments); -}; - describe('ExceptionHandler', function () { - this.timeout(5000); - - it('has expected methods', function () { - var handler = helpers.exceptionHandler(); - assume(handler.handle).is.a('function'); - assume(handler.unhandle).is.a('function'); - assume(handler.getAllInfo).is.a('function'); - assume(handler.getProcessInfo).is.a('function'); - assume(handler.getOsInfo).is.a('function'); - assume(handler.getTrace).is.a('function'); - }); - - it('new ExceptionHandler()', function () { - assume(function () { - new winston.ExceptionHandler(); - }).throws(/Logger is required/); - }); - - it('new ExceptionHandler(logger)', function () { - var logger = winston.createLogger(); - var handler = new winston.ExceptionHandler(logger); - assume(handler.logger).equals(logger); - }); - - it('.getProcessInfo()', function () { - var handler = helpers.exceptionHandler(); - helpers.assertProcessInfo(handler.getProcessInfo()); - }); - - it('.getOsInfo()', function () { - var handler = helpers.exceptionHandler(); - helpers.assertOsInfo(handler.getOsInfo()); - }); - - it('.getTrace(new Error)', function () { - var handler = helpers.exceptionHandler(); - helpers.assertTrace(handler.getTrace(new Error())); - }); - - it('.getTrace()', function () { - var handler = helpers.exceptionHandler(); - helpers.assertTrace(handler.getTrace()); - }); - - it('.handle()', function (done) { - var existing = helpers.clearExceptions(); - var writeable = new stream.Writable({ - objectMode: true, - write: function (info) { - assume(info).is.an('object'); - assume(info.error).is.an('error'); - assume(info.error.message).equals('wtf this error'); - assume(info.message).includes('uncaughtException: wtf this error'); - assume(info.stack).is.a('string'); - assume(info.process).is.an('object'); - assume(info.os).is.an('object'); - assume(info.trace).is.an('array'); - - existing.restore(); - done(); - } - }); - - var transport = new winston.transports.Stream({ stream: writeable }); - var handler = helpers.exceptionHandler({ - exitOnError: false, - transports: [transport] - }); - - assume(handler.catcher).equals(undefined); - - transport.handleExceptions = true; - handler.handle(); - - assume(handler.catcher).is.a('function'); - assume(process.listeners('uncaughtException')).deep.equals([ - handler.catcher - ]); - - helpers.throw('wtf this error'); - }); - - it('.getAllInfo(undefined)', function () { - var handler = helpers.exceptionHandler(); - // eslint-disable-next-line no-undefined - handler.getAllInfo(undefined); - }); - - after(function () { - // - // Restore normal `runTest` functionality - // so that we only affect the current suite. - // - mocha.Runner.prototype.runTest = _runTest; + this.timeout(100); + + baseHandlerTests({ + name: 'ExceptionHandler', + helper: 'exceptionHandler', + setup: 'clearExceptions', + listener: 'uncaughtException', + toggleSetting: 'handleExceptions', + trigger: msg => helpers.throw(msg) }); }); diff --git a/test/unit/winston/rejection-handler.test.js b/test/unit/winston/rejection-handler.test.js index 430e37e1a..40049d88f 100644 --- a/test/unit/winston/rejection-handler.test.js +++ b/test/unit/winston/rejection-handler.test.js @@ -6,119 +6,18 @@ * */ -const stream = require('stream'); -const assume = require('assume'); -const mocha = require('mocha'); -const winston = require('../../../lib/winston'); +const baseHandlerTests = require('../../helpers/handler-tests'); const helpers = require('../../helpers'); -// -// This is an awful and fragile hack that -// needs to be changed ASAP. -// https://github.com/mochajs/mocha/issues/1985 -// -var _runTest = mocha.Runner.prototype.runTest; -mocha.Runner.prototype.runTest = function () { - this.allowUncaught = true; - _runTest.apply(this, arguments); -}; - describe('UnhandledRejectionHandler', function () { - this.timeout(5000); - - it('has expected methods', function () { - var handler = helpers.rejectionHandler(); - assume(handler.handle).is.a('function'); - assume(handler.unhandle).is.a('function'); - assume(handler.getAllInfo).is.a('function'); - assume(handler.getProcessInfo).is.a('function'); - assume(handler.getOsInfo).is.a('function'); - assume(handler.getTrace).is.a('function'); - }); - - it('new RejectionHandler()', function () { - assume(function () { - new winston.RejectionHandler(); - }).throws(/Logger is required/); - }); - - it('new RejectionHandler(logger)', function () { - var logger = winston.createLogger(); - var handler = new winston.RejectionHandler(logger); - assume(handler.logger).equals(logger); - }); - - it('.getProcessInfo()', function () { - var handler = helpers.rejectionHandler(); - helpers.assertProcessInfo(handler.getProcessInfo()); - }); - - it('.getOsInfo()', function () { - var handler = helpers.rejectionHandler(); - helpers.assertOsInfo(handler.getOsInfo()); - }); - - it('.getTrace(new Error)', function () { - var handler = helpers.rejectionHandler(); - helpers.assertTrace(handler.getTrace(new Error())); - }); - - it('.getTrace()', function () { - var handler = helpers.rejectionHandler(); - helpers.assertTrace(handler.getTrace()); - }); - - it('.handle()', function (done) { - process.removeAllListeners('unhandledRejection'); - var existing = helpers.clearRejections(); - var writeable = new stream.Writable({ - objectMode: true, - write: function (info) { - assume(info).is.an('object'); - assume(info.error).is.an('error'); - assume(info.rejection).is.true(); - assume(info.error.message).equals('wtf this rejection'); - assume(info.message).includes('unhandledRejection: wtf this rejection'); - assume(info.stack).is.a('string'); - assume(info.process).is.an('object'); - assume(info.os).is.an('object'); - assume(info.trace).is.an('array'); - - existing.restore(); - done(); - } - }); - - var transport = new winston.transports.Stream({ stream: writeable }); - var handler = helpers.rejectionHandler({ - exitOnError: false, - transports: [transport] - }); - - assume(handler.catcher).equals(undefined); - - transport.handleRejections = true; - handler.handle(); - - assume(handler.catcher).is.a('function'); - assume(process.listeners('unhandledRejection')).deep.equals([ - handler.catcher - ]); - - helpers.reject(new Error('wtf this rejection')); - }); - - it('.getAllInfo(undefined)', function () { - var handler = helpers.rejectionHandler(); - // eslint-disable-next-line no-undefined - handler.getAllInfo(undefined); - }); - - after(function () { - // - // Restore normal `runTest` functionality - // so that we only affect the current suite. - // - mocha.Runner.prototype.runTest = _runTest; + this.timeout(100); + + baseHandlerTests({ + name: 'RejectionHandler', + helper: 'rejectionHandler', + setup: 'clearRejections', + listener: 'unhandledRejection', + toggleSetting: 'handleRejections', + trigger: msg => helpers.reject(new Error(msg)) }); });