Skip to content

Commit e96a57c

Browse files
committed
Add component tests for various activity workflows
- Introduce comprehensive tests for Complete, Correlate, For, Fork, If, Parallel, SetName, Switch, and While activities. - Ensure each test validates correct workflow execution and conditions.
1 parent ed0af3c commit e96a57c

19 files changed

Lines changed: 967 additions & 0 deletions

File tree

test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
using Elsa.Common.Models;
2+
using Elsa.Testing.Shared.Models;
3+
using Elsa.Testing.Shared.Services;
14
using Elsa.Workflows.ComponentTests.Fixtures;
5+
using Elsa.Workflows.Models;
6+
using Elsa.Workflows.Runtime.Entities;
27
using Microsoft.Extensions.DependencyInjection;
38

49
namespace Elsa.Workflows.ComponentTests.Abstractions;
@@ -20,4 +25,37 @@ void IDisposable.Dispose()
2025
protected virtual void OnDispose()
2126
{
2227
}
28+
29+
/// <summary>
30+
/// Runs a workflow by definition ID and waits for completion.
31+
/// </summary>
32+
protected async Task<TestWorkflowExecutionResult> RunWorkflowAsync(string definitionId)
33+
{
34+
var runner = Scope.ServiceProvider.GetRequiredService<AsyncWorkflowRunner>();
35+
return await runner.RunAndAwaitWorkflowCompletionAsync(
36+
WorkflowDefinitionHandle.ByDefinitionId(definitionId, VersionOptions.Published));
37+
}
38+
39+
/// <summary>
40+
/// Asserts that the workflow finished successfully.
41+
/// </summary>
42+
protected static void AssertWorkflowFinished(TestWorkflowExecutionResult result)
43+
{
44+
if (result.WorkflowExecutionContext.SubStatus != WorkflowSubStatus.Finished)
45+
throw new Xunit.Sdk.XunitException($"Expected workflow to be Finished but was {result.WorkflowExecutionContext.SubStatus}");
46+
}
47+
48+
/// <summary>
49+
/// Gets all WriteLine activity execution records from the result.
50+
/// </summary>
51+
protected static List<ActivityExecutionRecord> GetWriteLineRecords(TestWorkflowExecutionResult result) =>
52+
result.ActivityExecutionRecords.Where(x => x.ActivityType == "Elsa.WriteLine").ToList();
53+
54+
/// <summary>
55+
/// Gets the text output from WriteLine activity execution records.
56+
/// </summary>
57+
protected static List<string?> GetWriteLineMessages(TestWorkflowExecutionResult result) =>
58+
GetWriteLineRecords(result)
59+
.Select(x => x.ActivityState?[nameof(Elsa.Workflows.Activities.WriteLine.Text)]?.ToString())
60+
.ToList();
2361
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Elsa.Workflows.ComponentTests.Abstractions;
2+
using Elsa.Workflows.ComponentTests.Fixtures;
3+
4+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.Fork;
5+
6+
public class ForkActivityTests(App app) : AppComponentTest(app)
7+
{
8+
[Theory(DisplayName = "Fork activity should execute all branches")]
9+
[InlineData(nameof(ForkBasicWorkflow), new[] { "Branch A", "Branch B", "Branch C" })]
10+
[InlineData(nameof(ForkWaitAllWorkflow), new[] { "Branch A - Step 1", "Branch B - Step 1" })]
11+
public async Task Fork_ShouldExecuteAllBranches(string workflowName, string[] expectedMessageFragments)
12+
{
13+
// Arrange
14+
var definitionId = GetDefinitionId(workflowName);
15+
16+
// Act
17+
var result = await RunWorkflowAsync(definitionId);
18+
19+
// Assert
20+
AssertWorkflowFinished(result);
21+
var messages = GetWriteLineMessages(result);
22+
23+
foreach (var expected in expectedMessageFragments)
24+
{
25+
Assert.Contains(expected, messages);
26+
}
27+
}
28+
29+
private static string GetDefinitionId(string workflowName) => workflowName switch
30+
{
31+
nameof(ForkBasicWorkflow) => ForkBasicWorkflow.DefinitionId,
32+
nameof(ForkWaitAllWorkflow) => ForkWaitAllWorkflow.DefinitionId,
33+
_ => throw new ArgumentException($"Unknown workflow: {workflowName}")
34+
};
35+
}
36+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using Elsa.Workflows.Activities;
2+
3+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.Fork;
4+
5+
public class ForkBasicWorkflow : WorkflowBase
6+
{
7+
public static readonly string DefinitionId = nameof(ForkBasicWorkflow);
8+
9+
protected override void Build(IWorkflowBuilder builder)
10+
{
11+
builder.WithDefinitionId(DefinitionId);
12+
13+
builder.Root = new Elsa.Workflows.Activities.Fork
14+
{
15+
Branches =
16+
{
17+
new WriteLine("Branch A"),
18+
new WriteLine("Branch B"),
19+
new WriteLine("Branch C")
20+
}
21+
};
22+
}
23+
}
24+
25+
public class ForkWaitAllWorkflow : WorkflowBase
26+
{
27+
public static readonly string DefinitionId = nameof(ForkWaitAllWorkflow);
28+
29+
protected override void Build(IWorkflowBuilder builder)
30+
{
31+
builder.WithDefinitionId(DefinitionId);
32+
33+
builder.Root = new Sequence
34+
{
35+
Activities =
36+
{
37+
new Elsa.Workflows.Activities.Fork
38+
{
39+
JoinMode = ForkJoinMode.WaitAll,
40+
Branches =
41+
{
42+
new Sequence
43+
{
44+
Activities =
45+
{
46+
new WriteLine("Branch A - Step 1"),
47+
new WriteLine("Branch A - Step 2")
48+
}
49+
},
50+
new Sequence
51+
{
52+
Activities =
53+
{
54+
new WriteLine("Branch B - Step 1"),
55+
new WriteLine("Branch B - Step 2")
56+
}
57+
}
58+
}
59+
},
60+
new WriteLine("All branches completed")
61+
}
62+
};
63+
}
64+
}
65+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Elsa.Workflows.Activities;
2+
using Elsa.Workflows.ComponentTests.Abstractions;
3+
using Elsa.Workflows.ComponentTests.Fixtures;
4+
5+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.If;
6+
7+
public class IfActivityTests(App app) : AppComponentTest(app)
8+
{
9+
[Theory(DisplayName = "If activity should execute correct branch based on condition")]
10+
[InlineData(nameof(IfTrueWorkflow), "Condition is true", 1)]
11+
[InlineData(nameof(IfFalseWorkflow), "Condition is false", 1)]
12+
[InlineData(nameof(IfNoElseWorkflow), null, 0)]
13+
public async Task If_ShouldExecuteCorrectBranch(string workflowName, string? expectedMessage, int expectedWriteLineCount)
14+
{
15+
// Arrange
16+
var definitionId = GetDefinitionId(workflowName);
17+
18+
// Act
19+
var result = await RunWorkflowAsync(definitionId);
20+
21+
// Assert
22+
AssertWorkflowFinished(result);
23+
var writeLineRecords = GetWriteLineRecords(result);
24+
25+
Assert.Equal(expectedWriteLineCount, writeLineRecords.Count);
26+
if (expectedMessage != null)
27+
{
28+
Assert.Equal(expectedMessage, writeLineRecords[0].ActivityState?[nameof(WriteLine.Text)]);
29+
}
30+
}
31+
32+
private static string GetDefinitionId(string workflowName) => workflowName switch
33+
{
34+
nameof(IfTrueWorkflow) => IfTrueWorkflow.DefinitionId,
35+
nameof(IfFalseWorkflow) => IfFalseWorkflow.DefinitionId,
36+
nameof(IfNoElseWorkflow) => IfNoElseWorkflow.DefinitionId,
37+
_ => throw new ArgumentException($"Unknown workflow: {workflowName}")
38+
};
39+
}
40+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Elsa.Workflows.Activities;
2+
using Elsa.Workflows.Models;
3+
4+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.If;
5+
6+
public class IfTrueWorkflow : WorkflowBase
7+
{
8+
public static readonly string DefinitionId = nameof(IfTrueWorkflow);
9+
10+
protected override void Build(IWorkflowBuilder builder)
11+
{
12+
builder.WithDefinitionId(DefinitionId);
13+
14+
builder.Root = new Sequence
15+
{
16+
Activities =
17+
{
18+
new Elsa.Workflows.Activities.If(new Input<bool>(true))
19+
{
20+
Then = new WriteLine("Condition is true"),
21+
Else = new WriteLine("Condition is false")
22+
}
23+
}
24+
};
25+
}
26+
}
27+
28+
public class IfFalseWorkflow : WorkflowBase
29+
{
30+
public static readonly string DefinitionId = nameof(IfFalseWorkflow);
31+
32+
protected override void Build(IWorkflowBuilder builder)
33+
{
34+
builder.WithDefinitionId(DefinitionId);
35+
36+
builder.Root = new Sequence
37+
{
38+
Activities =
39+
{
40+
new Elsa.Workflows.Activities.If(new Input<bool>(false))
41+
{
42+
Then = new WriteLine("Condition is true"),
43+
Else = new WriteLine("Condition is false")
44+
}
45+
}
46+
};
47+
}
48+
}
49+
50+
public class IfNoElseWorkflow : WorkflowBase
51+
{
52+
public static readonly string DefinitionId = nameof(IfNoElseWorkflow);
53+
54+
protected override void Build(IWorkflowBuilder builder)
55+
{
56+
builder.WithDefinitionId(DefinitionId);
57+
58+
builder.Root = new Sequence
59+
{
60+
Activities =
61+
{
62+
new Elsa.Workflows.Activities.If(new Input<bool>(false))
63+
{
64+
Then = new WriteLine("Condition is true")
65+
// No Else branch
66+
}
67+
}
68+
};
69+
}
70+
}
71+
72+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Elsa.Workflows.ComponentTests.Abstractions;
2+
using Elsa.Workflows.ComponentTests.Fixtures;
3+
4+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.Parallel;
5+
6+
public class ParallelActivityTests(App app) : AppComponentTest(app)
7+
{
8+
[Theory(DisplayName = "Parallel activity should execute all branches")]
9+
[InlineData(nameof(ParallelBasicWorkflow), 4, new[] { "Branch 1", "Branch 2", "Branch 3", "All branches completed" })]
10+
[InlineData(nameof(ParallelWithSequencesWorkflow), 7, null)] // 6 branch steps + final message
11+
public async Task Parallel_ShouldExecuteAllBranches(string workflowName, int expectedWriteLineCount, string[]? expectedMessages)
12+
{
13+
// Arrange
14+
var definitionId = GetDefinitionId(workflowName);
15+
16+
// Act
17+
var result = await RunWorkflowAsync(definitionId);
18+
19+
// Assert
20+
AssertWorkflowFinished(result);
21+
var writeLineRecords = GetWriteLineRecords(result);
22+
Assert.Equal(expectedWriteLineCount, writeLineRecords.Count);
23+
24+
if (expectedMessages != null)
25+
{
26+
var messages = GetWriteLineMessages(result);
27+
foreach (var expected in expectedMessages)
28+
{
29+
Assert.Contains(expected, messages);
30+
}
31+
}
32+
}
33+
34+
private static string GetDefinitionId(string workflowName) => workflowName switch
35+
{
36+
nameof(ParallelBasicWorkflow) => ParallelBasicWorkflow.DefinitionId,
37+
nameof(ParallelWithSequencesWorkflow) => ParallelWithSequencesWorkflow.DefinitionId,
38+
_ => throw new ArgumentException($"Unknown workflow: {workflowName}")
39+
};
40+
}
41+
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using Elsa.Workflows.Activities;
2+
3+
namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.Branching.Parallel;
4+
5+
public class ParallelBasicWorkflow : WorkflowBase
6+
{
7+
public static readonly string DefinitionId = nameof(ParallelBasicWorkflow);
8+
9+
protected override void Build(IWorkflowBuilder builder)
10+
{
11+
builder.WithDefinitionId(DefinitionId);
12+
13+
builder.Root = new Sequence
14+
{
15+
Activities =
16+
{
17+
new Elsa.Workflows.Activities.Parallel
18+
{
19+
Activities =
20+
{
21+
new WriteLine("Branch 1"),
22+
new WriteLine("Branch 2"),
23+
new WriteLine("Branch 3")
24+
}
25+
},
26+
new WriteLine("All branches completed")
27+
}
28+
};
29+
}
30+
}
31+
32+
public class ParallelWithSequencesWorkflow : WorkflowBase
33+
{
34+
public static readonly string DefinitionId = nameof(ParallelWithSequencesWorkflow);
35+
36+
protected override void Build(IWorkflowBuilder builder)
37+
{
38+
builder.WithDefinitionId(DefinitionId);
39+
40+
builder.Root = new Sequence
41+
{
42+
Activities =
43+
{
44+
new Elsa.Workflows.Activities.Parallel
45+
{
46+
Activities =
47+
{
48+
new Sequence
49+
{
50+
Activities =
51+
{
52+
new WriteLine("Branch 1 - Step 1"),
53+
new WriteLine("Branch 1 - Step 2")
54+
}
55+
},
56+
new Sequence
57+
{
58+
Activities =
59+
{
60+
new WriteLine("Branch 2 - Step 1"),
61+
new WriteLine("Branch 2 - Step 2")
62+
}
63+
},
64+
new Sequence
65+
{
66+
Activities =
67+
{
68+
new WriteLine("Branch 3 - Step 1"),
69+
new WriteLine("Branch 3 - Step 2")
70+
}
71+
}
72+
}
73+
},
74+
new WriteLine("All branches completed")
75+
}
76+
};
77+
}
78+
}
79+

0 commit comments

Comments
 (0)