Created
January 10, 2024 08:10
-
-
Save pdehaan/6997d1244205d799909c26a4793e3701 to your computer and use it in GitHub Desktop.
Convert a glob of JUnit XML reports into a JSON object... for reasons.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fs from "node:fs"; | |
import fg from "fast-glob"; | |
import { XMLParser } from "fast-xml-parser"; | |
import { z } from "zod"; | |
const testsuiteSchema = z.object({ | |
testsuite: z.array( | |
z.object({ | |
testcase: z.array( | |
z.object({ | |
properties: z | |
.object({ | |
property: z.array( | |
z.any() | |
// z.object({ | |
// name: z.string(), | |
// value: z.string(), | |
// }) | |
), | |
}) | |
.optional(), | |
name: z.string(), | |
classname: z.string(), | |
time: z.coerce.number(), | |
skipped: z.any().optional(), | |
// If something was logged to STDOUT. | |
"system-out": z.string().trim().optional(), | |
}).strict() | |
), | |
name: z.string(), | |
timestamp: z.coerce.date(), | |
hostname: z.string(), | |
tests: z.coerce.number(), | |
failures: z.coerce.number(), | |
skipped: z.coerce.number(), | |
time: z.coerce.number(), | |
errors: z.coerce.number(), | |
}).strict(), | |
), | |
id: z.string(), | |
name: z.string(), | |
tests: z.coerce.number(), | |
failures: z.coerce.number(), | |
skipped: z.coerce.number(), | |
errors: z.coerce.number(), | |
time: z.coerce.number(), | |
}).strict(); | |
const $testsuites = junitToJSON("./artifacts/*.xml", testsuiteSchema); | |
fs.writeFileSync("test.json", JSON.stringify($testsuites, null, 2)); | |
function junitToJSON(xmlGlob, schema) { | |
const testsuites = fg.globSync(xmlGlob).reduce((acc = [], file = "") => { | |
const data = readXMLSync(file); | |
data.testsuites.testsuite = data.testsuites.testsuite.map((suite) => { | |
// Make sure `testcase[]` is always an array. | |
if (!Array.isArray(suite.testcase)) { | |
suite.testcase = [suite.testcase]; | |
} | |
// Make sure `properties.property[]` is always an array. | |
suite.testcase = suite.testcase.map((testcase) => { | |
if ( | |
testcase.properties?.property && | |
!Array.isArray(testcase.properties.property) | |
) { | |
testcase.properties.property = [testcase.properties.property]; | |
} | |
return testcase; | |
}); | |
return suite; | |
}); | |
return acc.concat(data.testsuites); | |
}, []); | |
if (schema) { | |
return z.array(schema).parse(testsuites); | |
} | |
return testsuites; | |
} | |
function readXMLSync(file) { | |
const parser = new XMLParser({ | |
ignoreAttributes: false, | |
ignoreDeclaration: true, | |
attributeNamePrefix: "", | |
}); | |
const xmlStr = fs.readFileSync(file, "utf-8"); | |
return parser.parse(xmlStr); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "fxa-functional-tests-artifacts-xml", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"type": "module", | |
"scripts": { | |
"start": "node index" | |
}, | |
"keywords": [], | |
"author": "Peter deHaan <[email protected]>", | |
"license": "MPL-2.0", | |
"dependencies": { | |
"fast-glob": "^3.3.2", | |
"fast-xml-parser": "^4.3.2", | |
"zod": "^3.22.4" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment