Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ The `junit-upload` and `playwright-json-upload` commands upload test results fro
- `--attachments` - Try to detect and upload any attachments with the test result
- `--force` - Ignore API request errors, invalid test cases, or attachments
- `--ignore-unmatched` - Suppress individual unmatched test messages, show summary only
- `--skip-report-stdout` - Control when to skip stdout blocks from test report (choices: `on-success`, `never`; default: `never`)
- `--skip-report-stderr` - Control when to skip stderr blocks from test report (choices: `on-success`, `never`; default: `never`)
Comment on lines +72 to +73

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These option names are a bit long, and there's an inconsistency with the PR description which uses --skip-stdout and --skip-stderr. For better CLI usability and consistency, consider renaming --skip-report-stdout and --skip-report-stderr to the shorter --skip-stdout and --skip-stderr respectively. This change would need to be applied in src/commands/resultUpload.ts and src/utils/result-upload/ResultUploadCommandHandler.ts as well.

- `-h, --help` - Show command help

### Run Name Template Placeholders
Expand Down Expand Up @@ -137,6 +139,18 @@ Ensure the required environment variables are defined before running these comma
```
This will show only a summary like "Skipped 5 unmatched tests" instead of individual error messages for each unmatched test.

9. Skip stdout/stderr for passed tests to reduce result payload size:
```bash
qasphere junit-upload --skip-report-stdout on-success ./test-results.xml
```
This will exclude stdout from passed tests while still including it for failed, blocked, or skipped tests.

Skip both stdout and stderr for passed tests:
```bash
qasphere junit-upload --skip-report-stdout on-success --skip-report-stderr on-success ./test-results.xml
```
This is useful when you have verbose logging in tests but only want to see output for failures.

## Test Report Requirements

The QAS CLI requires test cases in your reports (JUnit XML or Playwright JSON) to reference corresponding test cases in QA Sphere. These references are used to map test results from your automation to the appropriate test cases in QA Sphere. If a report lacks these references or the referenced test case doesn't exist in QA Sphere, the tool will display an error message.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "qas-cli",
"version": "0.4.1",
"version": "0.4.2",
"description": "QAS CLI is a command line tool for submitting your automation test results to QA Sphere at https://qasphere.com/",
"type": "module",
"main": "./build/bin/qasphere.js",
Expand Down
12 changes: 12 additions & 0 deletions src/commands/resultUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ export class ResultUploadCommandModule implements CommandModule<unknown, ResultU
describe: 'Suppress individual unmatched test messages, show summary only',
type: 'boolean',
},
'skip-report-stdout': {
describe: 'When to skip stdout from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},
'skip-report-stderr': {
describe: 'When to skip stderr from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},
Comment on lines +56 to +67

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PR title and description use --skip-stdout and --skip-stderr, but the implementation uses the longer --skip-report-stdout and --skip-report-stderr. Shorter option names are generally better for command-line usability. I suggest renaming the options for consistency and brevity. This change would also need to be applied in README.md and src/utils/result-upload/ResultUploadCommandHandler.ts.

Suggested change
'skip-report-stdout': {
describe: 'When to skip stdout from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},
'skip-report-stderr': {
describe: 'When to skip stderr from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},
'skip-stdout': {
describe: 'When to skip stdout from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},
'skip-stderr': {
describe: 'When to skip stderr from test results',
type: 'string',
choices: ['on-success', 'never'] as const,
default: 'never' as const,
},

help: {
alias: 'h',
help: true,
Expand Down
133 changes: 133 additions & 0 deletions src/tests/fixtures/junit-xml/webdriverio-real.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="4" failures="1" errors="0" skipped="0">
<testsuite name="Content display" timestamp="2025-11-06T19:38:02" time="16.606" tests="4" failures="1" errors="0" skipped="0">
<properties>
<property name="specId" value="0"/>
<property name="suiteName" value="Content display"/>
<property name="capabilities" value="chrome.142_0_7444_60.mac"/>
<property name="file" value="file://./test/specs/contents.e2e.ts"/>
</properties>
<testcase classname="chrome.142_0_7444_60.mac.Content_display" name="BD-055: User should see the content according to the About Us information" time="1.34" file="file://./test/specs/contents.e2e.ts">
<failure message="expect(received).toBe(expected) // Object.is equality&#xA;&#xA;Expected: &quot;Welcome to Bistro Delivery1&quot;&#xA;Received: &quot;Welcome to Bistro Delivery&quot;&#xA;&#xA;[[ATTACHMENT|./screenshots/BD_055_User_should_see_the_content_according_to_th_2025-11-06T15-38-03-728Z.png]]"><![CDATA[Error: expect(received).toBe(expected) // Object.is equality

Expected: "Welcome to Bistro Delivery1"
Received: "Welcome to Bistro Delivery"
at Context.<anonymous> (/Users/a/Developer/Hypersequent/bistro-e2e-webdriver/test/specs/contents.e2e.ts:12:21)]]></failure>
<system-out><![CDATA[
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
]]></system-out>
<system-err><![CDATA[
Error: expect(received).toBe(expected) // Object.is equality

Expected: "Welcome to Bistro Delivery1"
Received: "Welcome to Bistro Delivery"
at Context.<anonymous> (/Users/a/Developer/Hypersequent/bistro-e2e-webdriver/test/specs/contents.e2e.ts:12:21)
]]></system-err>
</testcase>
<testcase classname="chrome.142_0_7444_60.mac.Content_display" name="BD-026: Correct display of blocks and buttons in the navbar" time="9.26" file="file://./test/specs/contents.e2e.ts">
<system-out><![CDATA[
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.12/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.12/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.13/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.13/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.14/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.14/attribute/class - {}
RESULT: {}
COMMAND: POST /session/aeb3cc104d7c990baa142d47e9a07e78/refresh - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
RESULT: {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.27/css/display - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.28/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.28/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.29/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.29/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.30/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.30/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.33/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.33/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.34/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.34/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.35/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.35/attribute/class - {}
RESULT: {}
]]></system-out>
</testcase>
<testcase classname="chrome.142_0_7444_60.mac.Content_display" name="BD-038: User should see the Pizzas list by default on the Todays Menu block" time="5.3" file="file://./test/specs/contents.e2e.ts">
<system-out><![CDATA[
COMMAND: POST /session/aeb3cc104d7c990baa142d47e9a07e78/refresh - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
RESULT: {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.48/css/display - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
RESULT: {}
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
RESULT: {}
]]></system-out>
</testcase>
<testcase classname="chrome.142_0_7444_60.mac.Content_display" name="BD-052: User should see the Todays Menu block after clicking the Todays Menu button in the Welcome banner" time="0.701" file="file://./test/specs/contents.e2e.ts">
<system-out><![CDATA[
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
COMMAND: DELETE /session/aeb3cc104d7c990baa142d47e9a07e78 - {}
RESULT: {}
RESULT: {}
]]></system-out>
</testcase>
</testsuite>
</testsuites>
143 changes: 139 additions & 4 deletions src/tests/junit-xml-parsing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ describe('Junit XML parsing', () => {
const xmlContent = await readFile(xmlPath, 'utf8')

// This should not throw any exceptions
const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})

// Verify that we got the expected number of test cases
expect(testcases).toHaveLength(12)
Expand Down Expand Up @@ -48,7 +51,10 @@ describe('Junit XML parsing', () => {
const xmlPath = `${xmlBasePath}/comprehensive-test.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})

