Skip to content

Commit e2b4060

Browse files
committed
Add --skip-stdout and --skip-stderr options and extend attachment extraction
Adds two new command-line options for junit-upload and playwright-json-upload commands: - --skip-stdout: Control when to skip stdout from test results (on-success|never) - --skip-stderr: Control when to skip stderr from test results (on-success|never) Both options default to "never" (current behavior - always include output). When set to "on-success", stdout/stderr is excluded from passed tests but always included for failed, blocked, or skipped tests. This helps reduce payload size when tests have verbose logging while preserving debugging information for failures. Additionally, attachment extraction for JUnit XML has been extended to parse attachment markers from failure, error, and skipped element message attributes and text content, not just from system-out. This supports custom test framework configurations that embed attachment paths in error messages. Changes: - Added --skip-stdout and --skip-stderr command-line options to ResultUploadCommandModule - Updated Parser type signature to accept ParserOptions - Implemented conditional stdout/stderr filtering in junitXmlParser and playwrightJsonParser - Extended junitXmlParser to extract attachments from failure/error/skipped elements - Added comprehensive test coverage for new functionality - Updated README.md with usage examples Version bump: 0.4.1 → 0.4.2
1 parent d08d7bf commit e2b4060

File tree

9 files changed

+447
-54
lines changed

9 files changed

+447
-54
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ The `junit-upload` and `playwright-json-upload` commands upload test results fro
6969
- `--attachments` - Try to detect and upload any attachments with the test result
7070
- `--force` - Ignore API request errors, invalid test cases, or attachments
7171
- `--ignore-unmatched` - Suppress individual unmatched test messages, show summary only
72+
- `--skip-stdout` - Control when to skip stdout from test results (choices: `on-success`, `never`; default: `never`)
73+
- `--skip-stderr` - Control when to skip stderr from test results (choices: `on-success`, `never`; default: `never`)
7274
- `-h, --help` - Show command help
7375

