protractor-html-reporter-extended
Version:
Generates HTML report with pie charts based on a xml file
274 lines (250 loc) • 12.1 kB
JavaScript
const xmlDocument = require('xmldoc');
const fileSystem = require('fs');
const filePath = require('path');
const fsextra = require('fs-extra');
var _ = require('lodash');
let csvRecords = [];
let timeStampArr = [];
let csvRecordsPass = [];
let csvRecordsFail = [];
let csvRecordsSkipped = [];
let tcPassed = 0;
let tcFailed = 0;
let tcSkipped = 0;
let stepsPassed = 0;
let stepsFailed = 0;
let stepsSkipped = 0;
function readFile(filename) {
return fileSystem.readFileSync(filename, 'utf-8');
}
function getPath(filename, dir) {
if (dir) {
fsextra.ensureDirSync(dir);
return filePath.join(dir, filename);
}
return filePath.join(__dirname, filename);
}
function getTime(time) {
const toMMSSss = (secs) => {
var secN = parseInt(secs, 10);
var minutes = Math.floor(secN / 60) % 60;
var seconds = secN % 60;
if (minutes < 10) {
minutes = '0' + minutes;
}
if (seconds < 10) {
seconds = '0' + seconds;
}
return minutes + ' mins ' + seconds + ' secs';
};
return toMMSSss(time);
}
function calculateRunTime(timeArr) {
var min = timeArr.sort((a, b) => a - b)[0], max = timeArr.slice(-1)[0];
var elapsedTime = max - min;
elapsedTime /= 1000;
var elapsedTimeSeconds = Number(elapsedTime);
var h = Math.floor(elapsedTimeSeconds / 3600);
var m = Math.floor(elapsedTimeSeconds % 3600 / 60);
var s = Math.floor(elapsedTimeSeconds % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hr, " : " hrs") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " min, " : " mins, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " sec" : " secs") : "";
return hDisplay + mDisplay + sDisplay;
}
var HTMLReport = function () {
this.from = function (xmlfile, testConfig) {
try {
let xmlData = fileSystem.readFileSync(xmlfile, 'utf8');
let testResultXml = new xmlDocument.XmlDocument(xmlData);
let testSuites = testResultXml.childrenNamed('testsuite');
let fTestSuites = testSuites.filter(function (el) {
return el.children.length > 0;
});
let fDisabledSuites = fTestSuites.filter(function (el) {
return el.attr.tests === el.attr.disabled;
});
let fFailedSuites = fTestSuites.filter(function (el) {
return el.attr.failures > 0 || el.attr.errors > 0;
});
let fPassedSuites = fTestSuites.filter(x => fDisabledSuites.indexOf(x) < 0).filter(y => fFailedSuites.indexOf(y) < 0);
// Display Over all summary in Console
console.log('********************** Test Results Summary ************************');
console.log(' Total Passed: ' + fPassedSuites.length);
console.log(' Total Failed: ' + fFailedSuites.length);
console.log(' Total Skipped: ' + fDisabledSuites.length);
console.log('********************************************************************');
// Parse the details test case and test step wise and assign necessary status and color
for (let i = 0; i < fTestSuites.length; i++) {
let className = fTestSuites[i].attr.name.replace(/\n/g, ';');
let moduleName = className.split(',')[0].split('.')[0].replace(/\d+/g, '')
.replace(/_/g, ' ').replace('MBIL-', '').replace('@', '').replace(':', '').trim();
let testResult;
let styleColor;
let cssStyle;
let timeStamp = fTestSuites[i].attr.timestamp;
timeStampArr.push(new Date(timeStamp));
let time = fTestSuites[i].attr.time;
if (fTestSuites[i].attr.tests === fTestSuites[i].attr.disabled) {
testResult = 'Skipped';
styleColor = 'grey';
} else if (fTestSuites[i].attr.failures > 0 || fTestSuites[i].attr.errors > 0) {
testResult = 'Failed';
styleColor = 'red';
} else {
testResult = 'Passed';
styleColor = 'green';
}
let stepDetails = '';
let stepsCnt = fTestSuites[i].children.length;
let testSteps = [];
let errorMessages = [];
let screenshots = [];
let stepsTimes = [];
let tcPassedStepsCnt = 0;
let tcFailedStepsCnt = 0;
let tcSkippedStepsCnt = 0;
for (let j = 0; j < stepsCnt; j++) {
let step = fTestSuites[i].children[j].attr.name.replace('/"/g', '\'');
stepsTimes.push(fTestSuites[i].children[j].attr.time);
let firstChild = fTestSuites[i].children[j].firstChild;
if (firstChild == null) {
stepsPassed += 1;
tcPassedStepsCnt += 1;
styleColor = 'green';
cssStyle = '<span class="label label-success"><i class="glyphicon glyphicon-ok" style="line-height: 2"></i></span> ';
} else if (firstChild.name === 'failure') {
stepsFailed += 1;
tcFailedStepsCnt += 1;
styleColor = 'red';
cssStyle = '<span class="label label-danger"><i class="glyphicon glyphicon-remove" style="line-height: 2"></i></span> ';
} else if (firstChild.name === 'skipped') {
stepsSkipped += 1;
tcSkippedStepsCnt += 1;
styleColor = 'grey';
cssStyle = '<span class="label label-default"><i class="glyphicon glyphicon-off" style="line-height: 2"></i></span> ';
}
if (testResult === 'Failed') {
if (firstChild != null) {
errorMessages.push(firstChild.attr.message);
var splitChar = fTestSuites[i].attr.name.indexOf('.') < fTestSuites[i].attr.name.indexOf(' ') ? '.' : ' ';
const [screenshotPrefix] = fTestSuites[i].attr.name.split(splitChar);
const screenshotSuffix = fTestSuites[i].children[j].attr.name.replace(/\W/g, '').substring(0, 15);
screenshots.push(screenshotPrefix + screenshotSuffix + '.png');
} else {
errorMessages.push('');
screenshots.push('');
}
}
stepDetails = stepDetails + '<li style="color:' + styleColor + '">' + cssStyle + step + '</li>';
testSteps.push('<li style="color:' + styleColor + '">' + cssStyle + step + '</li>');
}
stepDetails = stepDetails.replace(/\n/g, ';');
let csvRowData = {
tcId: i + 1,
moduleName: moduleName,
className: className,
testResult: testResult,
timeStamp: timeStamp,
time: time,
stepCnt: stepsCnt,
tcPassedStepsCnt: tcPassedStepsCnt,
tcFailedStepsCnt: tcFailedStepsCnt,
tcSkippedStepsCnt: tcSkippedStepsCnt,
stepDetails: stepDetails,
errorMessages: errorMessages,
screenshots: screenshots,
testSteps: testSteps,
stepsTimes: stepsTimes
};
csvRecords.push(csvRowData);
if (testResult === 'Passed') csvRecordsPass.push(csvRowData);
else if (testResult === 'Failed') csvRecordsFail.push(csvRowData);
else if (testResult === 'Skipped') csvRecordsSkipped.push(csvRowData);
}
// CSV Report Generation
let allTestsData = [];
allTestsData.push('"TC ID"@"MODULE NAME"@"CLASS NAME"@"TEST RESULT"@"STEPS COUNT"@"STEPS DETAILS"');
for (let i = 0; i < csvRecords.length; i++) {
let row = '"' + csvRecords[i].tcId + '"@"' + csvRecords[i].moduleName + '"@"' + csvRecords[i].className + '"@"'
+ csvRecords[i].testResult + '"@"' + csvRecords[i].stepCnt + '"@"' + csvRecords[i].stepDetails + '"';
allTestsData.push(row);
}
// HTML Report Generation
var moduleLevelMap = {};
var overallTime = 0;
for (var i = 0; i < csvRecords.length; i++) {
var key = csvRecords[i].moduleName;
var value = {
passCount: 0,
failCount: 0,
skipCount: 0,
time: 0,
timeInHMS: ''
};
if (moduleLevelMap[key] != null) {
value = moduleLevelMap[key];
value.time += Number(csvRecords[i].time);
if (csvRecords[i].testResult === 'Passed') {
value.passCount += 1;
tcPassed += 1;
} else if (csvRecords[i].testResult === 'Failed') {
value.failCount += 1;
tcFailed += 1;
} else if (csvRecords[i].testResult === 'Skipped') {
value.skipCount += 1;
tcSkipped += 1;
}
value.timeInHMS = getTime(value.time);
moduleLevelMap[key] = value;
} else {
value.time = Number(csvRecords[i].time);
if (csvRecords[i].testResult === 'Passed') {
value.passCount = 1;
tcPassed += 1;
} else if (csvRecords[i].testResult === 'Failed') {
value.failCount = 1;
tcFailed += 1;
} else if (csvRecords[i].testResult === 'Skipped') {
value.skipCount = 1;
tcSkipped += 1;
}
value.timeInHMS = getTime(value.time);
moduleLevelMap[key] = value;
}
}
overallTime = calculateRunTime(timeStampArr);
let filePath = '';
if (testConfig.outputFilename === undefined) {
filePath = getPath('/Automation-test-report.html', testConfig['outputPath'] || './');
} else {
filePath = getPath('/' + testConfig['outputFilename'] + '.html', testConfig['outputPath'] || './');
}
// Write the HTML report file
fileSystem.writeFileSync(
filePath,
_.template(readFile(getPath('summary.tmpl')))({
projectName: testConfig.projectName,
browser: testConfig.platform + ' ' + testConfig.browserVersion,
reportDate: new Date(),
reportDirectory: filePath,
tcPassed: tcPassed,
tcFailed: tcFailed,
tcSkipped: tcSkipped,
stepsPassed: stepsPassed,
stepsFailed: stepsFailed,
stepsSkipped: stepsSkipped,
moduleLevelMap: moduleLevelMap,
csvRecordsPass: csvRecordsPass,
csvRecordsFail: csvRecordsFail,
csvRecordsSkipped: csvRecordsSkipped,
overallTime: overallTime,
piechart: readFile(getPath('piechart.js'))
})
);
} catch (ex) {
console.log('Error in generating the HTML report. Stack trace : ' + ex);
}
}
};
module.exports = HTMLReport;