Skip to content

Commit 0f51ea7

Browse files
authored
include stackTrace in result exception object (#2371)
1 parent 567a491 commit 0f51ea7

File tree

7 files changed

+124
-63
lines changed

7 files changed

+124
-63
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Please see [CONTRIBUTING.md](./CONTRIBUTING.md) on how to contribute to Cucumber
1010
## [Unreleased]
1111
### Added
1212
- Allow `provided` configuration to be a string ([#2373](https://github.com/cucumber/cucumber-js/pull/2373))
13+
- Include `stackTrace` in result exception object ([#2371](https://github.com/cucumber/cucumber-js/pull/2371))
1314

1415
## [10.2.1] - 2024-01-07
1516
### Fixed

features/support/formatter_output_helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,5 @@ export const ignorableKeys = [
118118
'seconds',
119119
// errors
120120
'message',
121+
'stackTrace',
121122
]

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@
216216
"@cucumber/html-formatter": "21.2.0",
217217
"@cucumber/message-streams": "4.0.1",
218218
"@cucumber/messages": "24.0.1",
219-
"@cucumber/tag-expressions": "6.0.0",
219+
"@cucumber/tag-expressions": "6.1.0",
220220
"assertion-error-formatter": "^3.0.0",
221221
"capital-case": "^1.0.4",
222222
"chalk": "^4.1.2",
@@ -251,7 +251,7 @@
251251
"yup": "1.2.0"
252252
},
253253
"devDependencies": {
254-
"@cucumber/compatibility-kit": "14.1.0",
254+
"@cucumber/compatibility-kit": "15.0.0",
255255
"@cucumber/query": "12.0.1",
256256
"@microsoft/api-extractor": "7.39.0",
257257
"@sinonjs/fake-timers": "10.0.2",

src/runtime/format_error.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,29 @@ export function formatError(
77
error: Error,
88
filterStackTraces: boolean
99
): Pick<TestStepResult, 'message' | 'exception'> {
10-
let filteredStack: string
11-
if (filterStackTraces) {
12-
try {
13-
filteredStack = filterStackTrace(errorStackParser.parse(error))
14-
.map((f) => f.source)
15-
.join('\n')
16-
} catch {
17-
// if we weren't able to parse and filter, we'll settle for the original
18-
}
10+
let processedStackTrace: string
11+
try {
12+
const parsedStack = errorStackParser.parse(error)
13+
const filteredStack = filterStackTraces
14+
? filterStackTrace(parsedStack)
15+
: parsedStack
16+
processedStackTrace = filteredStack.map((f) => f.source).join('\n')
17+
} catch {
18+
// if we weren't able to parse and process, we'll settle for the original
1919
}
2020
const message = format(error, {
2121
colorFns: {
22-
errorStack: (stack: string) =>
23-
filteredStack ? `\n${filteredStack}` : stack,
22+
errorStack: (stack: string) => {
23+
return processedStackTrace ? `\n${processedStackTrace}` : stack
24+
},
2425
},
2526
})
2627
return {
2728
message,
2829
exception: {
2930
type: error.name || 'Error',
3031
message: typeof error === 'string' ? error : error.message,
32+
stackTrace: processedStackTrace ?? error.stack,
3133
},
3234
}
3335
}

src/runtime/format_error_spec.ts

Lines changed: 97 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,111 @@ import { expect } from 'chai'
33
import { formatError } from './format_error'
44

55
describe('formatError', () => {
6-
function testFormatError(fn: () => void, filterStackTraces: boolean = false) {
7-
try {
8-
fn()
9-
return undefined
10-
} catch (error) {
11-
return formatError(error, filterStackTraces)
6+
describe('type and message', () => {
7+
function testFormatError(fn: () => void) {
8+
try {
9+
fn()
10+
return undefined
11+
} catch (error) {
12+
const {
13+
exception: { type, message },
14+
} = formatError(error, false)
15+
return { type, message }
16+
}
1217
}
13-
}
14-
15-
it('should handle a custom error', () => {
16-
expect(
17-
testFormatError(() => {
18-
assert.ok(false, 'Thing that should have been truthy was falsy!')
19-
}).exception
20-
).to.eql({
21-
type: 'AssertionError',
22-
message: 'Thing that should have been truthy was falsy!',
18+
19+
it('should handle a custom error', () => {
20+
expect(
21+
testFormatError(() => {
22+
assert.ok(false, 'Thing that should have been truthy was falsy!')
23+
})
24+
).to.eql({
25+
type: 'AssertionError',
26+
message: 'Thing that should have been truthy was falsy!',
27+
})
2328
})
24-
})
2529

26-
it('should handle a generic error', () => {
27-
expect(
28-
testFormatError(() => {
29-
throw new Error('A generally bad thing happened!')
30-
}).exception
31-
).to.eql({
32-
type: 'Error',
33-
message: 'A generally bad thing happened!',
30+
it('should handle a generic error', () => {
31+
expect(
32+
testFormatError(() => {
33+
throw new Error('A generally bad thing happened!')
34+
})
35+
).to.eql({
36+
type: 'Error',
37+
message: 'A generally bad thing happened!',
38+
})
39+
})
40+
41+
it('should handle an omitted message', () => {
42+
expect(
43+
testFormatError(() => {
44+
throw new Error()
45+
})
46+
).to.eql({
47+
type: 'Error',
48+
message: '',
49+
})
3450
})
35-
})
3651

37-
it('should handle an omitted message', () => {
38-
expect(
39-
testFormatError(() => {
40-
throw new Error()
41-
}).exception
42-
).to.eql({
43-
type: 'Error',
44-
message: '',
52+
it('should handle a thrown string', () => {
53+
expect(
54+
testFormatError(() => {
55+
throw 'Yikes!'
56+
})
57+
).to.eql({
58+
type: 'Error',
59+
message: 'Yikes!',
60+
})
4561
})
4662
})
4763

48-
it('should handle a thrown string', () => {
49-
expect(
50-
testFormatError(() => {
51-
throw 'Yikes!'
52-
}).exception
53-
).to.eql({
54-
type: 'Error',
55-
message: 'Yikes!',
64+
describe('stack traces', () => {
65+
;[false, true].forEach((filterStackTraces) => {
66+
describe('with filterStackTraces=' + filterStackTraces, () => {
67+
function testFormatError(fn: () => void) {
68+
try {
69+
fn()
70+
return undefined
71+
} catch (error) {
72+
const {
73+
exception: { stackTrace },
74+
} = formatError(error, false)
75+
return stackTrace
76+
}
77+
}
78+
79+
it('should handle a custom error', () => {
80+
expect(
81+
testFormatError(() => {
82+
assert.ok(false, 'Thing that should have been truthy was falsy!')
83+
})
84+
).to.have.string(' at ')
85+
})
86+
87+
it('should handle a generic error', () => {
88+
expect(
89+
testFormatError(() => {
90+
throw new Error('A generally bad thing happened!')
91+
})
92+
).to.have.string(' at ')
93+
})
94+
95+
it('should handle an omitted message', () => {
96+
expect(
97+
testFormatError(() => {
98+
throw new Error()
99+
})
100+
).to.have.string(' at ')
101+
})
102+
103+
it('should handle a thrown string', () => {
104+
expect(
105+
testFormatError(() => {
106+
throw 'Yikes!'
107+
})
108+
).to.be.undefined
109+
})
110+
})
56111
})
57112
})
58113
})

src/runtime/test_case_runner_spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ describe('TestCaseRunner', () => {
169169
exception: {
170170
type: 'Error',
171171
message: 'fail',
172+
stackTrace: undefined,
172173
},
173174
}
174175

@@ -316,6 +317,7 @@ describe('TestCaseRunner', () => {
316317
exception: {
317318
type: 'Error',
318319
message: 'Oh no!',
320+
stackTrace: undefined,
319321
},
320322
status: messages.TestStepResultStatus.FAILED,
321323
},

0 commit comments

Comments
 (0)