UNPKG

junit-xml

Version:

JUnit XML report builder with TypeScript support

131 lines (109 loc) 4.17 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.map((testSuite) => ({ testsuite: getTestSuiteXmlObject(testSuite) })), }; const testsuitesAttributes: { [key: string]: string } = { tests: testSuites.reduce((tests, suite) => tests + suite.tests, 0).toString(), errors: testSuites.reduce((errors, suite) => errors + suite.errors, 0).toString(), failures: testSuites.reduce((failures, suite) => failures + suite.failures, 0).toString(), skipped: testSuites.reduce((skipped, suite) => skipped + suite.skipped, 0).toString(), }; if (report.name) { testsuitesAttributes.name = report.name; } if (report.time) { testsuitesAttributes.time = report.time.toString(); } xmlObject.testsuites.push({ _attr: testsuitesAttributes }); return xmlObject; } function getTestSuiteXmlObject(testSuite: TestSuite & TestSuiteMetadata) { const testSuiteXmlObject: any[] = testSuite.testCases .map((testCase) => ({ testcase: getTestCaseXmlObject(testCase) })); const testsuiteAttributes: { [key: string]: string } = { tests: testSuite.tests.toString(), errors: testSuite.errors.toString(), failures: testSuite.failures.toString(), skipped: testSuite.skipped.toString(), }; if (testSuite.name) { testsuiteAttributes.name = testSuite.name; } if (testSuite.hostname) { testsuiteAttributes.hostname = testSuite.hostname; } if (testSuite.time) { testsuiteAttributes.time = testSuite.time.toString(); } if (testSuite.timestamp) { testsuiteAttributes.timestamp = testSuite.timestamp.toISOString(); } 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, }; if (testCase.time) { testcaseAttributes.time = testCase.time.toString(); } if (testCase.assertions) { testcaseAttributes.assertions = testCase.assertions.toString(); } testCaseXmlObject.push({ _attr: testcaseAttributes }); if (testCase.skipped) { testCaseXmlObject.push({ skipped: '' }); } const errors = (Array.isArray(testCase.errors)) ? testCase.errors.map(error => ({ error: formatMessage(error) })) : []; const failures = (Array.isArray(testCase.failures)) ? testCase.failures.map(failure => ({ error: formatMessage(failure) })) : []; const systemOuts = (Array.isArray(testCase.systemOut)) ? testCase.systemOut.map(systemOut => ({ 'system-out': systemOut })) : []; const systemErrs = (Array.isArray(testCase.systemErr)) ? testCase.systemErr.map(systemErr => ({ 'system-err': systemErr })) : []; return testCaseXmlObject.concat(errors).concat(failures).concat(systemOuts).concat(systemErrs); } 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 formatMessage(message: { message: string; type?: string }) { if (typeof message.type === 'string') { return [ message.message, { _attr: { type: message.type } } ]; } return message.message; }