UNPKG

junit-xml

Version:

JUnit XML report builder with TypeScript support

114 lines (96 loc) 3.73 kB
import { TestSuiteReport, TestSuite, TestCase } from './TestResults'; /** * * @param report A report in the default schema, as supported by GitLab */ export function getXmlObject(report: TestSuiteReport) { const testSuites = report.suites.map(attachTestSuiteMetadata); const xmlObject: { testsuites: any[] } = { testsuites: testSuites .filter(testSuite => testSuite.tests > 0) .map((testSuite, index) => ({ testsuite: getTestSuiteXmlObject(testSuite, index) })), }; return xmlObject; } function getTestSuiteXmlObject(testSuite: TestSuite & TestSuiteMetadata, index: number) { const systemOuts = testSuite.testCases .filter((testCase) => Array.isArray(testCase.systemOut) && testCase.systemOut.length > 0) .map((outTestCase) => outTestCase.systemOut!.join('\n')) .join('\n'); const systemErrs = testSuite.testCases .filter((testCase) => Array.isArray(testCase.systemErr) && testCase.systemErr.length > 0) .map((errTestCase) => errTestCase.systemErr!.join('\n')) .join('\n'); const testSuiteXmlObject: any[] = testSuite.testCases .map((testCase) => ({ testcase: getTestCaseXmlObject(testCase) })); testSuiteXmlObject.push({ 'system-out': systemOuts }); testSuiteXmlObject.push({ 'system-err': systemErrs }); testSuiteXmlObject.unshift({ properties: [] }) const testsuiteAttributes: { [key: string]: string } = { package: testSuite.name || `Test suite #${index}`, id: index.toString(), name: testSuite.name || `Test suite #${index}`, timestamp: mangleIsoDate((testSuite.timestamp || new Date(0)).toISOString()), hostname: testSuite.hostname || 'localhost', tests: testSuite.tests.toString(), errors: testSuite.errors.toString(), failures: testSuite.failures.toString(), time: (testSuite.time || 0).toString(), }; testSuiteXmlObject.push({ _attr: testsuiteAttributes }); return testSuiteXmlObject; } function getTestCaseXmlObject(testCase: TestCase) { const testCaseXmlObject: any[] = []; const testcaseAttributes: { [key: string]: string } = { name: testCase.name, classname: testCase.classname || testCase.name, time: (testCase.time || 0).toString(), }; testCaseXmlObject.push({ _attr: testcaseAttributes }); if (Array.isArray(testCase.errors)) { testCaseXmlObject.push({ error: formatMessages(testCase.errors) }); } if (Array.isArray(testCase.failures)) { testCaseXmlObject.push({ failure: formatMessages(testCase.failures) }); } return testCaseXmlObject; } interface TestSuiteMetadata { tests: number; failures: number; errors: number; skipped: number; }; function attachTestSuiteMetadata(testSuite: TestSuite): TestSuite & TestSuiteMetadata { return { ...testSuite, tests: testSuite.testCases.length, failures: testSuite.testCases.filter(isFailing).length, errors: testSuite.testCases.filter(hasErrors).length, skipped: testSuite.testCases.filter(isSkipped).length, }; } function isSkipped(testCase: TestCase): boolean { return testCase.skipped === true; } function isFailing(testCase: TestCase): boolean { return Array.isArray(testCase.failures) && testCase.failures.length > 0; } function hasErrors(testCase: TestCase): boolean { return Array.isArray(testCase.errors) && testCase.errors.length > 0; } function formatMessages(messages: Array<{ message: string; type?: string }>) { return { _attr: { message: messages.map(message => message.message).join(', '), type: 'Unkown', }, }; } /** * The schema uses an ISO8601 date regex that does not include the timezone; this function strips it. */ function mangleIsoDate(isoDate: string): string { return isoDate.substring(0, isoDate.length - 5); }