@@ -55,10 +55,10 @@ import type { RouteFunction, WaitStepResponse, WorkflowServeOptions } from "./ty
55
55
import type { NextRequest } from "next/server" ;
56
56
import { Client } from "./client" ;
57
57
import { nanoid } from "./utils" ;
58
+ import { makeGetWaitersRequest } from "./client/utils" ;
58
59
59
60
const WORKFLOW_PORT = "3000" ;
60
61
const THIRD_PARTY_PORT = "3001" ;
61
- const LOCAL_WORKFLOW_URL = `http://localhost:${ WORKFLOW_PORT } ` ;
62
62
const LOCAL_THIRD_PARTY_URL = `http://localhost:${ THIRD_PARTY_PORT } ` ;
63
63
64
64
const someWork = ( input : string ) => {
@@ -109,21 +109,23 @@ const testEndpoint = async <TInitialPayload = unknown>({
109
109
finishState,
110
110
failureFunction,
111
111
retries,
112
+ port = WORKFLOW_PORT ,
112
113
} : {
113
- finalCount : number ;
114
+ finalCount ? : number ;
114
115
waitFor : number ;
115
116
initialPayload : TInitialPayload ;
116
117
routeFunction : RouteFunction < TInitialPayload > ;
117
118
finishState : FinishState ;
118
119
failureFunction ?: WorkflowServeOptions [ "failureFunction" ] ;
119
120
retries ?: number ;
121
+ port ?: string ;
120
122
} ) => {
121
123
let counter = 0 ;
122
124
123
125
const endpoint = workflowServe < TInitialPayload > ( routeFunction , {
124
126
qstashClient,
125
- url : LOCAL_WORKFLOW_URL ,
126
- verbose : true ,
127
+ url : `http://localhost: ${ port } ` ,
128
+ // verbose: true,
127
129
failureFunction,
128
130
retries,
129
131
} ) ;
@@ -133,7 +135,7 @@ const testEndpoint = async <TInitialPayload = unknown>({
133
135
counter += 1 ;
134
136
return await endpoint ( request as NextRequest ) ;
135
137
} ,
136
- port : WORKFLOW_PORT ,
138
+ port : port ,
137
139
} ) ;
138
140
139
141
await qstashClient . publishJSON ( {
@@ -142,15 +144,17 @@ const testEndpoint = async <TInitialPayload = unknown>({
142
144
headers : {
143
145
Authentication : "Bearer secretPassword" ,
144
146
} ,
145
- url : `http://localhost:${ WORKFLOW_PORT } ` ,
147
+ url : `http://localhost:${ port } ` ,
146
148
} ) ;
147
149
148
150
await new Promise ( ( resolve ) => setTimeout ( resolve , waitFor ) ) ;
149
151
150
152
server . stop ( ) ;
151
153
152
154
finishState . check ( ) ;
153
- expect ( counter ) . toBe ( finalCount ) ;
155
+ if ( finalCount ) {
156
+ expect ( counter ) . toBe ( finalCount ) ;
157
+ }
154
158
} ;
155
159
156
160
describe . skip ( "live serve tests" , ( ) => {
@@ -590,8 +594,9 @@ describe.skip("live serve tests", () => {
590
594
context . waitForEvent ( "wait-event-step" , eventId , 3 ) ,
591
595
] ) ;
592
596
expect ( runResponse ) . toBe ( runResult ) ;
593
- expect ( waitResponse . eventData ) . toBe ( expectedWaitResponse . eventData ) ;
594
597
expect ( waitResponse . timeout ) . toBe ( expectedWaitResponse . timeout ) ;
598
+ expect ( waitResponse . eventData ) . toEqual ( expectedWaitResponse . eventData ) ;
599
+ expect ( typeof waitResponse . eventData ) . toBe ( typeof expectedWaitResponse . eventData ) ;
595
600
finishState . finish ( ) ;
596
601
} ,
597
602
} ) ;
@@ -651,5 +656,64 @@ describe.skip("live serve tests", () => {
651
656
} ,
652
657
{ timeout : 17_000 }
653
658
) ;
659
+
660
+ describe ( "should notify from inside a function" , ( ) => {
661
+ const testNotifyWithContext = async ( payload : unknown ) => {
662
+ const eventId = `my-event-id-${ nanoid ( ) } ` ;
663
+
664
+ const waitingEndpoint = testWaitEndpoint (
665
+ {
666
+ eventData : payload ,
667
+ timeout : false ,
668
+ } ,
669
+ eventId
670
+ ) ;
671
+
672
+ const finishState = new FinishState ( ) ;
673
+ const notifyingEndpoint = testEndpoint ( {
674
+ finishState,
675
+ initialPayload : undefined ,
676
+ waitFor : 15000 ,
677
+ port : "3002" ,
678
+ routeFunction : async ( context ) => {
679
+ // wait to avoid notifying the first waitForEvent
680
+ await context . sleep ( "sleep for first timeout" , 3 ) ;
681
+
682
+ while ( true ) {
683
+ const waiterExists = await context . run ( "check waiters" , async ( ) => {
684
+ const waiters = await makeGetWaitersRequest ( context . qstashClient . http , eventId ) ;
685
+
686
+ return Boolean ( waiters ) ;
687
+ } ) ;
688
+
689
+ if ( waiterExists ) {
690
+ break ;
691
+ }
692
+ }
693
+ const { notifyResponse } = await context . notify ( "notify-step" , eventId , payload ) ;
694
+ expect ( notifyResponse . length ) . toBeTruthy ( ) ;
695
+ finishState . finish ( ) ;
696
+ } ,
697
+ } ) ;
698
+
699
+ await Promise . all ( [ waitingEndpoint , notifyingEndpoint ] ) ;
700
+ } ;
701
+
702
+ test (
703
+ "should handle string event data" ,
704
+ async ( ) => {
705
+ await testNotifyWithContext ( "event-data" ) ;
706
+ } ,
707
+ { timeout : 170000 }
708
+ ) ;
709
+
710
+ test (
711
+ "should handle object event data" ,
712
+ async ( ) => {
713
+ await testNotifyWithContext ( { event : "data" } ) ;
714
+ } ,
715
+ { timeout : 170000 }
716
+ ) ;
717
+ } ) ;
654
718
} ) ;
655
719
} ) ;
0 commit comments