UNPKG

wdio-junit-to-html

Version:

A simple CLI module to convert WebdriverIO JUnit tests to HTML.

257 lines (224 loc) 9.56 kB
#! /usr/bin/env node var program = require('commander'); const fs = require('fs'); const xml2js = require('xml2js'); const dateFormat = require('dateformat'); const email = require('emailjs/email'); const GlobalVars = require('./vars.js'); const email_server = email.server.connect({ user: GlobalVars.email.from.username, password: GlobalVars.email.from.password, host: GlobalVars.email.from.smtp_host, ssl: GlobalVars.email.from.ssl }); var d = new Date(); const generationDate = dateFormat(d,'isoDate'); var outputDir = GlobalVars.paths.default_output_path; var inputDir = GlobalVars.paths.default_input_path; //How far back the path should go for source files var srcFileDepth = 3; var menu = [];menu.push('TEMP'); var menuID = 0; var failed = 0; var passed = 0; program .usage('[options]') .option('-i, --input <input>', 'The input folder path (relative)') .option('-o, --output <output>', 'The output folder path (relative)') .option('-s, --single','Export all reports in one file') .option('-e, --email_report','Send an email of a single using config from vars.js.') .option('-l, --log','Log basic information about what is being done.') .parse(process.argv); //Actual code that runs when module called if(program.input) inputDir = program.input; if(program.output) outputDir = program.output; generateFromFolder(); //Handles `program.single` within //Functions Below function parse(data){ var output = ''; for(s in data['testsuites']['testsuite']){ var suite = data['testsuites']['testsuite'][s]; if(s == 0){ //First suite, contains information about source file var fp = suite['properties'][0]['property'][3]['$']['value'].toString().split('\\'); var outFp = ""; for(var n=fp.length-srcFileDepth;n<fp.length;n++){ outFp += '\\'+fp[n]; } output += ` <div class="suite-container" id="suite_`+menuID+`"> <span class="title"><b>`+suite['properties'][0]['property'][1]['$']['value']+`</b></span> <span class="suite-duration"><b>Run Duration: </b>`+suite['$']['time']+`seconds</span> <span class="suite-fromfile"><b>Source File: </b>`+outFp+`</span> <span class="suite-spec"><b>Spec ID: </b>`+suite['properties'][0]['property'][0]['$']['value']+`</span> `; menu.push('<li class="head"><a href="#suite_'+menuID+'">'+suite['properties'][0]['property'][1]['$']['value']+'</a></li>'); menuID++; } else { // All "sub-suites" var name = suite['properties'][0]['property'][1]['$']['value']; var op_time = suite['$']['time']+'seconds'; var count_tests = suite['$']['tests']; var count_fails = suite['$']['failures']; var count_errors = suite['$']['errors']; var has_error = ""; if(parseInt(count_errors) > 0){ has_error = "has_error" } var count_skips = suite['$']['skipped']; //Begin outputting test suite to html output += ` <div class="suite" id="sub_`+menuID+`"> <span class="title `+has_error+`"><b>Suite: </b>`+name+`</span> <span class="duration"><b>Run Duration: </b>`+op_time+`</span> <span class="count_tests"><b>Test Count: </b>`+count_tests+`</span> <span class="count_fails"><b>Failed Test Count: </b>`+count_fails+`</span> <span class="count_errors"><b>Error Count: </b>`+count_errors+`</span> <span class="count_skips"><b>Skipped Test Count: </b>`+count_skips+`</span> <div class="tests"> <span class="expand_tests"></span>`; menu.push('<li class="sub"><a href="#sub_'+menuID+'">'+suite['properties'][0]['property'][1]['$']['value']+'</a></li>'); menuID++; //Output the individual tests for(var t in suite['testcase']){ var test = suite['testcase'][t]; var error = ''; var err_out = ''; if(test['error'] != null){ error = '<i style=\"color:red;\">'+test['error'][0]['$']['message']+'</i>'; err_out = '<pre class="err_out">'+test['system-err']+'</pre>'; failed++; } else { error = "<i style=\"color:green;\">PASS</i>"; passed++; } output += ` <div class="test" id="test_`+menuID+`"> <span class="name"><b>Name: </b>`+test['$']['name']+`</span> <span class="duration"><b>Run Time: </b>`+test['$']['time']+`seconds</span> <span class="result"><b>Result: </b>`+error+`</span> <span>`+err_out+`</span> </div>`; var menuErr = (test['error'] != null) ? ' error' : ''; menu.push('<li class="test'+menuErr+'"><a href="#test_'+menuID+'">'+test['$']['name']+'</a></li>'); menuID++; } output += '</div></div>'; } } output += '</div>\n<!--Closes `.suite-container`-->'; return output; } function cleanMenu(){ //"Finishes" the report, adds `#content` //MUST SET `menu = [];` AFTER CALLING THIS AND USING `menu` SOMEWHERE. menu[0] = '<li id="nav_counts">Report: '+generationDate+'<br><span class="has_error">FAILED: '+failed+'</span><br><br><span>PASSED: '+passed+'</span><br></li>'; menu.push('<li style="padding:8px 16px;"><button onclick="openall()">Open/Close all Tests</button></li></ul></nav>\n<div id="content">'); //If --email_report && --single, send email if(program.email_report && program.single){ console.log('Attempting to send email of report...'); GlobalVars.email.to.attachment[0].path = outputDir+'/alltests-'+generationDate+'.html'; var message = { text: GlobalVars.email.to.text, from: GlobalVars.email.from.username, to: GlobalVars.email.to.recepient, subject: GlobalVars.email.to.subject, attachment: [ GlobalVars.email.to.attachment[0] ] } email_server.send(message, function(err, message) { if(err){ console.log( err ); } else { console.log('Email sent!'); } }); } //Reset counter failed = 0; passed = 0; } function convertSingleFileToHTML(filePath){ var output = filePath; var pathSplit = filePath.split('\\'); fs.readFile(inputDir+'/'+filePath, 'utf8', function (err,data) { if (err) { return console.log(err); } xml2js.parseString(data,function(err,result){ var res = parse(result); //Finish up the menu cleanMenu(); fs.writeFile( outputDir+'/'+pathSplit[pathSplit.length-1].substr(0,pathSplit[pathSplit.length-1].length-4)+'.html', GlobalVars.HTMLHeader+menu.join('')+res+GlobalVars.HTMLFooter, //Actually parse the input here function(err){ if(err){ return console.log(err); } } ); }); menu = []; //Reset menu }); } function exportAsOneFile(){ var allFiles = []; //Array to hold all tests as HTML var files = fs.readdirSync(inputDir); //Go through all .xml files and add HTML to the `allFiles` array files.forEach(file => { if(file.substr(-4) == '.xml'){ var data = fs.readFileSync(inputDir+'/'+file);//, 'utf8', function (err,data) { xml2js.parseString(data,function(err,result){ //Add parsed XML -> HTML to `allFiles` allFiles.push( parse(result) ); }); } }); //Finish up the menu cleanMenu(); fs.writeFile( outputDir+'/alltests-'+generationDate+'.html', GlobalVars.HTMLHeader+menu.join('')+allFiles.join("\n\n<!--New Result File-->\n")+GlobalVars.HTMLFooter, //Actually parse the input here function(err){ if(err){ return console.log(err); } } ); menu = []; //Reset menu } function generateFromFolder(){ //Check if `outputDir` exists //if not, create it var startTime = new Date().getUTCMilliseconds(); if (!fs.existsSync(outputDir)){ fs.mkdirSync(outputDir); } fs.readdir(inputDir, (err, files) => { if(program.single){ //Will output all files as one if(program.log) console.log('Exporting files into one output.html'); exportAsOneFile(); } else { //Will output all files individually if(program.log) console.log('Exporting files individually'); files.forEach(file => { if(file.substr(-4) == '.xml'){ convertSingleFileToHTML(file); } }); } var endTime = new Date().getUTCMilliseconds(); var runTime = (endTime-startTime)/1000; if(program.log){ console.log('HTML Report(s) Generated in `%s`\n\tDone in %sseconds',outputDir,runTime); } }); }