// Test specific scenarios from our comprehensive test
const failureTests = testcases.filter((tc) => tc.status === 'failed')
Expand Down Expand Up @@ -78,7 +84,10 @@ describe('Junit XML parsing', () => {
const xmlPath = `${xmlBasePath}/empty-system-err.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})
expect(testcases).toHaveLength(1)

// Should parse as success (no failure/error/skipped present)
Expand All @@ -92,7 +101,10 @@ describe('Junit XML parsing', () => {
const xmlPath = `${xmlBasePath}/jest-failure-type-missing.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})
expect(testcases).toHaveLength(3)

// Verify test result types
Expand All @@ -110,4 +122,127 @@ describe('Junit XML parsing', () => {
expect(failedTest?.name).toContain('subtracts two numbers correctly')
expect(failedTest?.message).toContain('expect(received).toBe(expected)')
})

test('Should extract attachments from failure/error message attributes (WebDriverIO style)', async () => {
const xmlPath = `${xmlBasePath}/webdriverio-real.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})
expect(testcases).toHaveLength(4)

// Find the test case BD-055 which has a failure element with attachment in the message attribute
const bd055 = testcases.find((tc) => tc.name.includes('BD-055'))
expect(bd055).toBeDefined()
expect(bd055?.status).toBe('failed')

// This test should have an attachment extracted from the failure message attribute
// This is the WebDriverIO style where attachments are embedded in the failure message
expect(bd055?.attachments.length).toBeGreaterThan(0)
expect(bd055?.attachments[0].filename).toContain('BD_055')
expect(bd055?.attachments[0].filename).toContain('.png')
})

test('Should include stdout/stderr when skipStdout and skipStderr are set to "never"', async () => {
const xmlPath = `${xmlBasePath}/empty-system-err.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'never',
})

