Skip to content

Instantly share code, notes, and snippets.

@Prophet32j
Last active March 15, 2022 17:47
Show Gist options
  • Save Prophet32j/05a2ceda3743b9fd93e98e56a9227309 to your computer and use it in GitHub Desktop.
Save Prophet32j/05a2ceda3743b9fd93e98e56a9227309 to your computer and use it in GitHub Desktop.
Jest test output to mocha awesome converter
const marge = require('mochawesome-report-generator');
const fs = require('fs');
const path = require('path');
const uuid = require('uuid-v4');
module.exports = (testResults) => {
const margeInput = buildMargeInput(testResults);
marge.create(margeInput)
.then(function() {
console.log('Successfully generated Mocha Awesome report');
return testResults;
})
.catch(function(err) {
console.err('Error generating Mocha Awesome report: ', err);
throw err;
});
// debug purposes only
// writeOutput(testResults, 'jest-output');
// writeOutput(margeInput, 'marge-input');
return testResults;
}
const buildMargeInput = (testResults) => {
let elapsed = buildElapsedTime(testResults.testResults);
let testSuites = testResults.testResults.map(createSuite);
var input = {};
input.stats = {
suites: testResults.numTotalTestSuites,
tests: testResults.numTotalTests,
testsRegistered: testResults.numTotalTests,
passes: testResults.numPassedTests,
pending: testResults.numPendingTests,
failures: testResults.numFailedTests,
start: new Date(testResults.startTime), // Jest does epochs
end: new Date(testResults.startTime + elapsed),
duration: elapsed,
passPercent: testResults.numPassedTests / testResults.numTotalTests * 100,
pendingPercent: testResults.numPendingTests / testResults.numTotalTests * 100,
other: 0,
hasOther: false,
skipped: 0,
hasSkipped: false,
passPercentClass: "success",
pendingPercentClass: "danger"
};
input.suites = {
title: '',
suites: testSuites,
root: true,
uuid: uuid(),
tests: [],
pending: [],
_timeout: 5000,
fullFile: '',
file: '',
passes: [],
failures: [],
skipped: [],
hasTests: false,
hasSuites: true,
totalTests: 0,
totalFailures: 0,
totalPending: 0,
totalSkipped: 0,
hasPasses: false,
hasFailures: false,
hasPending: false,
hasSkipped: false,
duration: 0,
rootEmpty: true,
totalPasses: 0,
beforeHooks: [],
afterHooks: [],
hasBeforeHooks: false,
hasAfterHooks: false
};
// collect all tests
let allTests = testSuites.reduce((sum, suite) => {
return sum.concat(suite.tests);
}, []);
let allPending = allTests.filter(test => test.pending);
let allPasses = allTests.filter(test => test.pass);
let allFailures = allTests.filter(test => test.fail);
input.allTests = allTests;
input.allPending = allPending;
input.allPasses = allPasses;
input.allFailures = allFailures;
input.copyrightYear = 2017;
return input;
}
function createSuite(suite) {
let id = uuid();
let tests = suite.testResults.map((test) => {
return createTest(test, id);
});
let passes = tests.filter(test => test.pass);
let failures = tests.filter(test => test.fail);
let pending = tests.filter(test => test.pending);
return {
title: suite.testResults[0].ancestorTitles[0],
suites: [],
tests: tests,
pending: pending,
root: false,
uuid: id,
_timeout: 5000,
fullFile: suite.testFilePath,
file: suite.testFilePath.split('/').pop(),
beforeHooks: [],
afterHooks: [],
passes: passes,
failures: failures,
skipped: [],
hasTests: tests.length > 0,
hasSuites: false,
totalTests: tests.length,
totalPasses: passes.length,
totalFailures: failures.length,
totalPending: pending.length,
totalSkipped: 0,
hasPasses: passes.length > 0,
hasFailures: failures.length > 0,
hasPending: pending.length > 0,
hasSkipped: false,
hasBeforeHooks: false,
hasAfterHooks: false,
duration: suite.perfStats.end - suite.perfStats.start
}
}
function createTest(test, parentId) {
return {
title: test.title,
fullTitle: fullTitle(test),
timedOut: false,
duration: test.duration,
pass: passed(test),
fail: failed(test),
pending: pending(test),
code: '',
isRoot: false,
uuid: uuid(),
parentUUID: parentId,
skipped: false,
isHook: false,
err: {}
}
}
function passed(test) {
return test.status === 'passed';
}
function failed(test) {
return test.status === 'failed';
}
function pending(test) {
return test.status === 'pending';
}
function fullTitle(test) {
if (test.fullName) {
return test.fullName;
}
return test.ancestorTitles.reduce((sum, val) => {
sum + val + ' ';
}, '');
}
function buildElapsedTime(suites) {
return suites.reduce((sum, suite) => {
return sum + suite.testResults.reduce((_sum, test) => {
return _sum + test.duration;
}, 0);
}, 0);
}
function writeOutput(payload, filename) {
const json = JSON.stringify(payload);
const dir = path.join(__dirname, filename);
fs.writeFile(dir, json, 'utf8', (err) => {
if (err) { throw err; }
console.log('file saved');
});
}
{
"numFailedTestSuites":0,
"numFailedTests":0,
"numPassedTestSuites":1,
"numPassedTests":4,
"numPendingTestSuites":0,
"numPendingTests":0,
"numRuntimeErrorTestSuites":0,
"numTotalTestSuites":1,
"numTotalTests":4,
"snapshot":{
"added":0,
"failure":false,
"filesAdded":0,
"filesRemoved":0,
"filesUnmatched":0,
"filesUpdated":0,
"matched":0,
"total":0,
"unchecked":0,
"unmatched":0,
"updated":0
},
"startTime":1500663306186,
"success":true,
"testResults":[
{
"console":null,
"failureMessage":null,
"numFailingTests":0,
"numPassingTests":4,
"numPendingTests":0,
"perfStats":{
"end":1500663308338,
"start":1500663307435
},
"snapshot":{
"added":0,
"fileDeleted":false,
"matched":0,
"unchecked":0,
"unmatched":0,
"updated":0
},
"testFilePath":"/Users/ufen/dev/itada/web-ui/test/components/Asset/index.test.js",
"testResults":[
{
"ancestorTitles":[
"Asset,",
"when initialized without an asset,"
],
"duration":4,
"failureMessages":[
],
"fullName":"Asset, when initialized without an asset, should render a div tag with a spinner",
"numPassingAsserts":0,
"status":"passed",
"title":"should render a div tag with a spinner"
},
{
"ancestorTitles":[
"Asset,",
"when initialized without an asset,"
],
"duration":1,
"failureMessages":[
],
"fullName":"Asset, when initialized without an asset, should call the functions in the componentWillMount function",
"numPassingAsserts":0,
"status":"passed",
"title":"should call the functions in the componentWillMount function"
},
{
"ancestorTitles":[
"Asset,",
"when initialized with an asset,"
],
"duration":0,
"failureMessages":[
],
"fullName":"Asset, when initialized with an asset, should render an h1 element with asset name and category",
"numPassingAsserts":0,
"status":"passed",
"title":"should render an h1 element with asset name and category"
},
{
"ancestorTitles":[
"Asset,",
"when initialized with an asset,"
],
"duration":7,
"failureMessages":[
],
"fullName":"Asset, when initialized with an asset, should accept new props and register the changes",
"numPassingAsserts":0,
"status":"passed",
"title":"should accept new props and register the changes"
}
],
"skipped":false
}
],
"wasInterrupted":false
}
@dopry
Copy link

dopry commented Dec 31, 2020

https://gist.github.com/dopry/691e6b21170b55c41768d02dc059c48b is an update in case anyone is looking for draft of a jest-mochawesome-reporter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment