Replace the junit-report-builder package
This commit is contained in:
parent
c592349bc3
commit
ef67b52d6d
|
|
@ -1,69 +1,95 @@
|
|||
import path from 'node:path';
|
||||
import { parse } from 'node:url';
|
||||
|
||||
import jrp from 'junit-report-builder';
|
||||
|
||||
import fs from 'node:fs';
|
||||
import merge from 'lodash.merge';
|
||||
import { getLogger } from '@sitespeed.io/log';
|
||||
|
||||
const log = getLogger('sitespeedio.plugin.budget');
|
||||
|
||||
import merge from 'lodash.merge';
|
||||
/**
|
||||
* Escapes XML special characters.
|
||||
*
|
||||
* @param {string} str - The text to escape.
|
||||
* @returns {string} The escaped text.
|
||||
*/
|
||||
function xmlEscape(str) {
|
||||
return String(str)
|
||||
.replaceAll('&', '&')
|
||||
.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')
|
||||
.replaceAll('"', '"')
|
||||
.replaceAll("'", ''');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a string in a CDATA block.
|
||||
*
|
||||
* @param {string} str - The string to wrap.
|
||||
* @returns {string} The CDATA-wrapped string.
|
||||
*/
|
||||
function cdata(str) {
|
||||
return `<![CDATA[${str}]]>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a JUnit XML report mimicking the original output.
|
||||
*
|
||||
* @param {object} results - Object containing `failing` and `working` results.
|
||||
* @param {string} dir - Directory where `junit.xml` will be written.
|
||||
* @param {object} options - Options (expects `options.budget.friendlyName`).
|
||||
*/
|
||||
export function writeJunit(results, dir, options) {
|
||||
// lets have one suite per URL
|
||||
const urls = Object.keys(merge({}, results.failing, results.working));
|
||||
const failing = results.failing || {};
|
||||
const working = results.working || {};
|
||||
const urls = Object.keys(merge({}, failing, working));
|
||||
|
||||
let totalTests = 0;
|
||||
let totalFailures = 0;
|
||||
let suitesXml = '';
|
||||
|
||||
for (const url of urls) {
|
||||
// The URL can be an alias
|
||||
let name = url;
|
||||
if (url.startsWith('http')) {
|
||||
const parsedUrl = parse(url);
|
||||
name = url.startsWith('http') ? url : url;
|
||||
parsedUrl.hostname.replaceAll('.', '_') +
|
||||
'.' +
|
||||
parsedUrl.path.replaceAll('.', '_').replaceAll('/', '_');
|
||||
}
|
||||
const suiteName = `${options.budget.friendlyName || 'sitespeed.io'}.${url}`;
|
||||
let suiteTests = 0;
|
||||
let suiteFailures = 0;
|
||||
let testCasesXml = '';
|
||||
|
||||
const suite = jrp
|
||||
.testSuite()
|
||||
.name(options.budget.friendlyName || 'sitespeed.io' + '.' + name);
|
||||
|
||||
if (results.failing[url]) {
|
||||
for (const result of results.failing[url]) {
|
||||
suite
|
||||
.testCase()
|
||||
.className(name)
|
||||
.name(result.type + '.' + result.metric)
|
||||
.failure(
|
||||
result.metric + ' is ' + result.friendlyValue ||
|
||||
result.value +
|
||||
' and limit ' +
|
||||
result.limitType +
|
||||
' ' +
|
||||
result.friendlyLimit ||
|
||||
result.limit + ' ' + url
|
||||
);
|
||||
if (failing[url]) {
|
||||
for (const result of failing[url]) {
|
||||
suiteTests++;
|
||||
totalTests++;
|
||||
suiteFailures++;
|
||||
totalFailures++;
|
||||
const testCaseName = `${result.type}.${result.metric}`;
|
||||
const failureMessage = `${result.metric} is ${result.friendlyValue || result.value}`;
|
||||
testCasesXml += ` <testcase classname="${xmlEscape(url)}" name="${xmlEscape(testCaseName)}">\n`;
|
||||
testCasesXml += ` <failure message="${xmlEscape(failureMessage)}"/>\n`;
|
||||
testCasesXml += ` </testcase>\n`;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.working[url]) {
|
||||
for (const result of results.working[url]) {
|
||||
suite
|
||||
.testCase()
|
||||
.className(name)
|
||||
.name(result.type + '.' + result.metric)
|
||||
.standardOutput(
|
||||
result.metric + ' is ' + result.friendlyValue ||
|
||||
result.value +
|
||||
' and limit ' +
|
||||
result.limitType +
|
||||
' ' +
|
||||
result.friendlyLimit ||
|
||||
result.limit + ' ' + url
|
||||
);
|
||||
if (working[url]) {
|
||||
for (const result of working[url]) {
|
||||
suiteTests++;
|
||||
totalTests++;
|
||||
const testCaseName = `${result.type}.${result.metric}`;
|
||||
const systemOutMessage = `${result.metric} is ${result.friendlyValue || result.value}`;
|
||||
testCasesXml += ` <testcase classname="${xmlEscape(url)}" name="${xmlEscape(testCaseName)}">\n`;
|
||||
testCasesXml += ` <system-out>${cdata(systemOutMessage)}</system-out>\n`;
|
||||
testCasesXml += ` </testcase>\n`;
|
||||
}
|
||||
}
|
||||
|
||||
suitesXml += ` <testsuite name="${xmlEscape(suiteName)}" tests="${suiteTests}" failures="${suiteFailures}" errors="0" skipped="0">\n`;
|
||||
suitesXml += testCasesXml;
|
||||
suitesXml += ` </testsuite>\n`;
|
||||
}
|
||||
|
||||
const xml =
|
||||
`<?xml version="1.0" encoding="UTF-8"?>\n` +
|
||||
`<testsuites tests="${totalTests}" failures="${totalFailures}" errors="0" skipped="0">\n` +
|
||||
suitesXml +
|
||||
`</testsuites>\n`;
|
||||
|
||||
const file = path.join(dir, 'junit.xml');
|
||||
log.info('Write junit budget to %s', path.resolve(file));
|
||||
jrp.writeTo(file);
|
||||
fs.writeFileSync(file, xml);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
"fast-stats": "0.0.7",
|
||||
"import-global": "1.1.1",
|
||||
"influx": "5.9.3",
|
||||
"junit-report-builder": "3.2.1",
|
||||
"lodash.get": "4.4.2",
|
||||
"lodash.merge": "4.6.2",
|
||||
"lodash.set": "4.3.2",
|
||||
|
|
@ -4091,14 +4090,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/date-format": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz",
|
||||
"integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/date-time": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz",
|
||||
|
|
@ -6793,28 +6784,6 @@
|
|||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/junit-report-builder": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/junit-report-builder/-/junit-report-builder-3.2.1.tgz",
|
||||
"integrity": "sha512-IMCp5XyDQ4YESDE4Za7im3buM0/7cMnRfe17k2X8B05FnUl9vqnaliX6cgOEmPIeWKfJrEe/gANRq/XgqttCqQ==",
|
||||
"dependencies": {
|
||||
"date-format": "4.0.3",
|
||||
"lodash": "^4.17.21",
|
||||
"make-dir": "^3.1.0",
|
||||
"xmlbuilder": "^15.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/junit-report-builder/node_modules/xmlbuilder": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||
"integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||
|
|
@ -7088,6 +7057,7 @@
|
|||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
|
|
@ -7102,6 +7072,7 @@
|
|||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@
|
|||
"fast-stats": "0.0.7",
|
||||
"import-global": "1.1.1",
|
||||
"influx": "5.9.3",
|
||||
"junit-report-builder": "3.2.1",
|
||||
"lodash.get": "4.4.2",
|
||||
"lodash.merge": "4.6.2",
|
||||
"lodash.set": "4.3.2",
|
||||
|
|
|
|||
Loading…
Reference in New Issue