diff --git a/src/core/Elsa.Core/Builders/WorkflowDefinitionBuilder.cs b/src/core/Elsa.Core/Builders/WorkflowDefinitionBuilder.cs
index 68f63d986..857b22bfc 100644
--- a/src/core/Elsa.Core/Builders/WorkflowDefinitionBuilder.cs
+++ b/src/core/Elsa.Core/Builders/WorkflowDefinitionBuilder.cs
@@ -72,4 +72,11 @@ public class WorkflowDefinitionBuilder : IWorkflowDefinitionBuilder
var metadata = new WorkflowMetadata();
return new Workflow(identity, publication, metadata, root, Variables, Metadata, ApplicationProperties);
}
+
+ public Workflow BuildWorkflow(IWorkflow workflowDefinition)
+ {
+ WithDefinitionId(workflowDefinition.GetType().Name);
+ workflowDefinition.Build(this);
+ return BuildWorkflow();
+ }
}
\ No newline at end of file
diff --git a/src/runtime/Elsa.Runtime/Contracts/IWorkflow.cs b/src/core/Elsa.Core/Contracts/IWorkflow.cs
similarity index 59%
rename from src/runtime/Elsa.Runtime/Contracts/IWorkflow.cs
rename to src/core/Elsa.Core/Contracts/IWorkflow.cs
index 3f20e9c16..a361b6813 100644
--- a/src/runtime/Elsa.Runtime/Contracts/IWorkflow.cs
+++ b/src/core/Elsa.Core/Contracts/IWorkflow.cs
@@ -1,6 +1,4 @@
-using Elsa.Contracts;
-
-namespace Elsa.Runtime.Contracts;
+namespace Elsa.Contracts;
public interface IWorkflow
{
diff --git a/src/core/Elsa.Core/Elsa.Core.csproj b/src/core/Elsa.Core/Elsa.Core.csproj
index ab2dce856..00dccc304 100644
--- a/src/core/Elsa.Core/Elsa.Core.csproj
+++ b/src/core/Elsa.Core/Elsa.Core.csproj
@@ -9,11 +9,11 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/src/runtime/Elsa.Runtime/Extensions/WorkflowDictionaryExtensions.cs b/src/runtime/Elsa.Runtime/Extensions/WorkflowDictionaryExtensions.cs
index 6ee19c492..eb1241362 100644
--- a/src/runtime/Elsa.Runtime/Extensions/WorkflowDictionaryExtensions.cs
+++ b/src/runtime/Elsa.Runtime/Extensions/WorkflowDictionaryExtensions.cs
@@ -1,3 +1,4 @@
+using Elsa.Contracts;
using Elsa.Runtime.Contracts;
using Microsoft.Extensions.DependencyInjection;
diff --git a/src/runtime/Elsa.Runtime/Options/WorkflowRuntimeOptions.cs b/src/runtime/Elsa.Runtime/Options/WorkflowRuntimeOptions.cs
index 115c309d7..682b6e756 100644
--- a/src/runtime/Elsa.Runtime/Options/WorkflowRuntimeOptions.cs
+++ b/src/runtime/Elsa.Runtime/Options/WorkflowRuntimeOptions.cs
@@ -1,3 +1,4 @@
+using Elsa.Contracts;
using Elsa.Runtime.Contracts;
using Elsa.Runtime.Services;
using Microsoft.Extensions.DependencyInjection;
diff --git a/test/Elsa.IntegrationTests/Workflows/ForEachWorkflowTests.cs b/test/Elsa.IntegrationTests/Workflows/ForEachWorkflowTests.cs
new file mode 100644
index 000000000..2bfa59b6b
--- /dev/null
+++ b/test/Elsa.IntegrationTests/Workflows/ForEachWorkflowTests.cs
@@ -0,0 +1,60 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Elsa.Activities;
+using Elsa.Builders;
+using Elsa.Contracts;
+using Elsa.Models;
+using Elsa.Modules.Activities.Activities.Console;
+using Elsa.Testing.Shared;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Elsa.IntegrationTests.Workflows;
+
+public class ForEachWorkflowTests
+{
+ private readonly IWorkflowRunner _workflowRunner;
+ private readonly CapturingTextWriter _capturingTextWriter = new();
+ private readonly Workflow _workflow;
+
+ public ForEachWorkflowTests(ITestOutputHelper testOutputHelper)
+ {
+ var services = new TestContainerBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
+ _workflowRunner = services.GetRequiredService();
+ _workflow = new WorkflowDefinitionBuilder().BuildWorkflow(new ForEachWorkflow());
+ }
+
+ [Fact(DisplayName = "ForEach outputs each iteration")]
+ public async Task Test1()
+ {
+ await _workflowRunner.RunAsync(_workflow);
+ var lines = _capturingTextWriter.Lines.ToList();
+ Assert.Equal("C#", lines[0]);
+ Assert.Equal("Rust", lines[1]);
+ Assert.Equal("Go", lines[2]);
+ }
+
+ private class ForEachWorkflow : IWorkflow
+ {
+ public void Build(IWorkflowDefinitionBuilder workflow)
+ {
+ var items = new[] { "C#", "Rust", "Go" };
+ var currentItem = new Variable();
+
+ workflow.WithRoot(new Sequence
+ {
+ Activities =
+ {
+ new ForEach
+ {
+ Items = new Input>(items),
+ CurrentValue = currentItem,
+ Body = new WriteLine(context => currentItem.Get(context))
+ },
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Elsa.IntegrationTests/Workflows/HelloWorldWorkflowTests.cs b/test/Elsa.IntegrationTests/Workflows/HelloWorldWorkflowTests.cs
index 3c1b13302..def5e5741 100644
--- a/test/Elsa.IntegrationTests/Workflows/HelloWorldWorkflowTests.cs
+++ b/test/Elsa.IntegrationTests/Workflows/HelloWorldWorkflowTests.cs
@@ -3,8 +3,6 @@ using System.Threading.Tasks;
using Elsa.Contracts;
using Elsa.Models;
using Elsa.Modules.Activities.Activities.Console;
-using Elsa.Modules.Activities.Contracts;
-using Elsa.Modules.Activities.Providers;
using Elsa.Testing.Shared;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
@@ -19,11 +17,10 @@ public class HelloWorldWorkflowTests
public HelloWorldWorkflowTests(ITestOutputHelper testOutputHelper)
{
- var combinedTextWriter = new CombinedTextWriter(_capturingTextWriter, new XunitConsoleTextWriter(testOutputHelper));
- var services = TestContainerBuilder.Build(testOutputHelper, x => x.AddSingleton(new StandardOutStreamProvider(combinedTextWriter)));
+ var services = new TestContainerBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
_workflowRunner = services.GetRequiredService();
}
-
+
[Fact(DisplayName = "Run a simple workflow")]
public async Task Test1()
{
diff --git a/test/Elsa.Testing.Shared/TestContainerBuilder.cs b/test/Elsa.Testing.Shared/TestContainerBuilder.cs
index dc1263f44..c05ed1e2b 100644
--- a/test/Elsa.Testing.Shared/TestContainerBuilder.cs
+++ b/test/Elsa.Testing.Shared/TestContainerBuilder.cs
@@ -11,20 +11,34 @@ namespace Elsa.Testing.Shared;
public class TestContainerBuilder
{
- public static IServiceProvider Build(ITestOutputHelper testOutputHelper, Action? configureServices = default)
- {
- var services = new ServiceCollection();
+ private readonly ITestOutputHelper _testOutputHelper;
+ private readonly ServiceCollection _services;
- services
+ public TestContainerBuilder(ITestOutputHelper testOutputHelper)
+ {
+ _testOutputHelper = testOutputHelper;
+ _services = new ServiceCollection();
+
+ _services
.AddElsa()
.AddInMemoryPersistence()
+ .AddSingleton(testOutputHelper)
+ .AddSingleton(new StandardOutStreamProvider(new XunitConsoleTextWriter(testOutputHelper)))
.AddLogging(logging => logging.AddProvider(new XunitLoggerProvider(testOutputHelper)).SetMinimumLevel(LogLevel.Debug));
+ }
- services.AddSingleton(testOutputHelper);
- services.AddSingleton(new StandardOutStreamProvider(new XunitConsoleTextWriter(testOutputHelper)));
-
- configureServices?.Invoke(services);
+ public IServiceProvider Build() => _services.BuildServiceProvider();
- return services.BuildServiceProvider();
+ public TestContainerBuilder Configure(Action configure)
+ {
+ configure(_services);
+ return this;
+ }
+
+ public TestContainerBuilder WithCapturingTextWriter(CapturingTextWriter capturingTextWriter)
+ {
+ var combinedTextWriter = new CombinedTextWriter(capturingTextWriter, new XunitConsoleTextWriter(_testOutputHelper));
+ _services.AddSingleton(new StandardOutStreamProvider(combinedTextWriter));
+ return this;
}
}
\ No newline at end of file