UNPKG

appcenter-cli

Version:

Command line tool for Visual Studio App Center

176 lines (146 loc) 6.22 kB
import * as pfs from "../../../util/misc/promisfied-fs"; import { XmlUtil } from "./xml-util"; import * as fs from "fs"; import * as unzipper from "unzipper"; import { DOMParser } from "xmldom"; export class NUnitXmlUtil extends XmlUtil { async mergeXmlResults(pathToArchive: string): Promise<Document> { const tempPath: string = await pfs.mkTempDir("appcenter-uitestreports"); let mainXml: Document = null; const self: NUnitXmlUtil = this; return this.getMergeXmlResultsPromise(pathToArchive, tempPath, (fullPath: string, relativePath: string) => { const xml: Document = new DOMParser(XmlUtil.DOMParserConfig).parseFromString(fs.readFileSync(fullPath, "utf-8"), "text/xml"); let name: string = "unknown"; const matches: RegExpMatchArray = relativePath.match("^(.*)[_-]nunit[_-]report"); if (matches && matches.length > 1) { name = matches[1].replace(/\./gi, "_"); } self.appendToTestNameTransformation(xml, `_${name}`); self.removeIgnoredTransformation(xml); self.removeEmptySuitesTransformation(xml); if (mainXml) { if (this.isNUnit3(xml)) { mainXml = self.combineNUnit3(mainXml, xml); } else { mainXml = self.combineNUnit2(mainXml, xml); } } else { mainXml = xml; } }, (resolve: Function) => { resolve(mainXml); } ); } public getArchiveName(): string { return "nunit_xml_zip.zip"; } combineNUnit2(xml1: Document, xml2: Document): Document { this.combineResultsAttribute(xml1, xml2, "total"); this.combineResultsAttribute(xml1, xml2, "errors"); this.combineResultsAttribute(xml1, xml2, "failures"); this.combineResultsAttribute(xml1, xml2, "not-run"); this.combineResultsAttribute(xml1, xml2, "inconclusive"); this.combineResultsAttribute(xml1, xml2, "ignored"); this.combineResultsAttribute(xml1, xml2, "skipped"); this.combineResultsAttribute(xml1, xml2, "invalid"); const testSuitesParent: Element = this.collectAllElements(xml1.documentElement, "test-results")[0]; const testSuites: Element[] = this.collectChildren(xml2.documentElement, "test-suite"); testSuites.forEach((child: Element) => { testSuitesParent.appendChild(child); }); return xml1; } combineNUnit3(xml1: Document, xml2: Document): Document { this.combineResultsAttribute(xml1, xml2, "testcasecount"); this.combineResultsAttribute(xml1, xml2, "total"); this.combineResultsAttribute(xml1, xml2, "passed"); this.combineResultsAttribute(xml1, xml2, "failed"); this.combineResultsAttribute(xml1, xml2, "inconclusive"); this.combineResultsAttribute(xml1, xml2, "skipped"); this.combineResultsAttribute(xml1, xml2, "asserts"); const testSuitesParent: Element = this.collectAllElements(xml1.documentElement, "test-run")[0]; const testSuites: Element[] = this.collectChildren(xml2.documentElement, "test-suite"); testSuites.forEach((child: Element) => { testSuitesParent.appendChild(child); }); return xml1; } appendToTestNameTransformation(xml: Document, text: string): void { const testCases: Element[] = this.collectAllElements(xml.documentElement, "test-case"); testCases.forEach((testCase: Element) => { const name: Attr = testCase.attributes.getNamedItem("name"); if (name) { name.value = `${name.value}${text}`; } }); } removeIgnoredTransformation(xml: Document): void { const testResults: Element[] = this.collectAllElements(xml.documentElement, "test-results"); testResults.forEach((testResult: Element) => { const ignoredAttr: Attr = testResult.attributes.getNamedItem("ignored"); if (ignoredAttr) { const notRunAttr: Attr = testResult.attributes.getNamedItem("not-run"); if (notRunAttr) { const notRun: number = Number(notRunAttr.value); const ignored: number = Number(ignoredAttr.value); notRunAttr.value = String(notRun - ignored); } ignoredAttr.value = "0"; } }); const elements: Element[] = this.collectAllElements(xml.documentElement, "test-case"); elements.forEach((element: Element) => { const resultAttr: Attr = element.attributes.getNamedItem("result"); if (resultAttr && resultAttr.value === "Ignored" || resultAttr.value === "Skipped") { element.parentNode.removeChild(element); } }); } removeEmptySuitesTransformation(xml: Document): void { const elements: Element[] = this.collectAllElements(xml.documentElement, "test-suite"); elements.forEach((element: Element) => { if (this.countChildren(element) <= 1) { element.parentNode.removeChild(element); } }); } combineResultsAttribute(xml1: Document, xml2: Document, attributeName: string) { this.addResultsAttribute(xml1, attributeName, this.getResultsAttribute(xml2, attributeName)); } getResultsAttribute(xml: Document, attributeName: string): number { const testResults: Element = this.getResultsNode(xml); if (!testResults) { return 0; } const attr: Attr = testResults.attributes.getNamedItem(attributeName); if (attr.value) { return Number(attr.value); } return 0; } addResultsAttribute(xml: Document, attributeName: string, value: number) { const currentValue: number = this.getResultsAttribute(xml, attributeName); const testResults: Element = this.getResultsNode(xml); if (!testResults) { return; } const attr: Attr = testResults.attributes.getNamedItem(attributeName); if (attr) { attr.value = String(currentValue + value); } } getResultsNode(xml: Document): Element { let testResults: Element[] = this.collectAllElements(xml.documentElement, "test-results"); if (testResults.length === 0) { testResults = this.collectAllElements(xml.documentElement, "test-run"); } return testResults[0]; } isNUnit3(xml: Document): boolean { const testResults: Element[] = this.collectAllElements(xml.documentElement, "test-results"); return testResults.length === 0; } }