All files / lib/reporter xunit.js

100% Statements 46/46
83.33% Branches 15/18
100% Functions 13/13
100% Lines 43/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109              1x 1x   1x 1x 1x   1x 1x       1x     2x 1x         1x 1x   1x     1x 1x 1x   1x     1x 1x   1x 1x 1x 1x     1x             1x 1x             1x 3x           3x 1x 1x 2x 1x   1x                           5x 5x     5x 9x 9x       5x 5x 3x   5x    
"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) {
        Eif (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;
}