"use strict";
/**
* `GlaceJS` xunit reporter.
*
* @module
*/
const fs = require("fs");
const path = require("path");
require("colors");
const escape = require("mocha").utils.escape;
const fse = require("fs-extra");
const CONF = require("../config");
const TestCase = require("../testing").TestCase;
let stream;
module.exports = {
start: () => {
if (fs.existsSync(CONF.xunit.path)) {
fs.unlinkSync(CONF.xunit.path);
}
},
end: () => {
fse.mkdirsSync(path.dirname(CONF.xunit.path));
stream = fs.createWriteStream(CONF.xunit.path);
write(tag("testsuite", {
name: CONF.xunit.suiteName,
tests: CONF.test.cases.length,
failures: CONF.test.cases.filter(t => t.status === TestCase.FAILED).length,
errors: CONF.test.cases.filter(t => t.status === TestCase.FAILED).length,
skipped: CONF.test.cases.filter(t => t.status === TestCase.SKIPPED).length,
timestamp: new Date().toUTCString(),
time: (CONF.test.cases.map(t => t.duration).reduce((a, b) => a + b, 0) / 1000) || 0
}, false));
CONF.test.cases.forEach(t => writeTest(t));
write("</testsuite>");
console.log();
const reportMsg = "xUnit report is " + CONF.xunit.path;
console.log(Array(reportMsg.length + 1).join("-").yellow);
console.log(reportMsg.yellow);
},
done: () => new Promise(resolve => stream.end(resolve)),
};
/**
* Writes a line.
*
* @arg {string} line - Report text line.
*/
const write = line => {
stream.write(line + "\n");
};
/**
* Writes a test.
*
* @arg {TestCase} test - Test case.
*/
const writeTest = test => {
const attrs = {
classname: test.name,
name: test.name,
time: (test.duration / 1000) || 0
};
if (test.status === TestCase.FAILED) {
const err = test.errors.join("\n");
write(tag("testcase", attrs, false, tag("failure", {}, false, escape(err))));
} else if (test.status === TestCase.SKIPPED) {
write(tag("testcase", attrs, false, tag("skipped", {}, true)));
} else {
write(tag("testcase", attrs, true));
}
};
/**
* HTML tag helper. (copied from mochajs)
*
* @ignore
* @param name
* @param attrs
* @param close
* @param content
* @return {string}
*/
function tag (name, attrs, close, content) {
const end = close ? "/>" : ">";
const pairs = [];
let tag;
for (const key in attrs) {
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
pairs.push(key + "=\"" + escape(attrs[key]) + "\"");
}
}
tag = "<" + name + (pairs.length ? " " + pairs.join(" ") : "") + end;
if (content) {
tag += content + "</" + name + end;
}
return tag;
}