"use strict";
/**
* `GlaceJS` stdout reporter.
*
* @module
*/
const fs = require("fs");
const path = require("path");
const util = require("util");
const _ = require("lodash");
const colors = require("colors");
const fse = require("fs-extra");
const MochaReporter = require("mocha").reporters.base;
const prettyms = require("pretty-ms");
const CONF = require("../config");
const TestCase = require("../testing").TestCase;
const utils = require("../utils");
let report;
let indents = 0;
/**
* Calculate message indentation.
* @ignore
*/
const indent = () => Array(indents).join(" ");
/**
* Write report to stdout.
* @ignore
*/
const stdout = function() {
report.write(colors.strip(util.format.apply(util, arguments)) + "\n");
console.log.apply(console, arguments);
};
/**
* Print epilogue results.
* @ignore
*/
const epilogue = () => {
const passedTests = [], failedTests = [], skippedTests = [];
for (const testCase of CONF.test.cases) {
if (testCase.status === TestCase.FAILED) {
failedTests.push(testCase);
}
if (testCase.status === TestCase.PASSED) {
passedTests.push(testCase);
}
if (testCase.status === TestCase.SKIPPED) {
skippedTests.push(testCase);
}
}
printStatistics(passedTests.length, failedTests.length);
if (skippedTests.length) printSkippedTests(skippedTests);
utils.printTestErrors(failedTests, stdout);
utils.printSessionErrors(stdout);
};
/**
* Prints tests statistics.
* @ignore
*/
const printStatistics = (passedNum, failedNum) => {
let msg;
const indent = " ";
if (passedNum) {
msg = "passed test" + (passedNum === 1 ? "" : "s");
stdout((indent + MochaReporter.symbols.ok + " " +
String(passedNum).bold + " " + msg).green);
}
if (failedNum) {
msg = "failed test" + (failedNum === 1 ? "" : "s");
stdout((indent + MochaReporter.symbols.err + " " +
String(failedNum).bold + " " + msg).red);
}
const chunksNum = CONF.test.cases.reduce((a, b) => a + b.chunks.length, 0);
if (chunksNum) {
msg = "executed chunk" + (chunksNum === 1 ? "" : "s");
stdout(indent + chunksNum + " " + msg);
}
let execTime = CONF.test.cases
.map(t => t.duration)
.reduce((a, b) => a + b, 0);
if (execTime > 0) {
execTime = (execTime < 60000 ? `${execTime / 1000} sec` : prettyms(execTime)).bold;
stdout();
stdout(indent + "Summary tests time is", execTime);
}
};
/**
* Prints skipped tests.
* @ignore
*/
const printSkippedTests = skippedTests => {
let msg;
const indent = " ";
msg = "skipped test" + (skippedTests.length === 1 ? "" : "s");
stdout();
// HACK https://github.com/glacejs/glace-core/issues/136
stdout(indent + "# ".gray + String(skippedTests.length).gray.bold + " " + msg.gray);
for (const skip of skippedTests) {
msg = `* '${skip.name}'`;
if (skip.rawInfo[0]) {
msg += " - " + skip.rawInfo[0].bold;
}
stdout(indent + indent + msg.gray);
}
};
module.exports = {
/**
* Called before tests start.
*
* @method
* @instance
*/
start: () => {
fse.mkdirsSync(CONF.report.dir);
report = fs.createWriteStream(
path.resolve(CONF.report.dir, "stdout.log"), { flags : "w" });
},
/**
* Called before tests end.
*
* @method
* @instance
*/
end: () => {
epilogue();
stdout();
const reportMsg = "Local report is " + CONF.report.dir;
stdout(Array(reportMsg.length + 1).join("-").yellow);
stdout(reportMsg.yellow);
},
/**
* Called on scope start.
*
* @method
* @instance
* @arg {object} scope - `MochaJS` suite.
*/
scope: scope => {
++indents;
if (indents) {
stdout();
stdout((indent() + "scope: " + scope.title).cyan);
}
},
/**
* Called before scope end.
*
* @method
* @instance
*/
scopeEnd: () => {
--indents;
if (!indents) stdout();
},
/**
* Called on suite start.
*
* @method
* @instance
* @arg {object} suite - `MochaJS` suite.
*/
suite: suite => {
++indents;
if (indents) {
stdout();
stdout((indent() + "suite: " + suite.title).cyan);
}
},
/**
* Called before suite end.
*
* @method
* @instance
*/
suiteEnd: () => {
--indents;
if (!indents) stdout();
},
/**
* Called on test start.
*
* @method
* @instance
* @arg {object} test - `MochaJS` suite.
*/
test: test => {
++indents;
if (indents) {
stdout();
stdout((indent() + "test: " + test.title).cyan.bold);
}
},
/**
* Called on test end.
*
* @method
* @instance
*/
testEnd: () => {
--indents;
if (!indents) stdout();
},
/**
* Called on chunk passed.
*
* @method
* @instance
* @arg {object} chunk - `MochaJS` test.
*/
pass: chunk => {
let msg = indent() + " " + MochaReporter.symbols.ok + " chunk";
if (chunk.title) msg += ": " + chunk.title;
stdout(msg.green);
},
/**
* Called on chunk skipped.
*
* @method
* @instance
* @arg {object} chunk - `MochaJS` test.
*/
skip: chunk => {
let msg = indent() + " # chunk";
if (chunk.title) msg += ": " + chunk.title;
stdout(msg.gray);
},
/**
* Called on chunk or hook failed.
*
* @method
* @instance
* @arg {object} chunk - `MochaJS` test.
*/
fail: chunk => {
let suffix = chunk.type === "hook" ? " hook" : " chunk";
let msg = indent() + " " + MochaReporter.symbols.err + suffix;
if (chunk.title) msg += ": " + chunk.title;
stdout(msg.red);
if (CONF.report.errorsNow) {
let errMsg;
if (CONF.test.curCase) {
errMsg = _.last(CONF.test.curCase.errors);
} else {
errMsg = _.last(CONF.session.errors);
}
stdout(errMsg.red.bold);
}
},
/**
* Called on report finalizing.
*
* @method
* @instance
*/
done: () => new Promise(resolve => report.end(resolve)),
};