< Summary

Information
Class: Elsa.Workflows.Activities.Switch
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Switch.cs
Line coverage
92%
Covered lines: 25
Uncovered lines: 2
Coverable lines: 27
Total lines: 158
Line coverage: 92.5%
Branch coverage
100%
Covered branches: 12
Total branches: 12
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%
get_Output()100%11100%
get_Cases()100%11100%
get_Mode()100%11100%
get_Default()100%11100%
ExecuteAsync()100%88100%
FindMatchingCasesAsync()100%44100%
OnChildActivityCompletedAsync()100%210%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Switch.cs

#LineLine coverage
 1using System.Runtime.CompilerServices;
 2using System.Text.Json.Serialization;
 3using Elsa.Expressions.Contracts;
 4using Elsa.Expressions.Models;
 5using Elsa.Workflows.Attributes;
 6using Elsa.Workflows.Models;
 7using Elsa.Workflows.UIHints;
 8using JetBrains.Annotations;
 9
 10namespace Elsa.Workflows.Activities;
 11
 12/// <summary>
 13/// The Switch activity is an approximation of the `switch` construct in C#.
 14/// When a case evaluates to true, the associated activity is then scheduled for execution.
 15/// </summary>
 16[Activity("Elsa", "Branching", "Evaluate a set of case conditions and schedule the activity for a matching case.")]
 17[PublicAPI]
 18public class Switch : Activity
 19{
 20    /// <inheritdoc />
 1521    public Switch([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
 22    {
 1523    }
 24
 25    /// <summary>
 26    /// The value to switch on, made available as output for capturing.
 27    /// </summary>
 1328    public Output<object>? Output { get; set; }
 29
 30    /// <summary>
 31    /// The cases to evaluate.
 32    /// </summary>
 33    [Input(
 34        Description = "The cases to evaluate.",
 35        UIHint = "switch-editor"
 36    )]
 7137    public ICollection<SwitchCase> Cases { get; set; } = new List<SwitchCase>();
 38
 39    /// <summary>
 40    /// The switch mode determines whether the first match should be scheduled, or all matches.
 41    /// </summary>
 42    [Input(
 43        Description = "The switch mode determines whether the first match should be scheduled, or all matches.",
 44        UIHint = InputUIHints.DropDown
 45    )]
 6746    public Input<SwitchMode> Mode { get; set; } = new(SwitchMode.MatchFirst);
 47
 48    /// <summary>
 49    /// The default activity to schedule when no case matches.
 50    /// </summary>
 3951    [Port] public IActivity? Default { get; set; }
 52
 53    /// <inheritdoc />
 54    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
 55    {
 1356        var matchingCases = (await FindMatchingCasesAsync(context.ExpressionExecutionContext)).ToList();
 1357        var hasAnyMatches = matchingCases.Any();
 1358        var mode = context.Get(Mode);
 1359        var results = mode == SwitchMode.MatchFirst ? hasAnyMatches ? new[] { matchingCases.First() } : Array.Empty<Swit
 60
 1361        if (hasAnyMatches)
 62        {
 1463            foreach (var result in results)
 64            {
 465                await context.ScheduleActivityAsync(result.Activity, OnChildActivityCompletedAsync);
 66            }
 67
 368            return;
 69        }
 70
 1071        await context.ScheduleActivityAsync(Default, OnChildActivityCompletedAsync);
 1372    }
 73
 74    private async Task<IEnumerable<SwitchCase>> FindMatchingCasesAsync(ExpressionExecutionContext context)
 75    {
 1376        var matchingCases = new List<SwitchCase>();
 1377        var expressionEvaluator = context.GetRequiredService<IExpressionEvaluator>();
 78
 5479        foreach (var switchCase in Cases)
 80        {
 1481            var result = await expressionEvaluator.EvaluateAsync<bool?>(switchCase.Condition, context);
 82
 1483            if (result == true)
 84            {
 685                matchingCases.Add(switchCase);
 86            }
 1487        }
 88
 1389        return matchingCases;
 1390    }
 91
 92    private async ValueTask OnChildActivityCompletedAsync(ActivityCompletedContext context)
 93    {
 094        await context.TargetContext.CompleteActivityAsync();
 095    }
 96}
 97
 98/// <summary>
 99/// Represents an individual case of the <see cref="Switch"/> activity.
 100/// </summary>
 101public class SwitchCase
 102{
 103    /// <summary>
 104    /// Initializes a new instance of the <see cref="SwitchCase"/> class.
 105    /// </summary>
 106    [JsonConstructor]
 107    public SwitchCase()
 108    {
 109    }
 110
 111    /// <summary>
 112    /// Initializes a new instance of the <see cref="SwitchCase"/> class.
 113    /// </summary>
 114    /// <param name="label">The label of the case.</param>
 115    /// <param name="condition">The condition to evaluate.</param>
 116    /// <param name="activity">The activity to schedule when the condition evaluates to true.</param>
 117    public SwitchCase(string label, Expression condition, IActivity activity)
 118    {
 119        Label = label;
 120        Condition = condition;
 121        Activity = activity;
 122    }
 123
 124    /// <inheritdoc />
 125    public SwitchCase(string label, Func<ExpressionExecutionContext, ValueTask<bool>> condition, IActivity activity) : t
 126    {
 127    }
 128
 129    /// <inheritdoc />
 130    public SwitchCase(string label, Func<ValueTask<bool>> condition, IActivity activity) : this(label, Expression.Delega
 131    {
 132    }
 133
 134    /// <inheritdoc />
 135    public SwitchCase(string label, Func<ExpressionExecutionContext, bool> condition, IActivity activity) : this(label, 
 136    {
 137    }
 138
 139    /// <inheritdoc />
 140    public SwitchCase(string label, Func<bool> condition, IActivity activity) : this(label, Expression.DelegateExpressio
 141    {
 142    }
 143
 144    /// <summary>
 145    /// The label of the case.
 146    /// </summary>
 147    public string Label { get; set; } = null!;
 148
 149    /// <summary>
 150    /// The condition to evaluate.
 151    /// </summary>
 152    public Expression Condition { get; set; } = Expression.LiteralExpression(false);
 153
 154    /// <summary>
 155    /// The activity to schedule when the condition evaluates to true.
 156    /// </summary>
 157    public IActivity? Activity { get; set; }
 158}