@@ -2,11 +2,14 @@ namespace Temporalio.Tests.Testing;
22
33using System . Diagnostics ;
44using System . Runtime . InteropServices ;
5+ using NexusRpc ;
6+ using NexusRpc . Handlers ;
57using Temporalio . Activities ;
68using Temporalio . Api . Enums . V1 ;
79using Temporalio . Client ;
810using Temporalio . Common ;
911using Temporalio . Exceptions ;
12+ using Temporalio . Nexus ;
1013using Temporalio . Testing ;
1114using Temporalio . Worker ;
1215using Temporalio . Workflows ;
@@ -241,6 +244,73 @@ await env.WithAutoTimeSkippingDisabledAsync(async () =>
241244 } ) ;
242245 }
243246
247+ [ NexusService ]
248+ public interface INexusWorkflowRunService
249+ {
250+ [ NexusOperation ]
251+ string RunOperation ( string input ) ;
252+ }
253+
254+ [ Workflow ]
255+ public class NexusBackingWorkflow
256+ {
257+ [ WorkflowRun ]
258+ public Task < string > RunAsync ( string input ) => Task . FromResult ( $ "done: { input } ") ;
259+ }
260+
261+ [ NexusServiceHandler ( typeof ( INexusWorkflowRunService ) ) ]
262+ public class NexusWorkflowRunServiceHandler
263+ {
264+ [ NexusOperationHandler ]
265+ public IOperationHandler < string , string > RunOperation ( ) =>
266+ WorkflowRunOperationHandler . FromHandleFactory (
267+ ( WorkflowRunOperationContext context , string input ) =>
268+ context . StartWorkflowAsync (
269+ ( NexusBackingWorkflow wf ) => wf . RunAsync ( input ) ,
270+ new ( ) { Id = $ "nexus-wf-{ Guid . NewGuid ( ) } " } ) ) ;
271+ }
272+
273+ [ Workflow ]
274+ public class NexusCallerWorkflow
275+ {
276+ private readonly string endpoint ;
277+
278+ public NexusCallerWorkflow ( string endpoint ) => this . endpoint = endpoint ;
279+
280+ [ WorkflowRun ]
281+ public async Task < string > RunAsync ( string input )
282+ {
283+ return await Workflow . CreateNexusWorkflowClient < INexusWorkflowRunService > ( endpoint ) .
284+ ExecuteNexusOperationAsync ( svc => svc . RunOperation ( input ) ) ;
285+ }
286+ }
287+
288+ [ OnlyIntelFact ]
289+ public async Task StartTimeSkippingAsync_NexusWorkflowRunOperation_Completes ( )
290+ {
291+ await using var env = await WorkflowEnvironment . StartTimeSkippingAsync ( ) ;
292+ var taskQueue = $ "tq-{ Guid . NewGuid ( ) } ";
293+ var endpointName = $ "nexus-endpoint-{ taskQueue } ";
294+ await env . CreateNexusEndpointAsync ( endpointName , taskQueue ) ;
295+ using var worker = new TemporalWorker (
296+ env . Client ,
297+ new TemporalWorkerOptions ( taskQueue ) .
298+ AddNexusService ( new NexusWorkflowRunServiceHandler ( ) ) .
299+ AddWorkflow < NexusBackingWorkflow > ( ) .
300+ AddWorkflow ( WorkflowDefinition . Create (
301+ typeof ( NexusCallerWorkflow ) ,
302+ null ,
303+ _args => new NexusCallerWorkflow ( endpointName ) ) ) ) ;
304+ await worker . ExecuteAsync ( async ( ) =>
305+ {
306+ // Run the caller workflow which invokes a Nexus workflow-run operation
307+ var result = await env . Client . ExecuteWorkflowAsync (
308+ ( NexusCallerWorkflow wf ) => wf . RunAsync ( "test-input" ) ,
309+ new ( id : $ "workflow-{ Guid . NewGuid ( ) } ", taskQueue : taskQueue ) ) ;
310+ Assert . Equal ( "done: test-input" , result ) ;
311+ } ) ;
312+ }
313+
244314 [ Fact ]
245315 public async Task StartLocal_SearchAttributes_ProperlyRegistered ( )
246316 {
0 commit comments