From c0053f563b744185b98db899b90e801de4712fda Mon Sep 17 00:00:00 2001 From: Maksim Stepanov <17935127+delatrie@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:06:34 +0700 Subject: [PATCH] feat: parentSuite by junit reader --- packages/reader/src/junitxml/index.ts | 26 ++++++++++--- packages/reader/test/junitxml.test.ts | 37 +++++++++++++++++++ .../suites/aggregatedPackageInvalid.xml | 9 +++++ .../suites/aggregatedPackageMissing.xml | 6 +++ .../labels/suites/wellDefinedAggregated.xml | 6 +++ 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageInvalid.xml create mode 100644 packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageMissing.xml create mode 100644 packages/reader/test/resources/junitxmldata/labels/suites/wellDefinedAggregated.xml diff --git a/packages/reader/src/junitxml/index.ts b/packages/reader/src/junitxml/index.ts index 3700728..29e5835 100644 --- a/packages/reader/src/junitxml/index.ts +++ b/packages/reader/src/junitxml/index.ts @@ -20,6 +20,7 @@ const STDOUT_ATTACHMENT_NAME = "System output"; const STDERR_ATTACHMENT_NAME = "System error"; const SUITE_PACKAGE_NAME = "package"; +const SUITE_PARENT_LABEL_NAME = "parentSuite"; const SUITE_LABEL_NAME = "suite"; const TEST_CLASS_LABEL_NAME = "testClass"; @@ -90,7 +91,7 @@ const parseRootElement = async (visitor: ResultsVisitor, xml: Record) => { +const parseTestSuite = async (visitor: ResultsVisitor, testSuite: Record, isAggregated: boolean) => { const { name, package: packageAttribute, testcase } = testSuite; if (!isStringAnyRecordArray(testcase)) { @@ -115,6 +116,7 @@ const parseTestSuite = async (visitor: ResultsVisitor, testSuite: Record, + isAggregated: boolean, ) => { const { "name": nameAttribute, @@ -151,7 +154,7 @@ const parseTestCase = async ( message, trace, steps: await parseAttachments(visitor, systemOut, systemErr), - labels: convertLabels(suitePackage, suiteName, className), + labels: convertLabels({ suitePackage, suiteName, className, isAggregated }), }, { readerId }, ); @@ -188,11 +191,24 @@ const visitPlainTextAttachment = async ( }; }; -const convertLabels = (suitePackage?: string, suiteName?: string, className?: string) => { +const convertLabels = ({ + suitePackage, + suiteName, + className, + isAggregated, +}: { + suitePackage: string | undefined; + suiteName: string | undefined; + className: string | undefined; + isAggregated: boolean; +}) => { const labels: RawTestLabel[] = []; if (suitePackage) { labels.push({ name: SUITE_PACKAGE_NAME, value: suitePackage }); + if (isAggregated) { + labels.push({ name: SUITE_PARENT_LABEL_NAME, value: suitePackage }); + } } if (suiteName) { diff --git a/packages/reader/test/junitxml.test.ts b/packages/reader/test/junitxml.test.ts index 0f58597..955be6f 100644 --- a/packages/reader/test/junitxml.test.ts +++ b/packages/reader/test/junitxml.test.ts @@ -97,6 +97,43 @@ describe("junit xml reader", () => { expect(trs).toMatchObject([{ labels: expect.not.arrayContaining([{ name: "suite" }]) }]); }); + + // See https://github.com/windyroad/JUnit-Schema/blob/cfa434d4b8e102a8f55b8727b552a0063ee9044e/JUnit.xsd#L173 + it("should add package as parent suite for an aggregated document", async () => { + const visitor = await readResults(junitXml, { + "junitxmldata/labels/suites/wellDefinedAggregated.xml": randomTestsuiteFileName(), + }); + + expect(visitor.visitTestResult).toHaveBeenCalledTimes(1); + + const trs = visitor.visitTestResult.mock.calls.map((c) => c[0]); + + expect(trs).toMatchObject([{ labels: expect.arrayContaining([{ name: "parentSuite", value: "foo" }]) }]); + }); + + it("should ignore a missing package of an aggregated document", async () => { + const visitor = await readResults(junitXml, { + "junitxmldata/labels/suites/aggregatedPackageMissing.xml": randomTestsuiteFileName(), + }); + + expect(visitor.visitTestResult).toHaveBeenCalledTimes(1); + + const trs = visitor.visitTestResult.mock.calls.map((c) => c[0]); + + expect(trs).toMatchObject([{ labels: expect.not.arrayContaining([{ name: "parentSuite" }]) }]); + }); + + it("should ignore an ill-formed package of an aggregated document", async () => { + const visitor = await readResults(junitXml, { + "junitxmldata/labels/suites/aggregatedPackageInvalid.xml": randomTestsuiteFileName(), + }); + + expect(visitor.visitTestResult).toHaveBeenCalledTimes(1); + + const trs = visitor.visitTestResult.mock.calls.map((c) => c[0]); + + expect(trs).toMatchObject([{ labels: expect.not.arrayContaining([{ name: "parentSuite" }]) }]); + }); }); describe("testClass", () => { diff --git a/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageInvalid.xml b/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageInvalid.xml new file mode 100644 index 0000000..d709228 --- /dev/null +++ b/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageInvalid.xml @@ -0,0 +1,9 @@ + + + + + bar + + + + \ No newline at end of file diff --git a/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageMissing.xml b/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageMissing.xml new file mode 100644 index 0000000..763d33c --- /dev/null +++ b/packages/reader/test/resources/junitxmldata/labels/suites/aggregatedPackageMissing.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/reader/test/resources/junitxmldata/labels/suites/wellDefinedAggregated.xml b/packages/reader/test/resources/junitxmldata/labels/suites/wellDefinedAggregated.xml new file mode 100644 index 0000000..2a90a0d --- /dev/null +++ b/packages/reader/test/resources/junitxmldata/labels/suites/wellDefinedAggregated.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file