@@ -4,6 +4,7 @@ import vm from 'node:vm';
44import anyTest , { ExecutionContext , TestFn } from 'ava' ;
55import dedent from 'dedent' ;
66import Long from 'long' ; // eslint-disable-line import/no-named-as-default
7+ import escapeStringRexep from 'escape-string-regexp' ;
78import {
89 ApplicationFailure ,
910 defaultFailureConverter ,
@@ -172,6 +173,14 @@ function compareCompletion(
172173 ) ;
173174}
174175
176+ // Compare stack traces while handling $CLASS keyword to match any identifier that isn't consistent across Node versions.
177+ // As of Node 24.6.0 type names are now present on source mapped stack traces
178+ // See [f33e0fcc83954f728fcfd2ef6ae59435bc4af059](https://github.com/nodejs/node/commit/f33e0fcc83954f728fcfd2ef6ae59435bc4af059)
179+ function compareFailureStackTrace ( t : ExecutionContext < Context > , actual : string , expected : string ) {
180+ const escapedTrace = escapeStringRexep ( expected ) . replaceAll ( '\\$CLASS' , '(?:[A-Za-z]+)' ) ;
181+ t . regex ( actual , RegExp ( `^${ escapedTrace } $` ) ) ;
182+ }
183+
175184function makeSuccess (
176185 commands : coresdk . workflow_commands . IWorkflowCommand [ ] = [ makeCompleteWorkflowExecution ( ) ] ,
177186 usedInternalFlags : SdkFlag [ ] = [ ]
@@ -307,13 +316,12 @@ function makeCompleteWorkflowExecution(result?: Payload): coresdk.workflow_comma
307316
308317function makeFailWorkflowExecution (
309318 message : string ,
310- stackTrace : string ,
311319 type = 'Error' ,
312320 nonRetryable = true
313321) : coresdk . workflow_commands . IWorkflowCommand {
314322 return {
315323 failWorkflowExecution : {
316- failure : { message, stackTrace , applicationFailureInfo : { type, nonRetryable } , source : 'TypeScriptSDK' } ,
324+ failure : { message, applicationFailureInfo : { type, nonRetryable } , source : 'TypeScriptSDK' } ,
317325 } ,
318326 } ;
319327}
@@ -453,22 +461,28 @@ function cleanWorkflowQueryFailureStackTrace(
453461 return req ;
454462}
455463
464+ function removeWorkflowFailureStackTrace (
465+ req : coresdk . workflow_completion . IWorkflowActivationCompletion ,
466+ commandIndex = 0
467+ ) {
468+ const stackTrace = req . successful ! . commands ! [ commandIndex ] . failWorkflowExecution ! . failure ! . stackTrace ! ;
469+ delete req . successful ! . commands ! [ commandIndex ] . failWorkflowExecution ! . failure ! . stackTrace ;
470+ return stackTrace ;
471+ }
472+
456473test ( 'throwAsync' , async ( t ) => {
457474 const { workflowType } = t . context ;
458475 const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) ) ;
459- compareCompletion (
476+ const actualStackTrace = removeWorkflowFailureStackTrace ( req ) ;
477+ compareCompletion ( t , req , makeSuccess ( [ makeFailWorkflowExecution ( 'failure' ) ] ) ) ;
478+ compareFailureStackTrace (
460479 t ,
461- req ,
462- makeSuccess ( [
463- makeFailWorkflowExecution (
464- 'failure' ,
465- dedent `
480+ actualStackTrace ,
481+ dedent `
466482 ApplicationFailure: failure
467- at Function .nonRetryable (common/src/failure.ts)
483+ at $CLASS .nonRetryable (common/src/failure.ts)
468484 at throwAsync (test/src/workflows/throw-async.ts)
469485 `
470- ) ,
471- ] )
472486 ) ;
473487} ) ;
474488
@@ -768,27 +782,26 @@ test('interruptableWorkflow', async (t) => {
768782 const req = cleanWorkflowFailureStackTrace (
769783 await activate ( t , await makeSignalWorkflow ( 'interrupt' , [ 'just because' ] ) )
770784 ) ;
785+ const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
771786 compareCompletion (
772787 t ,
773788 req ,
774789 makeSuccess (
775- [
776- makeFailWorkflowExecution (
777- 'just because' ,
778- // The stack trace is weird here and might confuse users, it might be a JS limitation
779- // since the Error stack trace is generated in the constructor.
780- dedent `
781- ApplicationFailure: just because
782- at Function.retryable (common/src/failure.ts)
783- at test/src/workflows/interrupt-signal.ts
784- ` ,
785- 'Error' ,
786- false
787- ) ,
788- ] ,
790+ [ makeFailWorkflowExecution ( 'just because' , 'Error' , false ) ] ,
789791 [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
790792 )
791793 ) ;
794+ compareFailureStackTrace (
795+ t ,
796+ stackTrace ,
797+ // The stack trace is weird here and might confuse users, it might be a JS limitation
798+ // since the Error stack trace is generated in the constructor.
799+ dedent `
800+ ApplicationFailure: just because
801+ at $CLASS.retryable (common/src/failure.ts)
802+ at test/src/workflows/interrupt-signal.ts
803+ `
804+ ) ;
792805 }
793806} ) ;
794807
@@ -800,24 +813,24 @@ test('failSignalWorkflow', async (t) => {
800813 }
801814 {
802815 const req = cleanWorkflowFailureStackTrace ( await activate ( t , await makeSignalWorkflow ( 'fail' , [ ] ) ) ) ;
816+ const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
803817 compareCompletion (
804818 t ,
805819 req ,
806820 makeSuccess (
807- [
808- makeFailWorkflowExecution (
809- 'Signal failed' ,
810- dedent `
811- ApplicationFailure: Signal failed
812- at Function.nonRetryable (common/src/failure.ts)
813- at test/src/workflows/fail-signal.ts
814- ` ,
815- 'Error'
816- ) ,
817- ] ,
821+ [ makeFailWorkflowExecution ( 'Signal failed' , 'Error' ) ] ,
818822 [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
819823 )
820824 ) ;
825+ compareFailureStackTrace (
826+ t ,
827+ stackTrace ,
828+ dedent `
829+ ApplicationFailure: Signal failed
830+ at $CLASS.nonRetryable (common/src/failure.ts)
831+ at test/src/workflows/fail-signal.ts
832+ `
833+ ) ;
821834 }
822835} ) ;
823836
@@ -840,23 +853,23 @@ test('asyncFailSignalWorkflow', async (t) => {
840853 }
841854 {
842855 const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeFireTimer ( 2 ) ) ) ;
856+ const stackTrace = removeWorkflowFailureStackTrace ( req ) ;
843857 compareCompletion (
844858 t ,
845859 req ,
846860 makeSuccess (
847- [
848- makeFailWorkflowExecution (
849- 'Signal failed' ,
850- dedent `
851- ApplicationFailure: Signal failed
852- at Function.nonRetryable (common/src/failure.ts)
853- at test/src/workflows/async-fail-signal.ts` ,
854- 'Error'
855- ) ,
856- ] ,
861+ [ makeFailWorkflowExecution ( 'Signal failed' , 'Error' ) ] ,
857862 [ SdkFlags . ProcessWorkflowActivationJobsAsSingleBatch ]
858863 )
859864 ) ;
865+ compareFailureStackTrace (
866+ t ,
867+ stackTrace ,
868+ dedent `
869+ ApplicationFailure: Signal failed
870+ at $CLASS.nonRetryable (common/src/failure.ts)
871+ at test/src/workflows/async-fail-signal.ts`
872+ ) ;
860873 }
861874} ) ;
862875
@@ -1445,6 +1458,7 @@ test('nonCancellableInNonCancellable', async (t) => {
14451458test ( 'cancellationErrorIsPropagated' , async ( t ) => {
14461459 const { workflowType, logs } = t . context ;
14471460 const req = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) , 2 ) ;
1461+ const stackTrace = removeWorkflowFailureStackTrace ( req , 2 ) ;
14481462 compareCompletion (
14491463 t ,
14501464 req ,
@@ -1455,22 +1469,26 @@ test('cancellationErrorIsPropagated', async (t) => {
14551469 failWorkflowExecution : {
14561470 failure : {
14571471 message : 'Cancellation scope cancelled' ,
1458- stackTrace : dedent `
1459- CancelledFailure: Cancellation scope cancelled
1460- at CancellationScope.cancel (workflow/src/cancellation-scope.ts)
1461- at test/src/workflows/cancellation-error-is-propagated.ts
1462- at CancellationScope.runInContext (workflow/src/cancellation-scope.ts)
1463- at CancellationScope.run (workflow/src/cancellation-scope.ts)
1464- at Function.cancellable (workflow/src/cancellation-scope.ts)
1465- at cancellationErrorIsPropagated (test/src/workflows/cancellation-error-is-propagated.ts)
1466- ` ,
14671472 canceledFailureInfo : { } ,
14681473 source : 'TypeScriptSDK' ,
14691474 } ,
14701475 } ,
14711476 } ,
14721477 ] )
14731478 ) ;
1479+ compareFailureStackTrace (
1480+ t ,
1481+ stackTrace ,
1482+ dedent `
1483+ CancelledFailure: Cancellation scope cancelled
1484+ at CancellationScope.cancel (workflow/src/cancellation-scope.ts)
1485+ at test/src/workflows/cancellation-error-is-propagated.ts
1486+ at CancellationScope.runInContext (workflow/src/cancellation-scope.ts)
1487+ at CancellationScope.run (workflow/src/cancellation-scope.ts)
1488+ at $CLASS.cancellable (workflow/src/cancellation-scope.ts)
1489+ at cancellationErrorIsPropagated (test/src/workflows/cancellation-error-is-propagated.ts)
1490+ `
1491+ ) ;
14741492 t . deepEqual ( logs , [ ] ) ;
14751493} ) ;
14761494
@@ -1655,13 +1673,9 @@ test('resolve activity with failure - http', async (t) => {
16551673 } ,
16561674 } )
16571675 ) ;
1658- compareCompletion (
1659- t ,
1660- completion ,
1661- makeSuccess ( [
1662- makeFailWorkflowExecution ( 'Connection timeout' , 'ApplicationFailure: Connection timeout' , 'MockError' ) ,
1663- ] )
1664- ) ;
1676+ const stackTrace = removeWorkflowFailureStackTrace ( completion ) ;
1677+ compareCompletion ( t , completion , makeSuccess ( [ makeFailWorkflowExecution ( 'Connection timeout' , 'MockError' ) ] ) ) ;
1678+ compareFailureStackTrace ( t , stackTrace , 'ApplicationFailure: Connection timeout' ) ;
16651679 }
16661680} ) ;
16671681
@@ -1872,19 +1886,16 @@ test('tryToContinueAfterCompletion', async (t) => {
18721886 const { workflowType } = t . context ;
18731887 {
18741888 const completion = cleanWorkflowFailureStackTrace ( await activate ( t , makeStartWorkflow ( workflowType ) ) ) ;
1875- compareCompletion (
1889+ const stackTrace = removeWorkflowFailureStackTrace ( completion ) ;
1890+ compareCompletion ( t , completion , makeSuccess ( [ makeFailWorkflowExecution ( 'fail before continue' ) ] ) ) ;
1891+ compareFailureStackTrace (
18761892 t ,
1877- completion ,
1878- makeSuccess ( [
1879- makeFailWorkflowExecution (
1880- 'fail before continue' ,
1881- dedent `
1893+ stackTrace ,
1894+ dedent `
18821895 ApplicationFailure: fail before continue
1883- at Function .nonRetryable (common/src/failure.ts)
1896+ at $CLASS .nonRetryable (common/src/failure.ts)
18841897 at tryToContinueAfterCompletion (test/src/workflows/try-to-continue-after-completion.ts)
18851898 `
1886- ) ,
1887- ] )
18881899 ) ;
18891900 }
18901901} ) ;
0 commit comments