"use strict";
/**
* Contains hacks for test run.
*
* @module
*/
const util = require("util");
const _ = require("lodash");
const LOG = require("glace-utils").logger;
const Mocha = require("mocha");
const Pending = require("mocha/lib/pending");
const mochaUtils = require("mocha/lib/utils");
mochaUtils.isString = _.isString; // monkey patch mocha to define instance of `String` as string not as object
const CONF = require("./config");
const utils = require("./utils");
/**
* Patches original `Mocha.Runner.prototype.uncaught` in order to process
* uncaught exceptions flexible.
* @ignore
*/
module.exports.suppressMochaUncaught = () => {
Mocha.Runner.prototype.uncaught = function (err) {
LOG.error(util.format("UNCAUGHT EXCEPTION", err));
if (CONF.session.uncaughtException === "fail") {
utils.accountError("Uncaught exception", err);
}
};
};
/**
* Patches mocha runner to allow multiple independent `after`-calls.
*/
Mocha.Runner.prototype.hook = function(name, fn) {
var suite = this.suite;
var hooks = suite.getHooks(name);
var self = this;
function next(i) {
var hook = hooks[i];
if (!hook) {
return fn();
}
self.currentRunnable = hook;
if (name === "beforeAll") {
hook.ctx.currentTest = hook.parent.tests[0];
} else if (name === "afterAll") {
hook.ctx.currentTest = hook.parent.tests[hook.parent.tests.length - 1];
} else {
hook.ctx.currentTest = self.test;
}
self.emit(Mocha.Runner.constants.EVENT_HOOK_BEGIN, hook);
if (!hook.listeners("error").length) {
hook.on("error", function(err) {
self.failHook(hook, err);
});
}
hook.run(function(err) {
var testError = hook.error();
if (testError) {
self.fail(self.test, testError);
}
if (err) {
if (err instanceof Pending) {
if (name === Mocha.Suite.constants.HOOK_TYPE_BEFORE_EACH ||
name === Mocha.Suite.constants.HOOK_TYPE_AFTER_EACH) {
self.test.pending = true;
} else {
suite.tests.forEach(function(test) {
test.pending = true;
});
suite.suites.forEach(function(suite) {
suite.pending = true;
});
// a pending hook won't be executed twice.
hook.pending = true;
}
} else {
self.failHook(hook, err);
// stop executing hooks, notify callee of hook err
if (!name.startsWith("after")) return fn(err);
}
}
self.emit(Mocha.Runner.constants.EVENT_HOOK_END, hook);
delete hook.ctx.currentTest;
next(++i);
});
}
Mocha.Runner.immediately(function() {
next(0);
});
};