7476
### Run Name Template Placeholders
@@ -137,6 +139,18 @@ Ensure the required environment variables are defined before running these comma
137139
```
138140
This will show only a summary like "Skipped 5 unmatched tests" instead of individual error messages for each unmatched test.
139141
142+
9. Skip stdout/stderr for passed tests to reduce result payload size:
143+
```bash
144+
qasphere junit-upload --skip-stdout on-success ./test-results.xml
145+
```
146+
This will exclude stdout from passed tests while still including it for failed, blocked, or skipped tests.
147+
148+
10. Skip both stdout and stderr for passed tests:
149+
```bash
150+
qasphere junit-upload --skip-stdout on-success --skip-stderr on-success ./test-results.xml
151+
```
152+
This is useful when you have verbose logging in tests but only want to see output for failures.
153+
140154
## Test Report Requirements
141155
142156
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.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "qas-cli",
3-
"version": "0.4.1",
3+
"version": "0.4.2",
44
"description": "QAS CLI is a command line tool for submitting your automation test results to QA Sphere at https://qasphere.com/",
55
"type": "module",
66
"main": "./build/bin/qasphere.js",

src/commands/resultUpload.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ export class ResultUploadCommandModule implements CommandModule<unknown, ResultU
5353
describe: 'Suppress individual unmatched test messages, show summary only',
5454
type: 'boolean',
5555
},
56+
'skip-stdout': {
57+
describe: 'When to skip stdout from test results',
58+
type: 'string',
59+
choices: ['on-success', 'never'] as const,
60+
default: 'never' as const,
61+
},
62+
'skip-stderr': {
63+
describe: 'When to skip stderr from test results',
64+
type: 'string',
65+
choices: ['on-success', 'never'] as const,
66+
default: 'never' as const,
67+
},
5668
help: {
5769
alias: 'h',
5870
help: true,
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<testsuites tests="4" failures="1" errors="0" skipped="0">
3+
<testsuite name="Content display" timestamp="2025-11-06T19:38:02" time="16.606" tests="4" failures="1" errors="0" skipped="0">
4+
<properties>
5+
<property name="specId" value="0"/>
6+
<property name="suiteName" value="Content display"/>
7+
<property name="capabilities" value="chrome.142_0_7444_60.mac"/>
8+
<property name="file" value="file://./test/specs/contents.e2e.ts"/>
9+
</properties>
10+
<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">
11+
<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
12+
13+
Expected: "Welcome to Bistro Delivery1"
14+
Received: "Welcome to Bistro Delivery"
15+
at Context.<anonymous> (/Users/a/Developer/Hypersequent/bistro-e2e-webdriver/test/specs/contents.e2e.ts:12:21)]]></failure>
16+
<system-out><![CDATA[
17+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
18+
]]></system-out>
19+
<system-err><![CDATA[
20+
Error: expect(received).toBe(expected) // Object.is equality
21+
22+
Expected: "Welcome to Bistro Delivery1"
23+
Received: "Welcome to Bistro Delivery"
24+
at Context.<anonymous> (/Users/a/Developer/Hypersequent/bistro-e2e-webdriver/test/specs/contents.e2e.ts:12:21)
25+
]]></system-err>
26+
</testcase>
27+
<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">
28+
<system-out><![CDATA[
29+
RESULT: {}
30+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.12/text - {}
31+
RESULT: {}
32+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.12/attribute/class - {}
33+
RESULT: {}
34+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.13/text - {}
35+
RESULT: {}
36+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.13/attribute/class - {}
37+
RESULT: {}
38+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.14/text - {}
39+
RESULT: {}
40+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.F12651217887B7218F02B630A2CE5981.e.14/attribute/class - {}
41+
RESULT: {}
42+
COMMAND: POST /session/aeb3cc104d7c990baa142d47e9a07e78/refresh - {}
43+
RESULT: {}
44+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
45+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
46+
RESULT: {}
47+
RESULT: {}
48+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.27/css/display - {}
49+
RESULT: {}
50+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.28/text - {}
51+
RESULT: {}
52+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.28/attribute/class - {}
53+
RESULT: {}
54+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.29/text - {}
55+
RESULT: {}
56+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.29/attribute/class - {}
57+
RESULT: {}
58+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.30/text - {}
59+
RESULT: {}
60+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.A070D46FB18647D0A8B43910587F4FC5.e.30/attribute/class - {}
61+
RESULT: {}
62+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.33/text - {}
63+
RESULT: {}
64+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.33/attribute/class - {}
65+
RESULT: {}
66+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.34/text - {}
67+
RESULT: {}
68+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.34/attribute/class - {}
69+
RESULT: {}
70+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.35/text - {}
71+
RESULT: {}
72+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.427C0127B97BD750ED14AC6CF8453C40.e.35/attribute/class - {}
73+
RESULT: {}
74+
]]></system-out>
75+
</testcase>
76+
<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">
77+
<system-out><![CDATA[
78+
COMMAND: POST /session/aeb3cc104d7c990baa142d47e9a07e78/refresh - {}
79+
RESULT: {}
80+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
81+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
82+
RESULT: {}
83+
RESULT: {}
84+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.48/css/display - {}
85+
RESULT: {}
86+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
87+
RESULT: {}
88+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
89+
RESULT: {}
90+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
91+
RESULT: {}
92+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
93+
RESULT: {}
94+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
95+
RESULT: {}
96+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
97+
RESULT: {}
98+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
99+
RESULT: {}
100+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
101+
RESULT: {}
102+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
103+
RESULT: {}
104+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
105+
RESULT: {}
106+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
107+
RESULT: {}
108+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
109+
RESULT: {}
110+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/text - {}
111+
RESULT: {}
112+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.51/attribute/class - {}
113+
RESULT: {}
114+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/text - {}
115+
RESULT: {}
116+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.49/attribute/class - {}
117+
RESULT: {}
118+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/text - {}
119+
RESULT: {}
120+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/element/f.E3584DA9C1D58D38C87AA03B59F633BD.d.2EAD87E4F34ECC43B3DD3AE08892BAA5.e.52/attribute/class - {}
121+
RESULT: {}
122+
]]></system-out>
123+
</testcase>
124+
<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">
125+
<system-out><![CDATA[
126+
COMMAND: GET /session/aeb3cc104d7c990baa142d47e9a07e78/window - {}
127+
COMMAND: DELETE /session/aeb3cc104d7c990baa142d47e9a07e78 - {}
128+
RESULT: {}
129+
RESULT: {}
130+
]]></system-out>
131+
</testcase>
132+
</testsuite>
133+
</testsuites>

src/tests/junit-xml-parsing.spec.ts

Lines changed: 139 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ describe('Junit XML parsing', () => {
1010
const xmlContent = await readFile(xmlPath, 'utf8')
1111

1212
// This should not throw any exceptions
13-
const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
13+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
14+
skipStdout: 'never',
15+
skipStderr: 'never',
16+
})
1417

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

51-
const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
54+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
55+
skipStdout: 'never',
56+
skipStderr: 'never',
57+
})
5258

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

81-
const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
87+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
88+
skipStdout: 'never',
89+
skipStderr: 'never',
90+
})
8291
expect(testcases).toHaveLength(1)
8392

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

95-
const testcases = await parseJUnitXml(xmlContent, xmlBasePath)
104+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
105+
skipStdout: 'never',
106+
skipStderr: 'never',
107+
})
96108
expect(testcases).toHaveLength(3)
97109

98110
// Verify test result types
@@ -110,4 +122,127 @@ describe('Junit XML parsing', () => {
110122
expect(failedTest?.name).toContain('subtracts two numbers correctly')
111123
expect(failedTest?.message).toContain('expect(received).toBe(expected)')
112124
})
125+
126+
test('Should extract attachments from failure/error message attributes (WebDriverIO style)', async () => {
127+
const xmlPath = `${xmlBasePath}/webdriverio-real.xml`
128+
const xmlContent = await readFile(xmlPath, 'utf8')
129+
130+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
131+
skipStdout: 'never',
132+
skipStderr: 'never',
133+
})
134+
expect(testcases).toHaveLength(4)
135+
136+
// Find the test case BD-055 which has a failure element with attachment in the message attribute
137+
const bd055 = testcases.find((tc) => tc.name.includes('BD-055'))
138+
expect(bd055).toBeDefined()
139+
expect(bd055?.status).toBe('failed')
140+
141+
// This test should have an attachment extracted from the failure message attribute
142+
// This is the WebDriverIO style where attachments are embedded in the failure message
143+
expect(bd055?.attachments.length).toBeGreaterThan(0)
144+
expect(bd055?.attachments[0].filename).toContain('BD_055')
145+
expect(bd055?.attachments[0].filename).toContain('.png')
146+
})
147+
148+
test('Should include stdout/stderr when skipStdout and skipStderr are set to "never"', async () => {
149+
const xmlPath = `${xmlBasePath}/empty-system-err.xml`
150+
const xmlContent = await readFile(xmlPath, 'utf8')
151+
152+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
153+
skipStdout: 'never',
154+
skipStderr: 'never',
155+
})
156+
157+
expect(testcases).toHaveLength(1)
158+
expect(testcases[0].status).toBe('passed')
159+
// Should include stdout content
160+
expect(testcases[0].message).toContain('ViewManager initialized')
161+
})
162+
163+
test('Should skip stdout for passed tests when skipStdout is set to "on-success"', async () => {
164+
const xmlPath = `${xmlBasePath}/empty-system-err.xml`
165+
const xmlContent = await readFile(xmlPath, 'utf8')
166+
167+
const testcases = await parseJUnitXml(xmlContent, xmlBasePath, {
168+
skipStdout: 'on-success',
169+
skipStderr: 'never',
170+
})
171+
172+
expect(testcases).toHaveLength(1)
173+
expect(testcases[0].status).toBe('passed')
174+
// Should NOT include stdout content for passed tests
175+
expect(testcases[0].message).not.toContain('ViewManager initialized')
176+
expect(testcases[0].message).toBe('')
177+
})
178+
179+
test('Should skip stderr for passed tests when skipStderr is set to "on-success"', async () => {
180+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
181+
<testsuites name="Test Suite">
182+
<testsuite name="Sample Suite">
183+
<testcase name="Test with stderr">
184+
<system-out>stdout content</system-out>
185+
<system-err>stderr content</system-err>
186+
</testcase>
187+
</testsuite>
188+
</testsuites>`
189+
190+
const testcases = await parseJUnitXml(xml, xmlBasePath, {
191+
skipStdout: 'never',
192+
skipStderr: 'on-success',
193+
})
194+
195+
expect(testcases).toHaveLength(1)
196+
expect(testcases[0].status).toBe('passed')
197+
// Should include stdout but not stderr for passed tests
198+
expect(testcases[0].message).toContain('stdout content')
199+
expect(testcases[0].message).not.toContain('stderr content')
200+
})
201+
202+
test('Should include stdout/stderr for failed tests even when skip options are set to "on-success"', async () => {
203+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
204+
<testsuites name="Test Suite">
205+
<testsuite name="Sample Suite">
206+
<testcase name="Failed test with output">
207+
<failure message="Test failed">Failure details</failure>
208+
<system-out>stdout from failed test</system-out>
209+
<system-err>stderr from failed test</system-err>
210+
</testcase>
211+
</testsuite>
212+
</testsuites>`
213+
214+
const testcases = await parseJUnitXml(xml, xmlBasePath, {
215+
skipStdout: 'on-success',
216+
skipStderr: 'on-success',
217+
})
218+
219+
expect(testcases).toHaveLength(1)
220+
expect(testcases[0].status).toBe('failed')
221+
// Should include both stdout and stderr for failed tests
222+
expect(testcases[0].message).toContain('Failure details')
223+
expect(testcases[0].message).toContain('stdout from failed test')
224+
expect(testcases[0].message).toContain('stderr from failed test')
225+
})
226+
227+
test('Should skip both stdout and stderr for passed tests when both skip options are set to "on-success"', async () => {
228+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
229+
<testsuites name="Test Suite">
230+
<testsuite name="Sample Suite">
231+
<testcase name="Passed test with output">
232+
<system-out>stdout content</system-out>
233+
<system-err>stderr content</system-err>
234+
</testcase>
235+
</testsuite>
236+
</testsuites>`
237+
238+
const testcases = await parseJUnitXml(xml, xmlBasePath, {
239+
skipStdout: 'on-success',
240+
skipStderr: 'on-success',
241+
})
242+
243+
expect(testcases).toHaveLength(1)
244+
expect(testcases[0].status).toBe('passed')
245+
// Should not include stdout or stderr for passed tests
246+
expect(testcases[0].message).toBe('')
247+
})
113248
})

0 commit comments

Comments
 (0)