< Summary

Information
Class: Elsa.Workflows.Activities.For
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/For.cs
Line coverage
97%
Covered lines: 44
Uncovered lines: 1
Coverable lines: 45
Total lines: 127
Line coverage: 97.7%
Branch coverage
75%
Covered branches: 18
Total branches: 24
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%
get_Start()100%11100%
get_End()100%11100%
get_Step()100%11100%
get_OuterBoundInclusive()100%11100%
get_Body()100%11100%
get_CurrentValue()100%11100%
ExecuteAsync()100%22100%
HandleIteration()72.72%2222100%
OnChildComplete()100%210%

File(s)

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

#LineLine coverage
 1using System.Runtime.CompilerServices;
 2using Elsa.Extensions;
 3using Elsa.Workflows.Attributes;
 4using Elsa.Workflows.Behaviors;
 5using Elsa.Workflows.Memory;
 6using Elsa.Workflows.Models;
 7using JetBrains.Annotations;
 8
 9namespace Elsa.Workflows.Activities;
 10
 11/// <summary>
 12/// Iterate over a sequence of steps between a start and an end number.
 13/// </summary>
 14[Activity("Elsa", "Looping", "Iterate over a sequence of steps between a start and an end number.")]
 15[PublicAPI]
 16public class For : Activity
 17{
 18    private const string CurrentStepProperty = "CurrentStep";
 19
 20    /// <inheritdoc />
 5021    public For([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
 22    {
 5023        Behaviors.Add<BreakBehavior>(this);
 5024    }
 25
 26    /// <inheritdoc />
 1727    public For(int start, int end, int step, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null
 28    {
 1729        Start = new(start);
 1730        End = new(end);
 1731        Step = new(step);
 1732    }
 33
 34    /// <summary>
 35    /// The start step.
 36    /// </summary>
 37    [Input(Description = "The start step.")]
 23538    public Input<int> Start { get; set; } = new(0);
 39
 40    /// <summary>
 41    /// The end step.
 42    /// </summary>
 43    [Input(Description = "The end step.")]
 23444    public Input<int> End { get; set; } = new(0);
 45
 46    /// <summary>
 47    /// The step size. To count down, enter a negative number.
 48    /// </summary>
 49    [Input(Description = "The step size. To count down, enter a negative number.")]
 23350    public Input<int> Step { get; set; } = new(1);
 51
 52    /// <summary>
 53    /// Controls whether the end step is upper/lowerbound inclusive or exclusive. True (inclusive) by default.
 54    /// </summary>
 55    [Input(Description = "Controls whether the end step is upper/lowerbound inclusive or exclusive. True (inclusive) by 
 20856    public Input<bool> OuterBoundInclusive { get; set; } = new(true);
 57
 58    /// <summary>
 59    /// The activity to execute for each iteration.
 60    /// </summary>
 61    [Port]
 18162    public IActivity? Body { get; set; }
 63
 64    /// <summary>
 65    /// Stores the current value for each iteration.
 66    /// </summary>
 67    [Output]
 12068    public Output<object?> CurrentValue { get; set; } = new();
 69
 70    /// <inheritdoc />
 71    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
 72    {
 4473        var iterateNode = Body;
 74
 4475        if (iterateNode == null)
 176            return;
 77
 4378        await HandleIteration(context);
 4479    }
 80
 81    private async ValueTask HandleIteration(ActivityExecutionContext context)
 82    {
 4383        var iterateNode = Body;
 4384        var end = context.Get(End);
 4385        var currentValue = context.GetProperty<int?>(CurrentStepProperty);
 4386        var start = context.Get(Start);
 4387        var step = context.Get(Step);
 4388        var inclusive = context.Get(OuterBoundInclusive);
 4389        var increment = step >= 0;
 90
 4391        currentValue = currentValue == null ? start : currentValue + step;
 92
 4393        var isBreaking = context.GetIsBreaking();
 94
 4395        var loop =
 4396            !isBreaking && (increment && inclusive ? currentValue <= end
 4397                : increment && !inclusive ? currentValue < end
 4398                : !increment && inclusive ? currentValue >= end
 4399                : !increment && !inclusive && currentValue > end);
 100
 43101        if (loop)
 102        {
 23103            if (iterateNode != null)
 104            {
 23105                var variables = new[]
 23106                {
 23107                    new Variable("CurrentValue", currentValue)
 23108                };
 23109                await context.ScheduleActivityAsync(iterateNode, OnChildComplete, variables: variables);
 110            }
 111
 112
 113            // Update internal step.
 23114            context.SetProperty(CurrentStepProperty, currentValue);
 115
 116            // Update loop variable.
 23117            context.Set(CurrentValue, currentValue);
 118        }
 119        else
 120        {
 121            // Report activity completion.
 20122            await context.CompleteActivityAsync();
 123        }
 43124    }
 125
 0126    private async ValueTask OnChildComplete(ActivityCompletedContext context) => await HandleIteration(context.TargetCon
 127}