Replace the junit-report-builder package (#4448)
This commit is contained in:
parent
2cc6fdf820
commit
06fb437625
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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