@@ -163,13 +163,51 @@ function compareCompletion(
163
163
req : coresdk . workflow_completion . IWorkflowActivationCompletion ,
164
164
expected : coresdk . workflow_completion . IWorkflowActivationCompletion
165
165
) {
166
+ const stackTraces = extractFailureStackTraces ( req , expected ) ;
166
167
t . deepEqual (
167
168
coresdk . workflow_completion . WorkflowActivationCompletion . create ( req ) . toJSON ( ) ,
168
169
coresdk . workflow_completion . WorkflowActivationCompletion . create ( {
169
170
...expected ,
170
171
runId : t . context . runId ,
171
172
} ) . toJSON ( )
172
173
) ;
174
+
175
+ if ( stackTraces ) {
176
+ for ( const { actual, expected } of stackTraces ) {
177
+ compareStackTrace ( t , actual , expected ) ;
178
+ }
179
+ }
180
+ }
181
+
182
+ // Extracts failure stack traces from completions if structure matches, leaving them unchanged if structure differs.
183
+ // We leave them unchanged on structure differences as ava's `deepEqual` provides a better failure message.
184
+ function extractFailureStackTraces (
185
+ req : coresdk . workflow_completion . IWorkflowActivationCompletion ,
186
+ expected : coresdk . workflow_completion . IWorkflowActivationCompletion
187
+ ) : { actual : string ; expected : string } [ ] | undefined {
188
+ const reqCommands = req . successful ?. commands ;
189
+ const expectedCommands = expected . successful ?. commands ;
190
+ if ( ! reqCommands || ! expectedCommands || reqCommands . length !== expectedCommands . length ) {
191
+ return ;
192
+ }
193
+ for ( let commandIndex = 0 ; commandIndex < reqCommands . length ; commandIndex ++ ) {
194
+ const reqStack = reqCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
195
+ const expectedStack = expectedCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
196
+ if ( typeof reqStack !== typeof expectedStack ) {
197
+ return ;
198
+ }
199
+ }
200
+ const stackTraces : { actual : string ; expected : string } [ ] = [ ] ;
201
+ for ( let commandIndex = 0 ; commandIndex < reqCommands . length ; commandIndex ++ ) {
202
+ const reqStack = reqCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
203
+ const expectedStack = expectedCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
204
+ if ( reqStack && expectedStack ) {
205
+ stackTraces . push ( { actual : reqStack , expected : expectedStack } ) ;
206
+ delete reqCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
207
+ delete expectedCommands [ commandIndex ] . failWorkflowExecution ?. failure ?. stackTrace ;
208
+ }
209
+ }
210
+ return stackTraces ;
173
211
}
174
212
175
213
function makeSuccess (
@@ -307,12 +345,13 @@ function makeCompleteWorkflowExecution(result?: Payload): coresdk.workflow_comma
307
345
308
346
function makeFailWorkflowExecution (
309
347
message : string ,
348
+ stackTrace ?: string ,
310
349
type = 'Error' ,
311
350
nonRetryable = true
312
351
) : coresdk . workflow_commands . IWorkflowCommand {
313
352
return {
314
353
failWorkflowExecution : {
315
- failure : { message, applicationFailureInfo : { type, nonRetryable } , source : 'TypeScriptSDK' } ,
354
+ failure : { message, stackTrace , applicationFailureInfo : { type, nonRetryable } , source : 'TypeScriptSDK' } ,
316
355
} ,
317
356
} ;
318
357
}
@@ -452,28 +491,22 @@ function cleanWorkflowQueryFailureStackTrace(
452
491
return req ;
453
492
}
454
493
455
- function removeWorkflowFailureStackTrace (
456
- req : coresdk . workflow_completion . IWorkflowActivationCompletion ,
457
- commandIndex = 0
458
- ) {
459
- const stackTrace = req . successful ! . commands ! [ commandIndex ] . failWorkflowExecution ! . failure ! . stackTrace ! ;
460
- delete req . successful ! . commands ! [ commandIndex ] . failWorkflowExecution ! . failure ! . stackTrace ;
461
- return stackTrace ;
462
- }
463
-
464
494
test ( 'throwAsync' , async ( t ) => {
465
495
const { workflowType } = t . context ;
466
496
const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) ) ;
467
- const actualStackTrace = removeWorkflowFailureStackTrace ( req ) ;
468
- compareCompletion ( t , req , makeSuccess ( [ makeFailWorkflowExecution ( 'failure' ) ] ) ) ;
469
- compareStackTrace (
497
+ compareCompletion (
470
498
t ,
471
- actualStackTrace ,
472
- dedent `
499
+ req ,
500
+ makeSuccess ( [
501
+ makeFailWorkflowExecution (
502
+ 'failure' ,
503
+ dedent `
473
504
ApplicationFailure: failure
474
505
at $CLASS.nonRetryable (common/src/failure.ts)
475
506
at throwAsync (test/src/workflows/throw-async.ts)
476
507
`
508
+ ) ,
509
+ ] )
477
510
) ;
478
511
} ) ;
479
512
@@ -773,25 +806,26 @@ test('interruptableWorkflow', async (t) => {
773
806
const req = cleanWorkflowFailureStackTrace (
774
807
await activate ( t , await makeSignalWorkflow ( 'interrupt' , [ 'just because' ] ) )
775
808
) ;
776
- const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
777
809
compareCompletion (
778
810
t ,
779
811
req ,
780
812
makeSuccess (
781
- [ makeFailWorkflowExecution ( 'just because' , 'Error' , false ) ] ,
782
- [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
783
- )
784
- ) ;
785
- compareStackTrace (
786
- t ,
787
- stackTrace ,
788
- // The stack trace is weird here and might confuse users, it might be a JS limitation
789
- // since the Error stack trace is generated in the constructor.
790
- dedent `
813
+ [
814
+ makeFailWorkflowExecution (
815
+ 'just because' ,
816
+ // The stack trace is weird here and might confuse users, it might be a JS limitation
817
+ // since the Error stack trace is generated in the constructor.
818
+ dedent `
791
819
ApplicationFailure: just because
792
820
at $CLASS.retryable (common/src/failure.ts)
793
821
at test/src/workflows/interrupt-signal.ts
794
- `
822
+ ` ,
823
+ 'Error' ,
824
+ false
825
+ ) ,
826
+ ] ,
827
+ [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
828
+ )
795
829
) ;
796
830
}
797
831
} ) ;
@@ -804,23 +838,23 @@ test('failSignalWorkflow', async (t) => {
804
838
}
805
839
{
806
840
const req = cleanWorkflowFailureStackTrace ( await activate ( t , await makeSignalWorkflow ( 'fail' , [ ] ) ) ) ;
807
- const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
808
841
compareCompletion (
809
842
t ,
810
843
req ,
811
844
makeSuccess (
812
- [ makeFailWorkflowExecution ( 'Signal failed' , 'Error' ) ] ,
813
- [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
814
- )
815
- ) ;
816
- compareStackTrace (
817
- t ,
818
- stackTrace ,
819
- dedent `
845
+ [
846
+ makeFailWorkflowExecution (
847
+ 'Signal failed' ,
848
+ dedent `
820
849
ApplicationFailure: Signal failed
821
850
at $CLASS.nonRetryable (common/src/failure.ts)
822
851
at test/src/workflows/fail-signal.ts
823
- `
852
+ ` ,
853
+ 'Error'
854
+ ) ,
855
+ ] ,
856
+ [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
857
+ )
824
858
) ;
825
859
}
826
860
} ) ;
@@ -844,22 +878,22 @@ test('asyncFailSignalWorkflow', async (t) => {
844
878
}
845
879
{
846
880
const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeFireTimer ( 2 ) ) ) ;
847
- const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
848
881
compareCompletion (
849
882
t ,
850
883
req ,
851
884
makeSuccess (
852
- [ makeFailWorkflowExecution ( 'Signal failed' , 'Error' ) ] ,
853
- [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
854
- )
855
- ) ;
856
- compareStackTrace (
857
- t ,
858
- stackTrace ,
859
- dedent `
885
+ [
886
+ makeFailWorkflowExecution (
887
+ 'Signal failed' ,
888
+ dedent `
860
889
ApplicationFailure: Signal failed
861
890
at $CLASS.nonRetryable (common/src/failure.ts)
862
- at test/src/workflows/async-fail-signal.ts`
891
+ at test/src/workflows/async-fail-signal.ts` ,
892
+ 'Error'
893
+ ) ,
894
+ ] ,
895
+ [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
896
+ )
863
897
) ;
864
898
}
865
899
} ) ;
@@ -1449,7 +1483,6 @@ test('nonCancellableInNonCancellable', async (t) => {
1449
1483
test ( 'cancellationErrorIsPropagated' , async ( t ) => {
1450
1484
const { workflowType, logs } = t . context ;
1451
1485
const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) , 2 ) ;
1452
- const stackTrace = removeWorkflowFailureStackTrace ( req , 2 ) ;
1453
1486
compareCompletion (
1454
1487
t ,
1455
1488
req ,
@@ -1460,25 +1493,21 @@ test('cancellationErrorIsPropagated', async (t) => {
1460
1493
failWorkflowExecution : {
1461
1494
failure : {
1462
1495
message : 'Cancellation scope cancelled' ,
1463
- canceledFailureInfo : { } ,
1464
- source : 'TypeScriptSDK' ,
1465
- } ,
1466
- } ,
1467
- } ,
1468
- ] )
1469
- ) ;
1470
- compareStackTrace (
1471
- t ,
1472
- stackTrace ,
1473
- dedent `
1496
+ stackTrace : dedent `
1474
1497
CancelledFailure: Cancellation scope cancelled
1475
1498
at CancellationScope.cancel (workflow/src/cancellation-scope.ts)
1476
1499
at test/src/workflows/cancellation-error-is-propagated.ts
1477
1500
at CancellationScope.runInContext (workflow/src/cancellation-scope.ts)
1478
1501
at CancellationScope.run (workflow/src/cancellation-scope.ts)
1479
1502
at $CLASS.cancellable (workflow/src/cancellation-scope.ts)
1480
1503
at cancellationErrorIsPropagated (test/src/workflows/cancellation-error-is-propagated.ts)
1481
- `
1504
+ ` ,
1505
+ canceledFailureInfo : { } ,
1506
+ source : 'TypeScriptSDK' ,
1507
+ } ,
1508
+ } ,
1509
+ } ,
1510
+ ] )
1482
1511
) ;
1483
1512
t . deepEqual ( logs , [ ] ) ;
1484
1513
} ) ;
@@ -1664,9 +1693,13 @@ test('resolve activity with failure - http', async (t) => {
1664
1693
} ,
1665
1694
} )
1666
1695
) ;
1667
- const stackTrace = removeWorkflowFailureStackTrace ( completion ) ;
1668
- compareCompletion ( t , completion , makeSuccess ( [ makeFailWorkflowExecution ( 'Connection timeout' , 'MockError' ) ] ) ) ;
1669
- compareStackTrace ( t , stackTrace , 'ApplicationFailure: Connection timeout' ) ;
1696
+ compareCompletion (
1697
+ t ,
1698
+ completion ,
1699
+ makeSuccess ( [
1700
+ makeFailWorkflowExecution ( 'Connection timeout' , 'ApplicationFailure: Connection timeout' , 'MockError' ) ,
1701
+ ] )
1702
+ ) ;
1670
1703
}
1671
1704
} ) ;
1672
1705
@@ -1877,16 +1910,19 @@ test('tryToContinueAfterCompletion', async (t) => {
1877
1910
const { workflowType } = t . context ;
1878
1911
{
1879
1912
const completion = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) ) ;
1880
- const stackTrace = removeWorkflowFailureStackTrace ( completion ) ;
1881
- compareCompletion ( t , completion , makeSuccess ( [ makeFailWorkflowExecution ( 'fail before continue' ) ] ) ) ;
1882
- compareStackTrace (
1913
+ compareCompletion (
1883
1914
t ,
1884
- stackTrace ,
1885
- dedent `
1915
+ completion ,
1916
+ makeSuccess ( [
1917
+ makeFailWorkflowExecution (
1918
+ 'fail before continue' ,
1919
+ dedent `
1886
1920
ApplicationFailure: fail before continue
1887
1921
at $CLASS.nonRetryable (common/src/failure.ts)
1888
1922
at tryToContinueAfterCompletion (test/src/workflows/try-to-continue-after-completion.ts)
1889
1923
`
1924
+ ) ,
1925
+ ] )
1890
1926
) ;
1891
1927
}
1892
1928
} ) ;
0 commit comments