expect(testcases).toHaveLength(1)
expect(testcases[0].status).toBe('passed')
// Should include stdout content
expect(testcases[0].message).toContain('ViewManager initialized')
})

test('Should skip stdout for passed tests when skipStdout is set to "on-success"', async () => {
const xmlPath = `${xmlBasePath}/empty-system-err.xml`
const xmlContent = await readFile(xmlPath, 'utf8')

const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
skipStdout: 'on-success',
skipStderr: 'never',
})

expect(testcases).toHaveLength(1)
expect(testcases[0].status).toBe('passed')
// Should NOT include stdout content for passed tests
expect(testcases[0].message).not.toContain('ViewManager initialized')
expect(testcases[0].message).toBe('')
})

test('Should skip stderr for passed tests when skipStderr is set to "on-success"', async () => {
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Test Suite">
<testsuite name="Sample Suite">
<testcase name="Test with stderr">
<system-out>stdout content</system-out>
<system-err>stderr content</system-err>
</testcase>
</testsuite>
</testsuites>`

const testcases = await parseJUnitXml(xml, xmlBasePath, {
skipStdout: 'never',
skipStderr: 'on-success',
})

expect(testcases).toHaveLength(1)
expect(testcases[0].status).toBe('passed')
// Should include stdout but not stderr for passed tests
expect(testcases[0].message).toContain('stdout content')
expect(testcases[0].message).not.toContain('stderr content')
})

test('Should include stdout/stderr for failed tests even when skip options are set to "on-success"', async () => {
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Test Suite">
<testsuite name="Sample Suite">
<testcase name="Failed test with output">
<failure message="Test failed">Failure details</failure>
<system-out>stdout from failed test</system-out>
<system-err>stderr from failed test</system-err>
</testcase>
</testsuite>
</testsuites>`

const testcases = await parseJUnitXml(xml, xmlBasePath, {
skipStdout: 'on-success',
skipStderr: 'on-success',
})

expect(testcases).toHaveLength(1)
expect(testcases[0].status).toBe('failed')
// Should include both stdout and stderr for failed tests
expect(testcases[0].message).toContain('Failure details')
expect(testcases[0].message).toContain('stdout from failed test')
expect(testcases[0].message).toContain('stderr from failed test')
})

test('Should skip both stdout and stderr for passed tests when both skip options are set to "on-success"', async () => {
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Test Suite">
<testsuite name="Sample Suite">
<testcase name="Passed test with output">
<system-out>stdout content</system-out>
<system-err>stderr content</system-err>
</testcase>
</testsuite>
</testsuites>`

const testcases = await parseJUnitXml(xml, xmlBasePath, {
skipStdout: 'on-success',
skipStderr: 'on-success',
})

expect(testcases).toHaveLength(1)
expect(testcases[0].status).toBe('passed')
// Should not include stdout or stderr for passed tests
expect(testcases[0].message).toBe('')
})
})
Loading