Taking+advantage+of+JUnit+XML+reports:
https://docs.getxray.app/display/XRAY/Taking+advantage+of+JUnit+XML+reports
Mocha tut:
https://mochajs.org/api/tutorial-custom-reporter.html
'use strict';
const mkdirp = require('mkdirp');
const xmlbuilder = require('xmlbuilder');
const Mocha = require('mocha');
const path = require('path');
const fs = require('fs');
const {
EVENT_RUN_BEGIN,
EVENT_RUN_END,
EVENT_TEST_FAIL,
EVENT_TEST_PASS,
EVENT_SUITE_BEGIN,
EVENT_SUITE_END,
EVENT_TEST_PENDING,
EVENT_TEST_END
} = Mocha.Runner.constants;
console.log(
"EVENT_RUN_BEGIN:" + EVENT_RUN_BEGIN,
"EVENT_RUN_END:" + EVENT_RUN_END,
"EVENT_TEST_FAIL:" + EVENT_TEST_FAIL,
"EVENT_TEST_PASS:" + EVENT_TEST_PASS,
"EVENT_SUITE_BEGIN:" + EVENT_SUITE_BEGIN,
"EVENT_SUITE_END:" + EVENT_SUITE_END,
"EVENT_TEST_PENDING:" + EVENT_TEST_PENDING,
"EVENT_TEST_END:" + EVENT_TEST_END);
class XrayJUnitReporter {
constructor(runner, options) {
this.runner = runner;
this.options = options;
this.testcases = [];
this.fullTitle = '';
this.passed = 0;
this.failed = 0;
this.skipped = 0;
runner.on(EVENT_TEST_END, (test) => {
this.fullTitle = test.parent.fullTitle();
console.log('fullTitle: ', this.fullTitle);
const inputString = "ESGFMW-418:cant-click-nonexisting-element";
const { test_key, title } = this.extractStrings(inputString);
console.log('test_key/title: ', test_key, title)
const testcase = {
'@name': this.fullTitle + title ,
'@classname': test.parent.fullTitle(),
'@time': test.duration / 1000,
properties: {
'property': {
'@name': 'test_key',
'@value': 'ESGFMW-438'
}
}
};
if (test.state === 'passed') {
this.passed++;
} else if (test.pending) {
this.skipped++;
testcase.skipped = {};
} else {
this.failed++;
const err = test.err;
testcase.failure = {
'@message': err.message,
'@type': err.name,
'#text': err.stack,
};
}
this.testcases.push(testcase);
});
runner.on(EVENT_RUN_END, () => {
const report = {
testsuites: {
testsuite: {
'@name': 'Mocha Suite',
'@tests': this.passed + this.failed + this.skipped,
'@failures': this.failed,
'@skipped': this.skipped,
// '@time': this.runner.totalTime / 1000,
testcase: this.testcases,
},
},
};
const xml = xmlbuilder.create(report, { encoding: 'UTF-8' }).end({ pretty: true });
const reportDir = this.options.reporterOptions.reportDir; // alternatively: this.options.reporterOptions.outputFile
const outputFile = path.resolve(reportDir, this.sanitizeFilename(this.fullTitle) + '.xml')
console.log(this.options.reporterOptions.reportDir, this.fullTitle, xml);
mkdirp.sync(reportDir);
fs.writeFileSync(outputFile, xml);
});
}
sanitizeFilename(filename) {
const invalidChars = /[<>:"/\\|?*\x00-\x1F]/g; // Regex pattern for invalid characters
const whitespaceChars = /\s/g; // Regex pattern for whitespaces
const replacementChar = "_"; // Character used for replacement
// Replace invalid characters and whitespaces with the replacement character
const sanitizedFilename = filename.replace(invalidChars, replacementChar).replace(whitespaceChars, replacementChar);
return sanitizedFilename;
}
extractStrings(inputString) {
const [test_key, title] = inputString.split(':');
return { test_key, title };
}
}
module.exports = XrayJUnitReporter;