Replace the junit-report-builder package (#4448)

This commit is contained in:
Peter Hedenskog 2025-02-26 15:05:44 +01:00 committed by GitHub
parent 2cc6fdf820
commit 06fb437625
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 1166 additions and 64 deletions

View File

@ -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('<', '&lt;')
.replaceAll('>', '&gt;')
.replaceAll('"', '&quot;')
.replaceAll("'", '&apos;');
}
/**
* 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);
}

1101
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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",