< Summary

Information
Class: Elsa.Testing.Shared.Services.AsyncWorkflowRunner
Assembly: Elsa.Testing.Shared.Component
File(s): /home/runner/work/elsa-core/elsa-core/src/common/Elsa.Testing.Shared.Component/Services/AsyncWorkflowRunner.cs
Line coverage
100%
Covered lines: 42
Uncovered lines: 0
Coverable lines: 42
Total lines: 96
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
RunAndAwaitWorkflowCompletionAsync()100%11100%
RunWorkflowAsync()100%11100%
OnWorkflowStateCommitted(...)100%22100%
OnActivityExecutedLogUpdated(...)100%22100%
GetSignalName(...)100%11100%
Dispose()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/common/Elsa.Testing.Shared.Component/Services/AsyncWorkflowRunner.cs

#LineLine coverage
 1using System.Collections.Concurrent;
 2using Elsa.Common.Models;
 3using Elsa.Testing.Shared.Models;
 4using Elsa.Workflows;
 5using Elsa.Workflows.Models;
 6using Elsa.Workflows.Runtime;
 7using Elsa.Workflows.Runtime.Entities;
 8using Elsa.Workflows.Runtime.Messages;
 9
 10namespace Elsa.Testing.Shared.Services;
 11
 12/// <summary>
 13/// Provides functionality to execute workflows asynchronously and await their completion for testing purposes.
 14/// Tracks activity execution records and workflow completion signals.
 15/// </summary>
 16public class AsyncWorkflowRunner : IDisposable
 17{
 18    private readonly IWorkflowRuntime _workflowRuntime;
 19    private readonly IIdentityGenerator _identityGenerator;
 20    private readonly SignalManager _signalManager;
 21    private readonly WorkflowEvents _workflowEvents;
 2922    private readonly ConcurrentDictionary<string, ActivityExecutionRecord> _activityExecutionRecords = new();
 23
 24    /// <summary>
 25    /// Initializes a new instance of the <see cref="AsyncWorkflowRunner"/> class.
 26    /// </summary>
 2927    public AsyncWorkflowRunner(IWorkflowRuntime workflowRuntime, IIdentityGenerator identityGenerator, SignalManager sig
 28    {
 2929        _workflowRuntime = workflowRuntime;
 2930        _identityGenerator = identityGenerator;
 2931        _signalManager = signalManager;
 2932        _workflowEvents = workflowEvents;
 33
 2934        _workflowEvents.WorkflowStateCommitted += OnWorkflowStateCommitted;
 2935        _workflowEvents.ActivityExecutedLogUpdated += OnActivityExecutedLogUpdated;
 2936    }
 37
 38    /// <summary>
 39    /// Runs the specified workflow definition asynchronously and waits for its completion.
 40    /// Returns the workflow execution context and activity execution records.
 41    /// </summary>
 42    /// <param name="workflowDefinitionHandle">The handle of the workflow definition to execute.</param>
 43    /// <returns>A <see cref="TestWorkflowExecutionResult"/> containing the workflow execution context and activity exec
 44    public async Task<TestWorkflowExecutionResult> RunAndAwaitWorkflowCompletionAsync(WorkflowDefinitionHandle workflowD
 45    {
 2646        var workflowInstanceId = _identityGenerator.GenerateId();
 2647        var workflowClient = await _workflowRuntime.CreateClientAsync(workflowInstanceId);
 2648        await workflowClient.CreateInstanceAsync(new()
 2649        {
 2650            WorkflowDefinitionHandle = workflowDefinitionHandle
 2651        });
 2652        _activityExecutionRecords.Clear();
 2653        await workflowClient.RunInstanceAsync(RunWorkflowInstanceRequest.Empty);
 2654        var signalName = GetSignalName(workflowInstanceId);
 2655        var workflowExecutionContext = await _signalManager.WaitAsync<WorkflowExecutionContext>(signalName);
 2656        return new(workflowExecutionContext, _activityExecutionRecords.Values.ToList());
 2657    }
 58
 59    public async Task RunWorkflowAsync(string definitionId, string? correlationId = null)
 60    {
 261        var workflowClient = await _workflowRuntime.CreateClientAsync();
 262        await workflowClient.CreateInstanceAsync(new()
 263        {
 264            WorkflowDefinitionHandle = WorkflowDefinitionHandle.ByDefinitionId(definitionId, VersionOptions.Published),
 265            CorrelationId = correlationId
 266        });
 267        await workflowClient.RunInstanceAsync(RunWorkflowInstanceRequest.Empty);
 268    }
 69
 70    private void OnWorkflowStateCommitted(object? sender, WorkflowStateCommittedEventArgs e)
 71    {
 8272        if (e.WorkflowExecutionContext.Status != WorkflowStatus.Finished)
 3173            return;
 74
 5175        var signalName = GetSignalName(e.WorkflowExecutionContext.Id);
 5176        _signalManager.Trigger(signalName, e.WorkflowExecutionContext);
 5177    }
 78
 79    private void OnActivityExecutedLogUpdated(object? sender, ActivityExecutedLogUpdatedEventArgs e)
 80    {
 78281        foreach (var record in e.Records)
 30982            _activityExecutionRecords[record.Id] = record;
 8283    }
 84
 7785    private static string GetSignalName(string workflowInstanceId) => $"WorkflowInstanceCompleted-{workflowInstanceId}";
 86
 87    /// <summary>
 88    /// Unsubscribes from workflow events and releases resources.
 89    /// </summary>
 90    public void Dispose()
 91    {
 2992        _workflowEvents.WorkflowStateCommitted -= OnWorkflowStateCommitted;
 2993        _workflowEvents.ActivityExecutedLogUpdated -= OnActivityExecutedLogUpdated;
 2994        GC.SuppressFinalize(this);
 2995    }
 96}