Add project files.
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Models;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Activities.IntegrationTests;
|
||||
|
||||
public class SetNameTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public SetNameTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_serviceProvider = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "SetName sets the workflow instance name.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
const string expectedName = "Foo";
|
||||
var setName = new SetName(new Input<string>(expectedName));
|
||||
var result = await _serviceProvider.RunActivityAsync(setName);
|
||||
var actualName = result.WorkflowState.Name;
|
||||
Assert.Equal(expectedName, actualName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Xunit;
|
||||
@@ -0,0 +1,25 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Activities.IntegrationTests;
|
||||
|
||||
public class WriteLineTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public WriteLineTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_serviceProvider = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "WriteLine prints the expected line to the console.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
const string expectedLine = "Hello world!";
|
||||
var writeLine = new WriteLine(expectedLine);
|
||||
await _serviceProvider.RunActivityAsync(writeLine);
|
||||
Assert.Equal(expectedLine, _capturingTextWriter.Lines.Single());
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Alterations\Elsa.Alterations.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Runtime\Elsa.Workflows.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Workflows\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Workflows\version-1.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Workflows\version-2.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,73 @@
|
||||
using Elsa.Alterations.AlterationTypes;
|
||||
using Elsa.Alterations.Core.Contracts;
|
||||
using Elsa.Alterations.Extensions;
|
||||
using Elsa.Common.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Management;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Alterations.IntegrationTests;
|
||||
|
||||
/// <summary>
|
||||
/// Contains tests for migration.
|
||||
/// </summary>
|
||||
public class MigrationTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IAlterationRunner _alterationRunner;
|
||||
private readonly IWorkflowInstanceStore _workflowInstanceStore;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MigrationTests"/> class.
|
||||
/// </summary>
|
||||
public MigrationTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.ConfigureElsa(elsa => elsa.UseAlterations())
|
||||
.Build();
|
||||
_alterationRunner = _services.GetRequiredService<IAlterationRunner>();
|
||||
_workflowInstanceStore = _services.GetRequiredService<IWorkflowInstanceStore>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method tests the migration from version 1 to version 2.
|
||||
/// </summary>
|
||||
[Fact(DisplayName = "Migrating from version 1 to 2 succeeds")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflows.
|
||||
await _services.ImportWorkflowDefinitionAsync("Workflows/version-1.json");
|
||||
await _services.ImportWorkflowDefinitionAsync("Workflows/version-2.json");
|
||||
|
||||
// Run version 1 workflow.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync("my-workflow", versionOptions: VersionOptions.SpecificVersion(1));
|
||||
|
||||
// Migrate to version 2.
|
||||
var alterations = new IAlteration[]
|
||||
{
|
||||
new Migrate
|
||||
{
|
||||
TargetVersion = 2
|
||||
}
|
||||
};
|
||||
var instanceIds = new[]
|
||||
{
|
||||
workflowState.Id
|
||||
};
|
||||
var migrationResult = await _alterationRunner.RunAsync(instanceIds, alterations);
|
||||
|
||||
// Assert success.
|
||||
Assert.True(migrationResult.All(x => x.IsSuccessful));
|
||||
|
||||
// Assert that the workflow instance is now at version 2.
|
||||
var workflowState2 = await _workflowInstanceStore.FindAsync(workflowState.Id);
|
||||
Assert.Equal(2, workflowState2!.Version);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Xunit;
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": "b760f121e7dc5dae",
|
||||
"definitionId": "my-workflow",
|
||||
"name": "Version 1",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "52ae1d65f7896a9e",
|
||||
"nodeId": "Workflow1:52ae1d65f7896a9e",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Version 1"
|
||||
}
|
||||
},
|
||||
"id": "3a1ab61a351fe232",
|
||||
"nodeId": "Workflow1:52ae1d65f7896a9e:3a1ab61a351fe232",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -121.796875,
|
||||
"y": 272
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": "4aca2e3aa79475d3",
|
||||
"definitionId": "my-workflow",
|
||||
"name": "Version 2",
|
||||
"version": 2,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "52ae1d65f7896a9e",
|
||||
"nodeId": "Workflow1:52ae1d65f7896a9e",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Version 2"
|
||||
}
|
||||
},
|
||||
"id": "3a1ab61a351fe232",
|
||||
"nodeId": "Workflow1:52ae1d65f7896a9e:3a1ab61a351fe232",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -121.796875,
|
||||
"y": 272
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.JavaScript\Elsa.JavaScript.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Dynamic;
|
||||
using System.Numerics;
|
||||
using System.Text.Json;
|
||||
using Elsa.Common.Converters;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.JavaScript.Contracts;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.JavaScript.IntegrationTests;
|
||||
public class JsonConverterTest(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
|
||||
[Fact(DisplayName = "JavaScript BigInt mapping to BigInteger serialization")]
|
||||
public async Task Test1()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var script = @"return {
|
||||
'BigNumber': BigInt('7239948466988781569')
|
||||
}";
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new MemoryRegister());
|
||||
var result = (await javaScriptEvaluator.EvaluateAsync(script, typeof(ExpandoObject), expressionExecutionContext))!;
|
||||
var options = new JsonSerializerOptions()
|
||||
{
|
||||
Converters = { new BigIntegerJsonConverter() }
|
||||
};
|
||||
var serializedText = JsonSerializer.Serialize(result, options);
|
||||
|
||||
Assert.Equal("{\"BigNumber\":7239948466988781569}", serializedText);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "JavaScript BigInt mapping to BigInteger serialization")]
|
||||
public async Task Test2()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var script = @"return {
|
||||
'BigNumber': BigInt('7239948466988781569')
|
||||
}";
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new MemoryRegister());
|
||||
var result = (await javaScriptEvaluator.EvaluateAsync(script, typeof(ExpandoObject), expressionExecutionContext))!;
|
||||
var serializedText = JsonSerializer.Serialize(result);
|
||||
|
||||
Assert.Equal("{\"BigNumber\":{\"IsPowerOfTwo\":false,\"IsZero\":false,\"IsOne\":false,\"IsEven\":false,\"Sign\":1}}", serializedText);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "BigIntegerJsonConverter Deserialize")]
|
||||
public async Task Test3()
|
||||
{
|
||||
var options = new JsonSerializerOptions()
|
||||
{
|
||||
Converters = { new BigIntegerJsonConverter() }
|
||||
};
|
||||
|
||||
BigInteger bigInteger = JsonSerializer.Deserialize<BigInteger>("7239948466988781569", options);
|
||||
|
||||
Assert.Equal(7239948466988781569, bigInteger);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System.Text.Json;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.JavaScript.Contracts;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.JavaScript.IntegrationTests;
|
||||
|
||||
public class JsonElementConverterTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
|
||||
[Fact(DisplayName = "JsonElement JsonObject can be passed to JavaScript")]
|
||||
public async Task TestJsonObjectPassedAsJsonElement()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new());
|
||||
var jsonVariable = new Variable<object>("JsonVariable", "");
|
||||
var jsonString = "{\"name\": \"John\", \"age\": 30}";
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
||||
|
||||
jsonVariable.Set(expressionExecutionContext, jsonElement);
|
||||
var script = "getVariable('JsonVariable').age";
|
||||
var result = await javaScriptEvaluator.EvaluateAsync(script, typeof(int), expressionExecutionContext);
|
||||
Assert.Equal(30, result);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "JsonElement JsonArray can be passed to JavaScript")]
|
||||
public async Task TestJsonArrayPassedAsJsonElement()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new());
|
||||
var jsonVariable = new Variable<object>("JsonVariable", "");
|
||||
var jsonString = "[1, 2, 3, 4, 5, 6]";
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
||||
|
||||
jsonVariable.Set(expressionExecutionContext, jsonElement);
|
||||
var script = "getVariable('JsonVariable')[3]";
|
||||
var result = await javaScriptEvaluator.EvaluateAsync(script, typeof(int), expressionExecutionContext);
|
||||
Assert.Equal(4, result);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "JsonElement string can be passed to JavaScript")]
|
||||
public async Task TestStringPassedAsJsonElement()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new());
|
||||
var jsonVariable = new Variable<object>("JsonVariable", "");
|
||||
var jsonString = "\"I'm just a string\"";
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
||||
|
||||
jsonVariable.Set(expressionExecutionContext, jsonElement);
|
||||
var script = "getVariable('JsonVariable')";
|
||||
var result = await javaScriptEvaluator.EvaluateAsync(script, typeof(string), expressionExecutionContext);
|
||||
Assert.Equal("I'm just a string", result);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "JsonElement boolean can be passed to JavaScript")]
|
||||
public async Task TestBooleanPassedAsJsonElement()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new());
|
||||
var jsonVariable = new Variable<object>("JsonVariable", "");
|
||||
var jsonString = "false";
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
||||
|
||||
jsonVariable.Set(expressionExecutionContext, jsonElement);
|
||||
var script = "getVariable('JsonVariable')";
|
||||
var result = await javaScriptEvaluator.EvaluateAsync(script, typeof(bool), expressionExecutionContext);
|
||||
Assert.Equal(false, result);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "JsonElement containing nested Json objects and arrays be passed to JavaScript")]
|
||||
public async Task TestNestedJsonPassedAsJsonElement()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new());
|
||||
var jsonVariable = new Variable<object>("JsonVariable", "");
|
||||
|
||||
var jsonString = @"
|
||||
{
|
||||
""name"": ""John Doe"",
|
||||
""age"": 35,
|
||||
""address"": {
|
||||
""street"": ""123 Main St"",
|
||||
""city"": ""Springfield"",
|
||||
""zip"": ""12345"",
|
||||
""coordinates"": { ""lat"": 40.7128, ""lng"": -74.006 }
|
||||
},
|
||||
""skills"": [
|
||||
{ ""name"": ""Programming"", ""level"": ""Advanced"" },
|
||||
{ ""name"": ""Writing"", ""level"": ""Intermediate"" }
|
||||
],
|
||||
""projects"": [
|
||||
{
|
||||
""title"": ""Project A"",
|
||||
""status"": ""Completed"",
|
||||
""team"": [""Alice"", ""Bob""]
|
||||
},
|
||||
{
|
||||
""title"": ""Project B"",
|
||||
""status"": ""In Progress"",
|
||||
""team"": [""Charlie"", ""David"", ""Eve""]
|
||||
}
|
||||
],
|
||||
""isEmployed"": true,
|
||||
""contact"": { ""email"": ""john.doe@example.com"", ""phone"": ""555-1234"" }
|
||||
}";
|
||||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonString);
|
||||
|
||||
jsonVariable.Set(expressionExecutionContext, jsonElement);
|
||||
|
||||
var script = "getVariable('JsonVariable').projects[1].team[0]";
|
||||
var result = await javaScriptEvaluator.EvaluateAsync(script, typeof(string), expressionExecutionContext);
|
||||
Assert.Equal("Charlie", result);
|
||||
|
||||
var script2 = "getVariable('JsonVariable').isEmployed";
|
||||
var result2 = await javaScriptEvaluator.EvaluateAsync(script2, typeof(bool), expressionExecutionContext);
|
||||
Assert.Equal(true, result2);
|
||||
|
||||
var script3 = "getVariable('JsonVariable').skills[0].level";
|
||||
var result3 = await javaScriptEvaluator.EvaluateAsync(script3, typeof(string), expressionExecutionContext);
|
||||
Assert.Equal("Advanced", result3);
|
||||
|
||||
var script4 = "getVariable('JsonVariable').address.coordinates.lat";
|
||||
var result4 = await javaScriptEvaluator.EvaluateAsync(script4, typeof(double), expressionExecutionContext);
|
||||
Assert.Equal(40.7128, result4);
|
||||
|
||||
var script5 = "getVariable('JsonVariable').age";
|
||||
var result5 = await javaScriptEvaluator.EvaluateAsync(script5, typeof(int), expressionExecutionContext);
|
||||
Assert.Equal(35, result5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Text.Json;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.JavaScript.Contracts;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.JavaScript.IntegrationTests;
|
||||
|
||||
public class ToJsonTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
|
||||
[Fact(DisplayName = "Serialize large unicode string using JavaScript's toJson function")]
|
||||
public async Task Test1()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var unicodeString = UnicodeRangeGenerator.GenerateUnicodeString();
|
||||
var script = $"toJson({{ text: '{unicodeString}' }})";
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new MemoryRegister());
|
||||
var result = (string)(await javaScriptEvaluator.EvaluateAsync(script, typeof(string), expressionExecutionContext))!;
|
||||
var serializedText = JsonDocument.Parse(result).RootElement.GetProperty("text").GetString();
|
||||
Assert.Equal(unicodeString, serializedText);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Serialize large unicode string using JavaScript's toJson function from a workflow variable")]
|
||||
public async Task Test2()
|
||||
{
|
||||
var javaScriptEvaluator = _serviceProvider.GetRequiredService<IJavaScriptEvaluator>();
|
||||
var expressionExecutionContext = new ExpressionExecutionContext(_serviceProvider, new MemoryRegister());
|
||||
var unicodeString = UnicodeRangeGenerator.GenerateUnicodeString();
|
||||
var payloadVariable = new Variable<object>("Payload", null!);
|
||||
var payload = new
|
||||
{
|
||||
Text = unicodeString
|
||||
};
|
||||
payloadVariable.Set(expressionExecutionContext, payload);
|
||||
var script = "toJson(getPayload())";
|
||||
var result = (string)(await javaScriptEvaluator.EvaluateAsync(script, typeof(string), expressionExecutionContext))!;
|
||||
var serializedText = JsonDocument.Parse(result).RootElement.GetProperty("Text").GetString();
|
||||
Assert.Equal(unicodeString, serializedText);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Http\Elsa.Http.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Resilience\Elsa.Resilience.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
using System.Net;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http;
|
||||
using Elsa.Resilience.Extensions;
|
||||
using Elsa.Resilience.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class FlowSendHttpRequestResilienceTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly TestRetryAttemptRecorder _recorder = new();
|
||||
|
||||
public FlowSendHttpRequestResilienceTests(ITestOutputHelper output)
|
||||
{
|
||||
var handler = new SequentialStatusHandler([HttpStatusCode.TooManyRequests, HttpStatusCode.ServiceUnavailable, HttpStatusCode.OK]);
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Resilience:Strategies:0:$type"] = "HttpResilienceStrategy",
|
||||
["Resilience:Strategies:0:Id"] = "test",
|
||||
["Resilience:Strategies:0:DisplayName"] = "Test",
|
||||
["Resilience:Strategies:0:MaxRetryAttempts"] = "5",
|
||||
["Resilience:Strategies:0:Delay"] = "00:00:00.001"
|
||||
})
|
||||
.Build();
|
||||
|
||||
_services = new TestApplicationBuilder(output)
|
||||
.ConfigureServices(s =>
|
||||
{
|
||||
s.AddSingleton<IConfiguration>(configuration);
|
||||
})
|
||||
.ConfigureElsa(module =>
|
||||
{
|
||||
module.UseHttp(http =>
|
||||
{
|
||||
http.HttpClientBuilder = builder => builder.ConfigurePrimaryHttpMessageHandler(() => handler);
|
||||
});
|
||||
|
||||
module.UseResilience(resilience =>
|
||||
{
|
||||
resilience.WithRetryAttemptRecorder(_ => _recorder);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "FlowSendHttpRequest retries using selected resilience strategy")]
|
||||
public async Task InvokesResilienceStrategy()
|
||||
{
|
||||
var activity = new FlowSendHttpRequest
|
||||
{
|
||||
Url = new(new Uri("http://localhost/test")),
|
||||
Method = new("GET"),
|
||||
ExpectedStatusCodes = new([200]),
|
||||
CustomProperties =
|
||||
{
|
||||
["resilienceStrategy"] = new ResilienceStrategyConfig
|
||||
{
|
||||
Mode = ResilienceStrategyConfigMode.Identifier,
|
||||
StrategyId = "test"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _services.RunActivityAsync(activity);
|
||||
var statusCode = result.GetActivityOutput<int>(activity, nameof(SendHttpRequestBase.StatusCode));
|
||||
|
||||
Assert.Equal(200, statusCode);
|
||||
Assert.Equal(2, _recorder.Attempts.Count);
|
||||
Assert.Collection(_recorder.Attempts,
|
||||
first => Assert.Equal(0, first.AttemptNumber),
|
||||
second => Assert.Equal(1, second.AttemptNumber));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class SequentialStatusHandler(IEnumerable<HttpStatusCode> codes) : HttpMessageHandler
|
||||
{
|
||||
private readonly Queue<HttpStatusCode> _codes = new(codes);
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var code = _codes.Count > 0 ? _codes.Dequeue() : _codes.Last();
|
||||
var response = new HttpResponseMessage(code)
|
||||
{
|
||||
Content = new StringContent(string.Empty)
|
||||
};
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Elsa.Resilience.Entities;
|
||||
using Elsa.Resilience.Models;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class TestRetryAttemptRecorder : IRetryAttemptRecorder
|
||||
{
|
||||
public IList<RetryAttemptRecord> Attempts { get; } = new List<RetryAttemptRecord>();
|
||||
|
||||
public Task RecordAsync(RecordRetryAttemptsContext context)
|
||||
{
|
||||
foreach (var record in context.Attempts)
|
||||
Attempts.Add(record);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Xunit;
|
||||
@@ -0,0 +1,64 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Activities.Workflows;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class BreakTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public BreakTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break exits out of ForEach")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BreakForEachWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "C#", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break exits out of immediate ForEach only")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<NestedForEachWithBreakWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "C#", "Classes", "Rust", "Classes", "Go", "Classes" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break exits out of For")]
|
||||
public async Task Test3()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BreakForWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "0", "1", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break exits out of While")]
|
||||
public async Task Test4()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BreakWhileWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "1", "2", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break removes the right bookmarks")]
|
||||
public async Task Test5()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BreakWhileWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "1", "2", "End" }, lines);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities.Workflows;
|
||||
|
||||
class BreakForEachWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var items = new[] { "C#", "Rust", "Go" };
|
||||
var currentItem = new Variable<string>("CurrentItem", "");
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new ForEach<string>
|
||||
{
|
||||
Items = new(items),
|
||||
CurrentValue = new (currentItem),
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new If(context => currentItem.Get(context) == "Rust")
|
||||
{
|
||||
Then = new Break()
|
||||
},
|
||||
new WriteLine(currentItem)
|
||||
}
|
||||
}
|
||||
},
|
||||
new WriteLine("End"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities.Workflows;
|
||||
|
||||
class BreakForWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", null);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new For(0, 3, 1)
|
||||
{
|
||||
CurrentValue = new (currentValue),
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new If(context => currentValue.Get(context) == 2)
|
||||
{
|
||||
Then = new Break()
|
||||
},
|
||||
new WriteLine(context => currentValue.Get(context).ToString()),
|
||||
}
|
||||
}
|
||||
},
|
||||
new WriteLine("End"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities.Workflows;
|
||||
|
||||
public class BreakWhileForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", 0);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Variables = { currentValue },
|
||||
Activities =
|
||||
{
|
||||
While.True(new Fork
|
||||
{
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new SetVariable
|
||||
{
|
||||
Variable = currentValue,
|
||||
Value = new (context => currentValue.Get(context) + 1)
|
||||
},
|
||||
new If(context => currentValue.Get(context) == 3)
|
||||
{
|
||||
Then = new Break()
|
||||
}
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Waiting for event..."),
|
||||
new Event("Some event") { Id = "SomeEvent" },
|
||||
new WriteLine("Resuming"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities.Workflows;
|
||||
|
||||
public class BreakWhileWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", 0);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Variables = { currentValue },
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
While.True(new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new SetVariable
|
||||
{
|
||||
Variable = currentValue,
|
||||
Value = new (context => currentValue.Get(context) + 1)
|
||||
},
|
||||
new If(context => currentValue.Get(context) == 3)
|
||||
{
|
||||
Then = new Break()
|
||||
},
|
||||
new WriteLine(context => currentValue.Get(context).ToString()),
|
||||
}
|
||||
}),
|
||||
new WriteLine("End"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class FinishForkedWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Fork
|
||||
{
|
||||
JoinMode = ForkJoinMode.WaitAll,
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 1"),
|
||||
new Event("Event 1")
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 2"),
|
||||
new Finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class FinishSequentialWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Line 1"),
|
||||
new Finish(),
|
||||
new WriteLine("Line 2")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class FinishTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public FinishTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Subsequent activities are not executed")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<FinishSequentialWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Workflow status is set to Finished")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync<FinishSequentialWorkflow>();
|
||||
var workflowState = result.WorkflowState;
|
||||
Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
|
||||
Assert.Equal(WorkflowSubStatus.Finished, workflowState.SubStatus);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "All bookmarks are removed")]
|
||||
public async Task Test3()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync<FinishSequentialWorkflow>();
|
||||
Assert.Empty(result.WorkflowState.Bookmarks);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class ForEachTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ForEachTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "ForEach outputs each iteration")]
|
||||
public async Task Test1()
|
||||
{
|
||||
var items = new[] { "C#", "Rust", "Go"};
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync(new ForEachWorkflow(items));
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(items, lines);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
class ForEachWorkflow : WorkflowBase
|
||||
{
|
||||
private readonly ICollection<string> _items;
|
||||
|
||||
public ForEachWorkflow(ICollection<string> items)
|
||||
{
|
||||
_items = items;
|
||||
}
|
||||
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentItem = new Variable<string>("CurrentItem", "");
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Variables = { currentItem },
|
||||
Activities =
|
||||
{
|
||||
new ForEach<string>
|
||||
{
|
||||
Items = new(_items),
|
||||
CurrentValue = new(currentItem),
|
||||
Body = new WriteLine(currentItem)
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
class NestedForEachWithBreakWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var outerItems = new[] { "C#", "Rust", "Go" };
|
||||
var innerItems = new[] { "Classes", "Functions", "Modules" };
|
||||
var currentOuterItem = new Variable<string>("CurrentOuterItem", "");
|
||||
var currentInnerItem = new Variable<string>("CurrentInnerItem", "");
|
||||
|
||||
workflow.Root = new ForEach<string>(outerItems)
|
||||
{
|
||||
CurrentValue = new (currentOuterItem),
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine(currentOuterItem),
|
||||
new ForEach<string>(innerItems)
|
||||
{
|
||||
CurrentValue = new (currentInnerItem),
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new If(context => currentInnerItem.Get(context) == "Functions")
|
||||
{
|
||||
Then = new Break()
|
||||
},
|
||||
new WriteLine(currentInnerItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class BasicForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Fork
|
||||
{
|
||||
Branches =
|
||||
{
|
||||
new WriteLine("Branch 1"),
|
||||
new WriteLine("Branch 2"),
|
||||
new WriteLine("Branch 3")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Options;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class ForkTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
|
||||
private IServiceProvider _services;
|
||||
|
||||
public ForkTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowBuilderFactory = _services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Each branch executes")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<BasicForkWorkflow>();
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Branch 1", "Branch 2", "Branch 3" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Wait AnyAsync causes workflow to continue")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<JoinAnyForkWorkflow>();
|
||||
|
||||
// First run.
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Collect one of the bookmarks to resume the workflow.
|
||||
var bookmark = result.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Event2");
|
||||
Assert.NotNull(bookmark);
|
||||
|
||||
// Resume the workflow.
|
||||
var runOptions = new RunWorkflowOptions { BookmarkId = bookmark.Id };
|
||||
await _workflowRunner.RunAsync(workflow, result.WorkflowState, runOptions);
|
||||
|
||||
// Verify output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Branch 2", "End" }, lines);
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class JoinAnyForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new Fork
|
||||
{
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new Event("Event 1")
|
||||
{
|
||||
Id = "Event1"
|
||||
},
|
||||
new WriteLine("Branch 1")
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new Event("Event 2")
|
||||
{
|
||||
Id = "Event2"
|
||||
},
|
||||
new WriteLine("Branch 2")
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new Event("Event 3")
|
||||
{
|
||||
Id = "Event3"
|
||||
},
|
||||
new WriteLine("Branch 3")
|
||||
}
|
||||
},
|
||||
},
|
||||
JoinMode = ForkJoinMode.WaitAny
|
||||
},
|
||||
new WriteLine("End")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class IfTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public IfTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "The correct branch executes when condition is true")]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task Test1(bool conditionResult)
|
||||
{
|
||||
var result = default(bool?);
|
||||
|
||||
var activity = new If(() => conditionResult)
|
||||
{
|
||||
Then = new Inline(() => result = true),
|
||||
Else = new Inline(() => result = false)
|
||||
};
|
||||
await _services.RunActivityAsync(activity);
|
||||
Assert.Equal(conditionResult, result);
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "The If activity completes only after either one of its branches completed")]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task Test2(bool conditionResult)
|
||||
{
|
||||
var activity = new If(() => conditionResult)
|
||||
{
|
||||
Then = new Inline(),
|
||||
Else = new Inline()
|
||||
};
|
||||
var result = await _services.RunActivityAsync(activity);
|
||||
Assert.Equal(WorkflowStatus.Finished, result.WorkflowState.Status);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The If activity produces a result when one of its branches completes")]
|
||||
public async Task Test3()
|
||||
{
|
||||
var activity = new If(() => true);
|
||||
var result = await _services.RunActivityAsync(activity);
|
||||
var activityResult = result.GetActivityOutput<bool>(activity);
|
||||
|
||||
Assert.True(activityResult);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
class NestedSequentialWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Line 1"),
|
||||
new WriteLine("Line 2"),
|
||||
new WriteLine("Line 3")
|
||||
}
|
||||
},
|
||||
new WriteLine("End"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class SequenceTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public SequenceTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Sequence completes after its child activities complete")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync(new SequentialWorkflow());
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1", "Line 2", "Line 3" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Sequence completes after its child sequence activity complete")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync(new NestedSequentialWorkflow());
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Line 1", "Line 2", "Line 3", "End" }, lines);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
class SequentialWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Line 1"),
|
||||
new WriteLine("Line 2"),
|
||||
new WriteLine("Line 3")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Activities;
|
||||
|
||||
public class WriteLineTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public WriteLineTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Run a simple workflow")]
|
||||
public async Task Test1()
|
||||
{
|
||||
var expectedOutput = "Hello World!";
|
||||
var workflow = Workflow.FromActivity(new WriteLine(expectedOutput));
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
var line = _capturingTextWriter.Lines.FirstOrDefault();
|
||||
Assert.Equal(expectedOutput, line);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Core;
|
||||
|
||||
public class ScheduleActivityExecutionContextTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
|
||||
[Fact(DisplayName = "Scheduling an activity that is not part of the workflow should throw an exception")]
|
||||
public async Task ScheduleActivityAsync_WithActivityNotPartOfWorkflow_ShouldThrowException()
|
||||
{
|
||||
await _serviceProvider.PopulateRegistriesAsync();
|
||||
var writeLineA = new WriteLine("Test");
|
||||
var writeLineB = new WriteLine("Test");
|
||||
var workflow = new Workflow
|
||||
{
|
||||
Root = writeLineA
|
||||
};
|
||||
var workflowGraphBuilder = _serviceProvider.GetRequiredService<IWorkflowGraphBuilder>();
|
||||
var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow);
|
||||
var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(_serviceProvider, workflowGraph, "test");
|
||||
var activityExecutionContext = await workflowExecutionContext.CreateActivityExecutionContextAsync(writeLineA);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => activityExecutionContext.ScheduleActivityAsync(writeLineB).AsTask());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Text.Json;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Core;
|
||||
|
||||
public class SerializerUnicodeEncodingTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
|
||||
[Fact]
|
||||
public void TestPayloadSerializer()
|
||||
{
|
||||
var serializer = _serviceProvider.GetRequiredService<IPayloadSerializer>();
|
||||
TestSerializer(input => serializer.Serialize(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestApiSerializer()
|
||||
{
|
||||
var serializer = _serviceProvider.GetRequiredService<IApiSerializer>();
|
||||
TestSerializer(input => serializer.Serialize(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestBookmarkPayloadSerializer()
|
||||
{
|
||||
var serializer = _serviceProvider.GetRequiredService<IBookmarkPayloadSerializer>();
|
||||
TestSerializer(input => serializer.Serialize(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSafeSerializer()
|
||||
{
|
||||
var serializer = _serviceProvider.GetRequiredService<ISafeSerializer>();
|
||||
TestSerializer(input => serializer.Serialize(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWorkflowStateSerializer()
|
||||
{
|
||||
var serializer = _serviceProvider.GetRequiredService<IWorkflowStateSerializer>();
|
||||
TestSerializer(input => serializer.Serialize(input));
|
||||
}
|
||||
|
||||
private void TestSerializer(Func<object, string> serialize)
|
||||
{
|
||||
var unicodeString = UnicodeRangeGenerator.GenerateUnicodeString();
|
||||
var anonymousObject = new
|
||||
{
|
||||
Text = unicodeString
|
||||
};
|
||||
var serializedJson = serialize(anonymousObject);
|
||||
var serializedStringValue = GetSerializedTextValue(serializedJson);
|
||||
Assert.Equal(unicodeString, serializedStringValue);
|
||||
}
|
||||
|
||||
private string GetSerializedTextValue(string serializedJson)
|
||||
{
|
||||
var rootElement = JsonDocument.Parse(serializedJson).RootElement;
|
||||
return GetCaseInsensitiveSerializedTextValue(rootElement, "text", "Text");
|
||||
}
|
||||
|
||||
private string GetCaseInsensitiveSerializedTextValue(JsonElement jsonElement, params string[] propertyNames)
|
||||
{
|
||||
foreach (string propertyName in propertyNames)
|
||||
if (jsonElement.TryGetProperty(propertyName, out var property))
|
||||
return property.GetString()!;
|
||||
throw new KeyNotFoundException($"None of the following properties were found: {string.Join(", ", propertyNames)}");
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{ca65b7d5-57e8-4932-b8b8-732d040c9b3a}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Proto.Persistence.Sqlite" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Http\Elsa.Http.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.JavaScript\Elsa.JavaScript.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Runtime.ProtoActor\Elsa.Workflows.Runtime.ProtoActor.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Scheduling\Elsa.Scheduling.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.WorkflowProviders.BlobStorage\Elsa.WorkflowProviders.BlobStorage.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Api\Elsa.Workflows.Api.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Runtime\Elsa.Workflows.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Serialization\**\*.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Update="Scenarios\**\Workflows\*.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Update="Scenarios\DependencyWorkflowsPublishing\Workflows\child.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Scenarios\DependencyWorkflowsPublishing\Workflows\parent.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cbreak/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cfinish/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cforeach/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cfork/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cif/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Csequence/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=activities_005Cwriteline/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=break/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=foreach/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=if/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=sequence/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=writeline/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityNotificationsMiddleware;
|
||||
|
||||
public class Spy
|
||||
{
|
||||
public bool ActivityExecutingWasCalled { get; set; }
|
||||
public bool ActivityExecutedWasCalled { get; set; }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
using Elsa.Mediator.Contracts;
|
||||
using Elsa.Workflows.Notifications;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityNotificationsMiddleware;
|
||||
|
||||
public class TestHandler : INotificationHandler<ActivityExecuting>, INotificationHandler<ActivityExecuted>
|
||||
{
|
||||
private readonly Spy _spy;
|
||||
|
||||
public TestHandler(Spy spy)
|
||||
{
|
||||
_spy = spy;
|
||||
}
|
||||
|
||||
public Task HandleAsync(ActivityExecuting notification, CancellationToken cancellationToken)
|
||||
{
|
||||
_spy.ActivityExecutingWasCalled = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task HandleAsync(ActivityExecuted notification, CancellationToken cancellationToken)
|
||||
{
|
||||
_spy.ActivityExecutedWasCalled = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Notifications;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityNotificationsMiddleware;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly Spy _spy;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
var services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.ConfigureServices(s =>
|
||||
{
|
||||
s.AddSingleton<Spy>();
|
||||
s.AddNotificationHandler<TestHandler, ActivityExecuting>();
|
||||
s.AddNotificationHandler<TestHandler, ActivityExecuted>();
|
||||
})
|
||||
|
||||
.Build();
|
||||
|
||||
_workflowRunner = services.GetRequiredService<IWorkflowRunner>();
|
||||
_spy = services.GetRequiredService<Spy>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Running workflow with activity notifications middleware results in notifications being published")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _workflowRunner.RunAsync<HelloWorldWorkflow>();
|
||||
Assert.True(_spy.ActivityExecutingWasCalled);
|
||||
Assert.True(_spy.ActivityExecutedWasCalled);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityNotificationsMiddleware;
|
||||
|
||||
class HelloWorldWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new WriteLine("Hello World!");
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class LoopingWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var readCurrentValue = new Inline<string>(context => context.GetVariable<string>("CurrentValue")!);
|
||||
|
||||
builder.Root = new ForEach<string>(
|
||||
[
|
||||
"Item 1",
|
||||
"Item 2",
|
||||
"Item 3"
|
||||
])
|
||||
{
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
[
|
||||
readCurrentValue,
|
||||
new WriteLine(context =>
|
||||
{
|
||||
var currentValue = context.GetVariable<string>("CurrentValue");
|
||||
var activityResult = context.GetActivityExecutionContext().GetResult(readCurrentValue);
|
||||
return $"Current value: {currentValue}, Activity result: {activityResult}";
|
||||
})
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class SumActivity : CodeActivity<int>
|
||||
{
|
||||
public SumActivity(Variable<int> a, Variable<int> b)
|
||||
{
|
||||
A = new(a);
|
||||
B = new(b);
|
||||
}
|
||||
|
||||
public Input<int> A { get; set; }
|
||||
public Input<int> B { get; set; }
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var input1 = A.Get(context);
|
||||
var input2 = B.Get(context);
|
||||
var result = input1 + input2;
|
||||
|
||||
// All three work.
|
||||
Result.Set(context, result);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class SumWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var a = new Variable<int>("A", 0);
|
||||
var b = new Variable<int>("B", 0);
|
||||
|
||||
var sumActivity = new SumActivity(a, b);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Variables = { a, b },
|
||||
Activities =
|
||||
{
|
||||
new Inline(context => a.Set(context, 4)),
|
||||
new Inline(context => b.Set(context, 6)),
|
||||
sumActivity,
|
||||
new WriteLine(context => $"The result of {a.Get(context)} and {b.Get(context)} is {sumActivity.GetResult<int>(context)}."),
|
||||
new WriteLine(context => $"The last result is {context.GetLastResult<int>()}."),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ActivityOutputs;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Activity outputs can be accessed from other activities.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<SumWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[]
|
||||
{
|
||||
"The result of 4 and 6 is 10.", "The last result is 10."
|
||||
}, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The last activity output is returned.")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<LoopingWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[]
|
||||
{
|
||||
"Current value: Item 1, Activity result: Item 1",
|
||||
"Current value: Item 2, Activity result: Item 2",
|
||||
"Current value: Item 3, Activity result: Item 3"
|
||||
}, lines);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Options;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Blocking;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowBuilderFactory = _services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Subsequent activity does not get scheduled when previous activity created a bookmark")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BlockingSequentialWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Subsequent activities are scheduled when resuming workflow using bookmark")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<BlockingSequentialWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
var bookmark = result.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Resume");
|
||||
|
||||
// Resume workflow.
|
||||
var runOptions = new RunWorkflowOptions { BookmarkId = bookmark!.Id };
|
||||
await _workflowRunner.RunAsync(workflow, result.WorkflowState, runOptions);
|
||||
|
||||
// Verify expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1", "Line 2", "Line 3" }, lines);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Blocking;
|
||||
|
||||
class BlockingSequentialWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Line 1"),
|
||||
new Event("Resume"){ Id = "Resume"},
|
||||
new WriteLine("Line 2"),
|
||||
new WriteLine("Line 3")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.BlockingAndBreaking.Workflows;
|
||||
using Elsa.Workflows.Options;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.BlockingAndBreaking;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowBuilderFactory = _services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Fork completes after all branches complete.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<WaitAllForkWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
var result1 = await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Resume the first branch.
|
||||
var bookmark = result1.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Branch 1");
|
||||
var runOptions = new RunWorkflowOptions { BookmarkId = bookmark!.Id };
|
||||
var result2 = await _workflowRunner.RunAsync(workflow, result1.WorkflowState, runOptions);
|
||||
|
||||
// Resume the second branch.
|
||||
bookmark = result2.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Branch 2");
|
||||
runOptions = new RunWorkflowOptions { BookmarkId = bookmark!.Id };
|
||||
var result3 = await _workflowRunner.RunAsync(workflow, result2.WorkflowState, runOptions);
|
||||
|
||||
// Verify expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Branch 1", "Branch 2", "Branch 1 - Resumed", "Branch 2 - Resumed", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Fork completes after any branch completes.")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<WaitAnyForkWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
var result1 = await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Resume the first branch.
|
||||
var bookmark = result1.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Branch 1");
|
||||
var runOptions = new RunWorkflowOptions { BookmarkId = bookmark!.Id };
|
||||
var result2 = await _workflowRunner.RunAsync(workflow, result1.WorkflowState, runOptions);
|
||||
|
||||
// Verify expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Branch 1", "Branch 2", "Branch 1 - Resumed", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Break breaks out of While loop.")]
|
||||
public async Task Test3()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<BreakWhileFromForkWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
var result1 = await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Resume the first branch.
|
||||
var bookmark = result1.WorkflowState.Bookmarks.FirstOrDefault(x => x.ActivityId == "Branch 1");
|
||||
var runOptions = new RunWorkflowOptions { BookmarkId = bookmark!.Id };
|
||||
var result2 = await _workflowRunner.RunAsync(workflow, result1.WorkflowState, runOptions);
|
||||
|
||||
// There should be no bookmarks left, since the while loop was broken out of.
|
||||
Assert.Empty(result2.WorkflowState.Bookmarks);
|
||||
|
||||
// Verify expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Branch 1", "Branch 2", "Branch 1 - Resumed", "End" }, lines);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.BlockingAndBreaking.Workflows;
|
||||
|
||||
public class BreakWhileFromForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", 0);
|
||||
|
||||
workflow.WithVariable(currentValue);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new While(() => true)
|
||||
{
|
||||
Body = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new Fork
|
||||
{
|
||||
JoinMode = ForkJoinMode.WaitAll,
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 1"),
|
||||
new Event("Branch 1") { Id = "Branch 1" },
|
||||
new WriteLine("Branch 1 - Resumed"),
|
||||
|
||||
// This should break the while loop, not matter how high up in the tree it is.
|
||||
new Break()
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 2"),
|
||||
new Event("Branch 2") { Id = "Branch 2" },
|
||||
new WriteLine("Branch 2 - Resumed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new WriteLine("End")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.BlockingAndBreaking.Workflows;
|
||||
|
||||
public class WaitAllForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", 0);
|
||||
|
||||
workflow.WithVariable(currentValue);
|
||||
|
||||
workflow.Root =
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new Fork
|
||||
{
|
||||
JoinMode = ForkJoinMode.WaitAll,
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 1"),
|
||||
new Event("Branch 1") { Id = "Branch 1" },
|
||||
new WriteLine("Branch 1 - Resumed"),
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 2"),
|
||||
new Event("Branch 2") { Id = "Branch 2" },
|
||||
new WriteLine("Branch 2 - Resumed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new WriteLine("End")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.BlockingAndBreaking.Workflows;
|
||||
|
||||
public class WaitAnyForkWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var currentValue = new Variable<int?>("CurrentValue", 0);
|
||||
|
||||
workflow.WithVariable(currentValue);
|
||||
|
||||
workflow.Root =
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Start"),
|
||||
new Fork
|
||||
{
|
||||
JoinMode = ForkJoinMode.WaitAny,
|
||||
Branches =
|
||||
{
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 1"),
|
||||
new Event("Branch 1") { Id = "Branch 1" },
|
||||
new WriteLine("Branch 1 - Resumed"),
|
||||
}
|
||||
},
|
||||
new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new WriteLine("Branch 2"),
|
||||
new Event("Branch 2") { Id = "Branch 2" },
|
||||
new WriteLine("Branch 2 - Resumed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new WriteLine("End")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CanExecute.Activities;
|
||||
|
||||
public class CustomActivity : CodeActivity
|
||||
{
|
||||
public CustomActivity(int magicNumber)
|
||||
{
|
||||
MagicNumber = new (magicNumber);
|
||||
}
|
||||
|
||||
public CustomActivity(Func<ExpressionExecutionContext, int> magicNumber)
|
||||
{
|
||||
MagicNumber = new (magicNumber);
|
||||
}
|
||||
|
||||
public Input<int> MagicNumber { get; set; }
|
||||
|
||||
protected override bool CanExecute(ActivityExecutionContext context)
|
||||
{
|
||||
var magicNumber = MagicNumber.Get(context);
|
||||
return magicNumber == 42;
|
||||
}
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var provider = context.GetService<IStandardOutStreamProvider>() ?? new StandardOutStreamProvider(Console.Out);
|
||||
var textWriter = provider.GetTextWriter();
|
||||
textWriter.WriteLine("Welcome to the world of Might and Magic!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.CanExecute.Activities;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.CanExecute.Workflows;
|
||||
using Elsa.Workflows.Options;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CanExecute;
|
||||
|
||||
public class CanExecuteTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
|
||||
public CanExecuteTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.AddActivitiesFrom<CustomActivity>()
|
||||
.Build();
|
||||
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Activities are executed only when they report that they can execute.")]
|
||||
[InlineData(12, "Magic number is 12")]
|
||||
[InlineData(42, "Magic number is 42\nWelcome to the world of Might and Magic!\nDone")]
|
||||
public async Task Test1(int magicNumber, string expectedLines)
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var runOptions = new RunWorkflowOptions
|
||||
{
|
||||
Input = new Dictionary<string, object>
|
||||
{
|
||||
["MagicNumber"] = magicNumber
|
||||
}
|
||||
};
|
||||
await _workflowRunner.RunAsync<MagicWorkflow>(runOptions);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(expectedLines.Split('\n', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries), lines);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.CanExecute.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CanExecute.Workflows;
|
||||
|
||||
public class MagicWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var magicNumberVariable = builder.WithVariable<int>();
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new SetVariable<int>(magicNumberVariable, context => context.GetInput<int>("MagicNumber")),
|
||||
new WriteLine(context => $"Magic number is {magicNumberVariable.Get(context)}"),
|
||||
new CustomActivity(context => magicNumberVariable.Get(context)),
|
||||
new WriteLine("Done")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Composites;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.ConfigureElsa(elsa => elsa.UseJavaScript())
|
||||
.Build();
|
||||
_workflowBuilderFactory = _services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The main workflow can capture the result of the composite activity")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<SumWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Verify expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Sum: 3" }, lines);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.JavaScript.Activities;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Composites;
|
||||
|
||||
/// <summary>
|
||||
/// A composite activity that sums two inputs and returns the result.
|
||||
/// </summary>
|
||||
public class Sum : Composite<int>
|
||||
{
|
||||
private readonly RunJavaScript _runJavaScript;
|
||||
|
||||
public Input<int> A { get; set; } = null!;
|
||||
public Input<int> B { get; set; } = null!;
|
||||
|
||||
public Sum()
|
||||
{
|
||||
_runJavaScript = new()
|
||||
{
|
||||
Script = new("getA() + getB();"),
|
||||
};
|
||||
|
||||
Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
_runJavaScript
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void ConfigureActivities(ActivityExecutionContext context)
|
||||
{
|
||||
// Copy input into variables so that JS activity can access them.
|
||||
var a = A.Get(context);
|
||||
var b = B.Get(context);
|
||||
Variables.Add(new Variable<int>("A", a));
|
||||
Variables.Add(new Variable<int>("B", b));
|
||||
|
||||
// If the call site set a result variable, assign it to the JavaScript activity's result.
|
||||
if (Result != null)
|
||||
_runJavaScript.Result = new(Result.MemoryBlockReference)!;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A workflow that uses the <see cref="Sum"/> composite activity.
|
||||
/// </summary>
|
||||
public class SumWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var sum = workflow.WithVariable<int>("Sum", 0);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new Sum
|
||||
{
|
||||
A = new(1),
|
||||
B = new(2),
|
||||
Result = new(sum)
|
||||
},
|
||||
new WriteLine(context => $"Sum: {sum.Get(context)}")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CompositesAndOutcomes;
|
||||
|
||||
public class ExplicitJoinWaitAnyTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ExplicitJoinWaitAnyTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.WithWorkflowsFromDirectory("Scenarios", "CompositesAndOutcomes", "Workflows")
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Complete activity must not cascade.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Execute.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync("tester");
|
||||
|
||||
// Assert expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
var expectedLinesArray = new[] { "Start", "End" };
|
||||
Assert.Equal(expectedLinesArray, lines);
|
||||
|
||||
// Assert expected workflow status.
|
||||
Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"id": "3457460b3fd74daa8f898564cf96fe48",
|
||||
"definitionId": "99c1c6cf2fec47b3b4916a01425ec989",
|
||||
"name": "Completor",
|
||||
"createdAt": "2023-09-14T13:49:38.017111+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [
|
||||
"Success",
|
||||
"Failure"
|
||||
],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"usableAsActivity": true,
|
||||
"autoUpdateConsumingWorkflows": true,
|
||||
"activityCategory": "Testing"
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Gn-5gEC2-UCmmzWTgvYCmw",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"outcomes": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Success"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "tyDvLNGiYkCbUabhgzcSdw:input-0"
|
||||
}
|
||||
},
|
||||
"id": "tyDvLNGiYkCbUabhgzcSdw",
|
||||
"name": "Complete1",
|
||||
"type": "Elsa.Complete",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -186.5,
|
||||
"y": -263
|
||||
},
|
||||
"size": {
|
||||
"width": 136.8125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"id": "9b6b4d4a6a8741c58ccbe3911eed7821",
|
||||
"definitionId": "bc7f148b2a5b4f55811537a0d762e137",
|
||||
"name": "Consumer",
|
||||
"createdAt": "2023-09-14T13:50:13.31251+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"usableAsActivity": true,
|
||||
"autoUpdateConsumingWorkflows": true,
|
||||
"activityCategory": "Testing"
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "v-ii0Vp0yUCPWReLNUiosg",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"workflowDefinitionId": "99c1c6cf2fec47b3b4916a01425ec989",
|
||||
"workflowDefinitionVersionId": "3457460b3fd74daa8f898564cf96fe48",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "3457460b3fd74daa8f898564cf96fe48",
|
||||
"id": "ctusr1Uv40uFqIws9Ymt9A",
|
||||
"name": "Completor1",
|
||||
"type": "Completor",
|
||||
"version": 2,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 20,
|
||||
"y": -260
|
||||
},
|
||||
"size": {
|
||||
"width": 106.859375,
|
||||
"height": 116.015625
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"id": "74144d614208497380a7bae783b78626",
|
||||
"definitionId": "tester",
|
||||
"name": "Tester",
|
||||
"createdAt": "2023-09-14T13:50:38.720025+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "k0HQeDE_gk-OxcsjGj3tbQ",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "35MeNlWlAUKXd5JFDJtJ3w:input-0"
|
||||
}
|
||||
},
|
||||
"id": "35MeNlWlAUKXd5JFDJtJ3w",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -198,
|
||||
"y": -246.9921875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "End"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "CvdSrKs5DESezhkLjb0YIw:input-0"
|
||||
}
|
||||
},
|
||||
"id": "CvdSrKs5DESezhkLjb0YIw",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 253,
|
||||
"y": -246.9921875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "bc7f148b2a5b4f55811537a0d762e137",
|
||||
"workflowDefinitionVersionId": "9b6b4d4a6a8741c58ccbe3911eed7821",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "9b6b4d4a6a8741c58ccbe3911eed7821",
|
||||
"id": "QfkYnRZDxEO0rtBTIbTXzg",
|
||||
"name": "Consumer1",
|
||||
"type": "Consumer",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 20,
|
||||
"y": -280
|
||||
},
|
||||
"size": {
|
||||
"width": 105.5625,
|
||||
"height": 116.015625
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "35MeNlWlAUKXd5JFDJtJ3w",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "QfkYnRZDxEO0rtBTIbTXzg",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "QfkYnRZDxEO0rtBTIbTXzg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "CvdSrKs5DESezhkLjb0YIw",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CompositesPassingData;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.ConfigureElsa(elsa => elsa.UseJavaScript())
|
||||
.Build();
|
||||
_workflowBuilderFactory = _services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The main workflow can capture the result of the composite activity")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<AddTextMainWorkflow>();
|
||||
|
||||
// Start workflow.
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
|
||||
// Verify expected output.
|
||||
var line = _capturingTextWriter.Lines.ToList().Last();
|
||||
Assert.Equal("hi there obi wan", line);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Management.Activities.SetOutput;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.CompositesPassingData;
|
||||
|
||||
/// <summary>
|
||||
/// A composite activity that adds text to a string
|
||||
/// </summary>
|
||||
public class AddTextSubWorkflow : Composite
|
||||
{
|
||||
public Input<string> A { get; set; } = default!;
|
||||
public Output<string> B { get; set; } = default!;
|
||||
|
||||
public AddTextSubWorkflow()
|
||||
{
|
||||
var setOutput = new SetOutput()
|
||||
{
|
||||
OutputName = new Input<string>("B"),
|
||||
OutputValue = new Input<object?>(context => "hi there " + A.Get(context))
|
||||
};
|
||||
|
||||
Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
setOutput
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A workflow that uses the <see cref="AddTextSubWorkflow"/> composite activity.
|
||||
/// </summary>
|
||||
public class AddTextMainWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var outVariable = new Variable<string>("out", "test");
|
||||
|
||||
var subWorkflow = new AddTextSubWorkflow()
|
||||
{
|
||||
A = new("obi wan"),
|
||||
B = new (outVariable)
|
||||
};
|
||||
|
||||
workflow.Variables.Add(outVariable);
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
subWorkflow,
|
||||
new WriteLine(context => outVariable.Get(context))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.DependencyWorkflows;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.WithWorkflowsFromDirectory("Scenarios", "DependencyWorkflows", "Workflows")
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Workflows provided from JSON files that depend on other workflows are executed correctly.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Run the "matter" workflow.
|
||||
await _services.RunWorkflowUntilEndAsync("matter-workflow");
|
||||
|
||||
// Assert.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
|
||||
Assert.Equal(new[] { "Atom", "Atom", "Atom", "Atom", "Atom", "Atom", "Atom", "Atom", "Atom" }, lines);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"id": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"definitionId": "40a40a0cdf5448acbc899391b2c50458",
|
||||
"name": "AtomActivity",
|
||||
"createdAt": "2023-06-01T14:00:29.374132+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"usableAsActivity": true,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": true
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"start": "Atom",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Atom"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "65ee0198-2051-491d-9035-6d05e73fbd08"
|
||||
}
|
||||
},
|
||||
"id": "Atom",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2394,
|
||||
"y": 2472
|
||||
}
|
||||
},
|
||||
"displayText": "Atom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"id": "matter-workflow-v1",
|
||||
"definitionId": "matter-workflow",
|
||||
"name": "Matter Workflow",
|
||||
"createdAt": "2023-06-01T14:06:25.895316+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"start": "MoleculeActivity2",
|
||||
"activities": [
|
||||
{
|
||||
"workflowDefinitionId": "86e355d944764f15872f8cfdcc1e9cec",
|
||||
"workflowDefinitionVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"id": "MoleculeActivity1",
|
||||
"type": "MoleculeActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2347,
|
||||
"y": 2407
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "86e355d944764f15872f8cfdcc1e9cec",
|
||||
"workflowDefinitionVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"id": "MoleculeActivity3",
|
||||
"type": "MoleculeActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2560,
|
||||
"y": 2560
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "86e355d944764f15872f8cfdcc1e9cec",
|
||||
"workflowDefinitionVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "fec9de7279a440f693a5901507140a77",
|
||||
"id": "MoleculeActivity2",
|
||||
"type": "MoleculeActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2140,
|
||||
"y": 2560
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "MoleculeActivity2",
|
||||
"target": "MoleculeActivity1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "MoleculeActivity1",
|
||||
"target": "MoleculeActivity3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"id": "fec9de7279a440f693a5901507140a77",
|
||||
"definitionId": "86e355d944764f15872f8cfdcc1e9cec",
|
||||
"name": "MoleculeActivity",
|
||||
"createdAt": "2023-06-01T14:05:32.409643+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"usableAsActivity": true,
|
||||
"autoUpdateConsumingWorkflows": true
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"start": "AtomActivity1",
|
||||
"activities": [
|
||||
{
|
||||
"workflowDefinitionId": "40a40a0cdf5448acbc899391b2c50458",
|
||||
"workflowDefinitionVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"id": "AtomActivity1",
|
||||
"type": "AtomActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2228,
|
||||
"y": 2418
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "40a40a0cdf5448acbc899391b2c50458",
|
||||
"workflowDefinitionVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"id": "AtomActivity2",
|
||||
"type": "AtomActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2458,
|
||||
"y": 2487
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "40a40a0cdf5448acbc899391b2c50458",
|
||||
"workflowDefinitionVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "82b53ccf2a4e4ced966b85fb3cc13eed",
|
||||
"id": "AtomActivity3",
|
||||
"type": "AtomActivity",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"CanStartWorkflow": false,
|
||||
"RunAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2660,
|
||||
"y": 2560
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "AtomActivity1",
|
||||
"target": "AtomActivity2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "AtomActivity2",
|
||||
"target": "AtomActivity3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
using Elsa.Common.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Management;
|
||||
using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
using Elsa.Workflows.Management.Entities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.DependencyWorkflowsPublishing;
|
||||
|
||||
/// <summary>
|
||||
/// Contains tests for the "DependencyWorkflowsPublishing" scenario.
|
||||
/// </summary>
|
||||
public class Tests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IWorkflowDefinitionPublisher _workflowDefinitionPublisher;
|
||||
private readonly IActivitySerializer _activitySerializer;
|
||||
private readonly IActivityVisitor _activityVisitor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Tests"/> class.
|
||||
/// </summary>
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.WithWorkflowsFromDirectory("Scenarios", "DependencyWorkflowsPublishing", "Workflows")
|
||||
.Build();
|
||||
|
||||
_workflowDefinitionPublisher = _services.GetRequiredService<IWorkflowDefinitionPublisher>();
|
||||
_activitySerializer = _services.GetRequiredService<IActivitySerializer>();
|
||||
_activityVisitor = _services.GetRequiredService<IActivityVisitor>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a dependency workflow is published, all consuming workflows are updated to point to the new version of the dependency.
|
||||
/// </summary>
|
||||
[Fact(DisplayName = "When a dependency workflow is published, all consuming workflows are updated to point to the new version of the dependency.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var childDefinitionV1 = await _services.GetWorkflowDefinitionAsync("child", VersionOptions.Latest);
|
||||
var parentDefinition = await _services.GetWorkflowDefinitionAsync("parent", VersionOptions.Latest);
|
||||
var childActivityV1 = await GetChildActivityAsync(parentDefinition);
|
||||
|
||||
// Assert initial state.
|
||||
Assert.Equal(1, childDefinitionV1.Version);
|
||||
Assert.False(parentDefinition.IsPublished);
|
||||
Assert.Equal(1, childActivityV1.Version);
|
||||
|
||||
// Create a new draft for the child workflow and publish it.
|
||||
var childDefinitionV2 = (await _workflowDefinitionPublisher.GetDraftAsync(childDefinitionV1.DefinitionId, VersionOptions.Published))!;
|
||||
await _workflowDefinitionPublisher.PublishAsync(childDefinitionV2);
|
||||
|
||||
// Assert that the parent workflow now points to the new version of the child workflow.
|
||||
parentDefinition = await _services.GetWorkflowDefinitionAsync("parent", VersionOptions.Latest);
|
||||
var childActivityV2 = await GetChildActivityAsync(parentDefinition);
|
||||
Assert.Equal(2, childActivityV2.Version);
|
||||
}
|
||||
|
||||
private async Task<WorkflowDefinitionActivity> GetChildActivityAsync(WorkflowDefinition parent)
|
||||
{
|
||||
var root = _activitySerializer.Deserialize(parent.StringData!);
|
||||
var graph = await _activityVisitor.VisitAsync(root);
|
||||
var flattenedList = graph.Flatten().ToList();
|
||||
return (WorkflowDefinitionActivity)flattenedList.Single(x => x.Activity is WorkflowDefinitionActivity { WorkflowDefinitionId: "child" }).Activity;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"id": "child-v1",
|
||||
"definitionId": "child",
|
||||
"name": "Child",
|
||||
"createdAt": "2024-02-07T14:57:47.115341+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {
|
||||
"Elsa:WorkflowContextProviderTypes": []
|
||||
},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"usableAsActivity": true,
|
||||
"autoUpdateConsumingWorkflows": true
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "c22918340b6cb7cd",
|
||||
"nodeId": "Workflow1:c22918340b6cb7cd",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"id": "ffd312ccf7a2af4f",
|
||||
"definitionId": "parent",
|
||||
"name": "Parent",
|
||||
"createdAt": "2024-02-07T14:58:12.954939+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {
|
||||
"Elsa:WorkflowContextProviderTypes": []
|
||||
},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "3535b9598a0962f0",
|
||||
"nodeId": "Workflow1:3535b9598a0962f0",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"workflowDefinitionId": "child",
|
||||
"workflowDefinitionVersionId": "child-v1",
|
||||
"latestAvailablePublishedVersion": 1,
|
||||
"latestAvailablePublishedVersionId": "child-v1",
|
||||
"id": "35525d3b78b8e518",
|
||||
"nodeId": "Workflow1:3535b9598a0962f0:35525d3b78b8e518",
|
||||
"name": "Child1",
|
||||
"type": "Child",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -95.17782592773438,
|
||||
"y": -137.3333282470703
|
||||
},
|
||||
"size": {
|
||||
"width": 67.78125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ExplicitJoins;
|
||||
|
||||
public class ExplicitJoinWaitAnyTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ExplicitJoinWaitAnyTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Workflows with explicit joins complete the workflow.")]
|
||||
[InlineData("join-any-1.json", "Start; End")]
|
||||
[InlineData("join-all-1.json", "Start; Line 1; Line 2; End")]
|
||||
[InlineData("join-all-2.json", "Start; Line 1; Line 2; End")]
|
||||
public async Task Test1(string filename, string expectedLines)
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var fileName = $"Scenarios/ExplicitJoins/Workflows/{filename}";
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync(fileName);
|
||||
|
||||
// Execute.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Assert expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
var expectedLinesArray = expectedLines.Split(";", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
Assert.Equal(expectedLinesArray, lines);
|
||||
|
||||
// Assert expected workflow status.
|
||||
Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
|
||||
}
|
||||
}
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
{
|
||||
"id": "9948e541b0e540c384c6eb9fdcf1d544",
|
||||
"definitionId": "296428cc22bd4f309e858f4b461dbb3d",
|
||||
"name": "Join 1",
|
||||
"createdAt": "2023-09-12T18:12:54.370149+00:00",
|
||||
"version": 2,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "sL581qWiIEOpRncv5Ez33A",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAll"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "aA4pfJOzyEqmLOY3U3vCoQ:input-0"
|
||||
}
|
||||
},
|
||||
"id": "aA4pfJOzyEqmLOY3U3vCoQ",
|
||||
"name": "FlowJoin1",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 198,
|
||||
"y": -266
|
||||
},
|
||||
"size": {
|
||||
"width": 136.859375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "FRXh0PlHekejZiWANAplUg:input-0"
|
||||
}
|
||||
},
|
||||
"id": "FRXh0PlHekejZiWANAplUg",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -287,
|
||||
"y": -266
|
||||
},
|
||||
"size": {
|
||||
"width": 102.21875,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Line 1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "GaVrCWqBDkS6YrvydxKvFA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "GaVrCWqBDkS6YrvydxKvFA",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -40,
|
||||
"y": -316
|
||||
},
|
||||
"size": {
|
||||
"width": 110.65625,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Line 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Line 2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "9Z7bt98j00uRMt9TS2FD0g:input-0"
|
||||
}
|
||||
},
|
||||
"id": "9Z7bt98j00uRMt9TS2FD0g",
|
||||
"name": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -40,
|
||||
"y": -207
|
||||
},
|
||||
"size": {
|
||||
"width": 110.65625,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Line 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "End"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "MplDrS_bUE-8td-XBUvWmA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "MplDrS_bUE-8td-XBUvWmA",
|
||||
"name": "WriteLine4",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 430,
|
||||
"y": -266
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "FRXh0PlHekejZiWANAplUg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "GaVrCWqBDkS6YrvydxKvFA",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "FRXh0PlHekejZiWANAplUg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "9Z7bt98j00uRMt9TS2FD0g",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "9Z7bt98j00uRMt9TS2FD0g",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "aA4pfJOzyEqmLOY3U3vCoQ",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "GaVrCWqBDkS6YrvydxKvFA",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "aA4pfJOzyEqmLOY3U3vCoQ",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "aA4pfJOzyEqmLOY3U3vCoQ",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "MplDrS_bUE-8td-XBUvWmA",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
{
|
||||
"id": "14984c048db34cceaf5e15ece80f9703",
|
||||
"definitionId": "64f8f2c852f04dc28f60707034d7a906",
|
||||
"name": "Join 2",
|
||||
"createdAt": "2023-09-12T18:12:43.392272+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "B2jpPDriPEe-zSOhVuAGeQ",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "2yPLgUudQEGPaschdLdkGg:input-0"
|
||||
}
|
||||
},
|
||||
"id": "2yPLgUudQEGPaschdLdkGg",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -358.5,
|
||||
"y": -229
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Start"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "zaAIlUtQDEaPqeITeRJ4_w",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:46",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Line 2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "g3jVTdvU3EK7V5JqRqfqjQ:input-0"
|
||||
}
|
||||
},
|
||||
"id": "g3jVTdvU3EK7V5JqRqfqjQ",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -279.5,
|
||||
"y": -294
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Line 2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
},
|
||||
"id": "eHAEEQ-Iu0GwM3mRxZin0Q",
|
||||
"name": "FlowNode1",
|
||||
"type": "Elsa.FlowNode",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -120,
|
||||
"y": -179
|
||||
},
|
||||
"size": {
|
||||
"width": 211.15625,
|
||||
"height": 120
|
||||
}
|
||||
},
|
||||
"displayText": "Line 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Line 1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "7RQ2sbVHo0SxsyK0dvTKEA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "7RQ2sbVHo0SxsyK0dvTKEA",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -120,
|
||||
"y": -279
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "Line 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAll"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "dVUuwMm5XUiYpiYoGo5JKA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "dVUuwMm5XUiYpiYoGo5JKA",
|
||||
"name": "FlowJoin1",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 180.5,
|
||||
"y": -229
|
||||
},
|
||||
"size": {
|
||||
"width": 136.859375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "End"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "NpZ_yT_irUuE9ASEfYLxbw:input-0"
|
||||
}
|
||||
},
|
||||
"id": "NpZ_yT_irUuE9ASEfYLxbw",
|
||||
"name": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 400,
|
||||
"y": -229
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
},
|
||||
"displayText": "End"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "2yPLgUudQEGPaschdLdkGg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "7RQ2sbVHo0SxsyK0dvTKEA",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "2yPLgUudQEGPaschdLdkGg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "eHAEEQ-Iu0GwM3mRxZin0Q",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "7RQ2sbVHo0SxsyK0dvTKEA",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "dVUuwMm5XUiYpiYoGo5JKA",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "eHAEEQ-Iu0GwM3mRxZin0Q",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "dVUuwMm5XUiYpiYoGo5JKA",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "dVUuwMm5XUiYpiYoGo5JKA",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "NpZ_yT_irUuE9ASEfYLxbw",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"id": "2484d1b14e2348f7a916ecef042536e6",
|
||||
"definitionId": "7204b870946b4968aa786a2c91431242",
|
||||
"name": "Flow Join Any",
|
||||
"createdAt": "2023-09-08T19:07:08.435872+00:00",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "F44h770hvkSaOWI_jjbM_A",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAny"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "ImdIbHXtHkiLlrExFlW51A:input-0"
|
||||
}
|
||||
},
|
||||
"id": "ImdIbHXtHkiLlrExFlW51A",
|
||||
"name": "FlowJoin1",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -180,
|
||||
"y": -320
|
||||
},
|
||||
"size": {
|
||||
"width": 136.859375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAny"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "cxnS1whoCESvwwPyBnno_Q:input-0"
|
||||
}
|
||||
},
|
||||
"id": "cxnS1whoCESvwwPyBnno_Q",
|
||||
"name": "FlowJoin2",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -180,
|
||||
"y": -80
|
||||
},
|
||||
"size": {
|
||||
"width": 136.859375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAny"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "H0apwXYdoESn2TJ5T_3xAg:input-0"
|
||||
}
|
||||
},
|
||||
"id": "H0apwXYdoESn2TJ5T_3xAg",
|
||||
"name": "FlowJoin3",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 40,
|
||||
"y": -194
|
||||
},
|
||||
"size": {
|
||||
"width": 136.859375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Kn9d-EVn2EiaYJqHd8VcmQ:input-0"
|
||||
}
|
||||
},
|
||||
"id": "Kn9d-EVn2EiaYJqHd8VcmQ",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -393.5,
|
||||
"y": -194
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "End"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "haHoM3A5EU6aYu_8dCYaYg:input-0"
|
||||
}
|
||||
},
|
||||
"id": "haHoM3A5EU6aYu_8dCYaYg",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 310.5,
|
||||
"y": -194
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "Kn9d-EVn2EiaYJqHd8VcmQ",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "ImdIbHXtHkiLlrExFlW51A",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "Kn9d-EVn2EiaYJqHd8VcmQ",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "cxnS1whoCESvwwPyBnno_Q",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "ImdIbHXtHkiLlrExFlW51A",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "H0apwXYdoESn2TJ5T_3xAg",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "cxnS1whoCESvwwPyBnno_Q",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "H0apwXYdoESn2TJ5T_3xAg",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "H0apwXYdoESn2TJ5T_3xAg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "haHoM3A5EU6aYu_8dCYaYg",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.FlowchartCompletion;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the flowchart completion feature using various workflow setups.
|
||||
/// </summary>
|
||||
public class Tests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Workflows should complete successfully.")]
|
||||
[InlineData("workflow1.json")]
|
||||
[InlineData("workflow2.json")]
|
||||
[InlineData("workflow3.json")]
|
||||
[InlineData("workflow4.json")]
|
||||
[InlineData("workflow5.json")]
|
||||
[InlineData("workflow6.json")]
|
||||
public async Task Test1(string workflowFileName)
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var fileName = $"Scenarios/FlowchartCompletion/Workflows/{workflowFileName}";
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync(fileName);
|
||||
|
||||
// Execute.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Assert that the workflow has completed.
|
||||
Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"id": "f7f7563b32de444797363df61e5109d3",
|
||||
"definitionId": "d91eff09eaad43efb9d58332f1f22c82",
|
||||
"name": "Flows",
|
||||
"createdAt": "2023-04-18T13:32:26.294066+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "WriteLine1",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2020,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine2:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2260,
|
||||
"y": 2260
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine3"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine3:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2260,
|
||||
"y": 2380
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine3"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
{
|
||||
"id": "dc6576d848aa4f46812356467575705f",
|
||||
"definitionId": "991a4f39f7074a9988465230cfdb8d81",
|
||||
"name": "Braided flow",
|
||||
"createdAt": "2023-04-18T13:45:03.454228+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "WriteLine1",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine7"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine7:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine7",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2340,
|
||||
"y": 2220
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine9"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine9:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine9",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2560,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1600,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine2:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2220
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine3"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine3:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine4"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine4:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine4",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2160
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine5"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine5:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine5",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine6"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine6:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine6",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2480
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine8"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine8:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine8",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2340,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "WriteLine5",
|
||||
"target": "WriteLine7",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine8",
|
||||
"target": "WriteLine9",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine7",
|
||||
"target": "WriteLine9",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine4",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "WriteLine5",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine4",
|
||||
"target": "WriteLine7",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine5",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine6",
|
||||
"target": "WriteLine8",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "WriteLine6",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine5",
|
||||
"target": "WriteLine8",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+469
@@ -0,0 +1,469 @@
|
||||
{
|
||||
"id": "01146119d31041c195148662710d95c7",
|
||||
"definitionId": "abb565fd716f4eb7be0510ab8ff36329",
|
||||
"name": "Braided delayed flow",
|
||||
"createdAt": "2023-04-18T14:06:58.250625+00:00",
|
||||
"version": 4,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "WriteLine1",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1600,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine2:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2220
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine3"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine3:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine4"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine4:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine4",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2160
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine5"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine5:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine5",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine6"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine6:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine6",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2480
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine8"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine8:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine8",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2460,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine7"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine7:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine7",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2460,
|
||||
"y": 2240
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine9"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine9:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine9",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2680,
|
||||
"y": 2300
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timeSpan": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-1"
|
||||
}
|
||||
},
|
||||
"strategy": {
|
||||
"typeName": "Elsa.Scheduling.Models.DelayBlockingStrategy, Elsa.Scheduling",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "NonBlocking"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-2"
|
||||
}
|
||||
},
|
||||
"autoBlockingThreshold": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-3"
|
||||
}
|
||||
},
|
||||
"id": "Delay1",
|
||||
"type": "Elsa.Delay",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2260,
|
||||
"y": 2240
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"timeSpan": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:10"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-1"
|
||||
}
|
||||
},
|
||||
"strategy": {
|
||||
"typeName": "Elsa.Scheduling.Models.DelayBlockingStrategy, Elsa.Scheduling",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "NonBlocking"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-2"
|
||||
}
|
||||
},
|
||||
"autoBlockingThreshold": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-3"
|
||||
}
|
||||
},
|
||||
"id": "Delay2",
|
||||
"type": "Elsa.Delay",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2280,
|
||||
"y": 2440
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine4",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "WriteLine5",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine5",
|
||||
"target": "WriteLine7",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine5",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine6",
|
||||
"target": "Delay2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "WriteLine6",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine8",
|
||||
"target": "WriteLine9",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "Delay2",
|
||||
"target": "WriteLine8",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine5",
|
||||
"target": "WriteLine8",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "Delay1",
|
||||
"target": "WriteLine7",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine7",
|
||||
"target": "WriteLine9",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine4",
|
||||
"target": "Delay1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+415
@@ -0,0 +1,415 @@
|
||||
{
|
||||
"id": "44200e995aaf429d9975bd7177e271d0",
|
||||
"definitionId": "7d0420cacaad4ae09c589a0355bbef44",
|
||||
"name": "Braided conditional delayed flow",
|
||||
"createdAt": "2023-04-18T14:37:02.902303+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "WriteLine1",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1600,
|
||||
"y": 2320
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine2"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine2:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2220
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine3"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine3:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 1820,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine4"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine4:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine4",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2160
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine6"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine6:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine6",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2480
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"typeName": "Boolean",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "True"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "FlowDecision1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "FlowDecision1",
|
||||
"type": "Elsa.FlowDecision",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2320
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"timeSpan": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-1"
|
||||
}
|
||||
},
|
||||
"strategy": {
|
||||
"typeName": "Elsa.Scheduling.Models.DelayBlockingStrategy, Elsa.Scheduling",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "NonBlocking"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-2"
|
||||
}
|
||||
},
|
||||
"autoBlockingThreshold": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay1:input-3"
|
||||
}
|
||||
},
|
||||
"id": "Delay1",
|
||||
"type": "Elsa.Delay",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2320,
|
||||
"y": 2220
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine7"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine7:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine7",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2520,
|
||||
"y": 2220
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timeSpan": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:10"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-1"
|
||||
}
|
||||
},
|
||||
"strategy": {
|
||||
"typeName": "Elsa.Scheduling.Models.DelayBlockingStrategy, Elsa.Scheduling",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "NonBlocking"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-2"
|
||||
}
|
||||
},
|
||||
"autoBlockingThreshold": {
|
||||
"typeName": "TimeSpan",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "00:00:05"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "Delay2:input-3"
|
||||
}
|
||||
},
|
||||
"id": "Delay2",
|
||||
"type": "Elsa.Delay",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2320,
|
||||
"y": 2420
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WriteLine8"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine8:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine8",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2520,
|
||||
"y": 2420
|
||||
}
|
||||
},
|
||||
"displayText": "WriteLine8"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine2",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine4",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "FlowDecision1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "WriteLine3",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine3",
|
||||
"target": "WriteLine6",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "FlowDecision1",
|
||||
"target": "Delay1",
|
||||
"sourcePort": "True",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "FlowDecision1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "Delay1",
|
||||
"target": "WriteLine7",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "Delay2",
|
||||
"target": "WriteLine8",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "FlowDecision1",
|
||||
"target": "Delay2",
|
||||
"sourcePort": "False",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"id": "3365d4c0198e459f834b799cbfe91154",
|
||||
"definitionId": "4aa1e566da264ab6b5495bedb734096d",
|
||||
"name": "Forking, Containment and Blocking",
|
||||
"description": "A combination of a fork, a containment and a blocking activity.",
|
||||
"version": 1,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "uEnFWEdaWkadgIMHT2umLA",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"id": "MLDV_altcUO5MwP7p5xJWw",
|
||||
"name": "Start1",
|
||||
"type": "Elsa.Start",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -480,
|
||||
"y": -566.046875
|
||||
},
|
||||
"size": {
|
||||
"width": 102.21875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Intermediary"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "EIh3Q0Um1U-QSCh1b3GBjQ:input-0"
|
||||
}
|
||||
},
|
||||
"id": "EIh3Q0Um1U-QSCh1b3GBjQ",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -228.5,
|
||||
"y": -476.046875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": null,
|
||||
"id": "0Z7Velr5CEW_r7YYoeEjBQ",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 69.34375,
|
||||
"y": -476.046875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "NJ5fh2bUWU-TxWeXsbNaSg",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"eventName": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Event4"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "8KVHRw-WpUizyxOq0C6Nvg:input-0"
|
||||
}
|
||||
},
|
||||
"result": null,
|
||||
"id": "8KVHRw-WpUizyxOq0C6Nvg",
|
||||
"name": "Event1",
|
||||
"type": "Elsa.Event",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -840,
|
||||
"y": -500
|
||||
},
|
||||
"size": {
|
||||
"width": 106.828125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
},
|
||||
"id": "HG4wfBhvlEW_149HwNyzHw",
|
||||
"name": "FlowNode1",
|
||||
"type": "Elsa.FlowNode",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -228.5,
|
||||
"y": -704.109375
|
||||
},
|
||||
"size": {
|
||||
"width": 211.15625,
|
||||
"height": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "MLDV_altcUO5MwP7p5xJWw",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "HG4wfBhvlEW_149HwNyzHw",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "MLDV_altcUO5MwP7p5xJWw",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "EIh3Q0Um1U-QSCh1b3GBjQ",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "EIh3Q0Um1U-QSCh1b3GBjQ",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "0Z7Velr5CEW_r7YYoeEjBQ",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"id": "e5190066597846cc926f8ae644d706f4",
|
||||
"definitionId": "b07725956291433abee7ff229b415194",
|
||||
"name": "Parallel For Each",
|
||||
"createdAt": "2023-09-10T16:32:58.422674+00:00",
|
||||
"version": 3,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "oplDmRa_zEqH8PCdTcFh8A",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "NTW8X70bTEaBtlYyU44PcA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "NTW8X70bTEaBtlYyU44PcA",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -352,
|
||||
"y": -286.9921875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "End"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "6Bf011ZOvUWOfQ1rKJEDFA:input-0"
|
||||
}
|
||||
},
|
||||
"id": "6Bf011ZOvUWOfQ1rKJEDFA",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 169,
|
||||
"y": -286.9921875
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"typeName": "Object[]",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "[\u0022Apple\u0022, \u0022Banana\u0022, \u0022Cherry\u0022]"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "By4rVs_-2kSDENFO-bniRg:input-0"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "ylZLDh7FQ0WmnbdnRJHutg",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"NotFoundConnectionsKey": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "\u0060Current fruit: ${getCurrentValue()}\u0060"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "fht2JVY0G0KURaRYB9jqlw:input-0"
|
||||
}
|
||||
},
|
||||
"id": "fht2JVY0G0KURaRYB9jqlw",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -459.5,
|
||||
"y": -374
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
},
|
||||
"id": "By4rVs_-2kSDENFO-bniRg",
|
||||
"name": "ParallelForEach1",
|
||||
"type": "Elsa.ParallelForEach",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -100,
|
||||
"y": -320
|
||||
},
|
||||
"size": {
|
||||
"width": 149.203125,
|
||||
"height": 116.015625
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "NTW8X70bTEaBtlYyU44PcA",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "By4rVs_-2kSDENFO-bniRg",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "By4rVs_-2kSDENFO-bniRg",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "6Bf011ZOvUWOfQ1rKJEDFA",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.FlowchartNextActivity.Activities;
|
||||
|
||||
public class CustomActivity : CodeActivity
|
||||
{
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
|
||||
{
|
||||
await context.CompleteActivityAsync();
|
||||
}
|
||||
}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Models;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.FlowchartNextActivity.Workflows;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.FlowchartNextActivity;
|
||||
|
||||
public class FlowchartNextActivityTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
|
||||
public FlowchartNextActivityTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.AddActivitiesFrom<FlowchartNextActivityTests>()
|
||||
.Build();
|
||||
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Flowchart only schedules next activity connected to outcome of previous activity.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<FlowchartWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Line 1" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Flowchart with backward connections and a dangling activity")]
|
||||
public async Task BackwardConnectionTest()
|
||||
{
|
||||
var workflow = new TestWorkflow(workflowBuilder =>
|
||||
{
|
||||
var loopVariable = new Variable<int>("LoopCount", 0);
|
||||
|
||||
var start = new Start();
|
||||
var dangling = new WriteLine("dangling");
|
||||
var writeLineDecision = new FlowSwitch()
|
||||
{
|
||||
Cases = {
|
||||
new FlowSwitchCase("LessThanThree", new Expression("JavaScript", "getVariable('LoopCount') < 3")),
|
||||
new FlowSwitchCase("LessThanOne", new Expression("JavaScript", "getVariable('LoopCount') < 1")),
|
||||
},
|
||||
Mode = new(SwitchMode.MatchAny)
|
||||
};
|
||||
var a = new WriteLine("A");
|
||||
var b = new WriteLine("B");
|
||||
var c = new WriteLine("C");
|
||||
var incrementLoop = new SetVariable()
|
||||
{
|
||||
Variable = loopVariable,
|
||||
Value = new Models.Input<object?>(new Expression("JavaScript", "getVariable('LoopCount') + 1"))
|
||||
};
|
||||
var loopbackDecision = new FlowSwitch()
|
||||
{
|
||||
Cases = {
|
||||
new FlowSwitchCase("EqualOne", new Expression("JavaScript", "getVariable('LoopCount') == 1")),
|
||||
new FlowSwitchCase("LessThanFour", new Expression("JavaScript", "getVariable('LoopCount') < 4")),
|
||||
},
|
||||
Mode = new(SwitchMode.MatchFirst)
|
||||
};
|
||||
var d = new WriteLine("D");
|
||||
var e = new WriteLine("E");
|
||||
var f = new WriteLine("F");
|
||||
var end = new End();
|
||||
|
||||
|
||||
workflowBuilder.Root = new Flowchart
|
||||
{
|
||||
Variables =
|
||||
{
|
||||
loopVariable
|
||||
},
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
dangling,
|
||||
writeLineDecision,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
incrementLoop,
|
||||
loopbackDecision,
|
||||
d,
|
||||
e,
|
||||
f,
|
||||
end
|
||||
},
|
||||
Connections =
|
||||
{
|
||||
new(start, writeLineDecision),
|
||||
new(dangling, writeLineDecision),
|
||||
new(new Endpoint(writeLineDecision, "LessThanThree"), new Endpoint(a)),
|
||||
new(new Endpoint(writeLineDecision, "LessThanThree"), new Endpoint(b)),
|
||||
new(new Endpoint(writeLineDecision, "LessThanOne"), new Endpoint(c)),
|
||||
new(new Endpoint(writeLineDecision, "Default"), new Endpoint(incrementLoop)),
|
||||
new(a, incrementLoop),
|
||||
new(b, incrementLoop),
|
||||
new(c, incrementLoop),
|
||||
new(incrementLoop, loopbackDecision),
|
||||
new(new Endpoint(loopbackDecision, "EqualOne"), new Endpoint(d)),
|
||||
new(d, incrementLoop),
|
||||
new(new Endpoint(loopbackDecision, "LessThanFour"), new Endpoint(e)),
|
||||
new(e, writeLineDecision),
|
||||
new(new Endpoint(loopbackDecision, "Default"), new Endpoint(f)),
|
||||
new(f, end),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(WorkflowSubStatus.Finished, result.WorkflowState.SubStatus);
|
||||
Assert.Equal(new[] { "A", "B", "C", "D", "E", "A", "B", "E", "F" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Flowchart with an invalid backward connection")]
|
||||
public async Task InvalidBackwardConnectionTest()
|
||||
{
|
||||
var workflow = new TestWorkflow(workflowBuilder =>
|
||||
{
|
||||
var start = new Start() { Id = "Start" };
|
||||
var a = new WriteLine("A") { Id = "WriteLineA" };
|
||||
var b = new WriteLine("B") { Id = "WriteLineB" };
|
||||
var c = new WriteLine("C") { Id = "WriteLineC" };
|
||||
var d = new WriteLine("D") { Id = "WriteLineD" };
|
||||
var e = new WriteLine("E") { Id = "WriteLineE" };
|
||||
|
||||
workflowBuilder.Root = new Flowchart
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
},
|
||||
Connections =
|
||||
{
|
||||
new(start, a),
|
||||
new(a, b),
|
||||
new(b, c),
|
||||
new(b, d),
|
||||
new(c, e),
|
||||
new(d, e),
|
||||
new(e, c),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(WorkflowSubStatus.Faulted, result.WorkflowState.SubStatus);
|
||||
Assert.Equal(1, result.WorkflowState.Incidents.Count());
|
||||
Assert.Equal("Invalid backward connection: Every path from the source ('WriteLineE') must go through the target ('WriteLineC') when tracing back to the start.", result.WorkflowState.Incidents.First().Message);
|
||||
Assert.Equal(new[] { "A", "B", "C", "D", "E" }, lines);
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Flowchart with a Join activity executed multiple times")]
|
||||
[InlineData(FlowJoinMode.WaitAll)]
|
||||
[InlineData(FlowJoinMode.WaitAny)]
|
||||
public async Task WaitAnyLoopTest(FlowJoinMode joinMode)
|
||||
{
|
||||
var workflow = new TestWorkflow(workflowBuilder =>
|
||||
{
|
||||
var loopVariable = new Variable<int>("LoopCount", 0);
|
||||
|
||||
var start = new Start();
|
||||
var a = new WriteLine("A");
|
||||
var b = new WriteLine("B");
|
||||
var c = new WriteLine("C");
|
||||
var d = new WriteLine("D");
|
||||
var join = new FlowJoin()
|
||||
{
|
||||
Mode = new(joinMode)
|
||||
};
|
||||
var incrementLoop = new SetVariable()
|
||||
{
|
||||
Variable = loopVariable,
|
||||
Value = new Models.Input<object?>(new Expression("JavaScript", "getVariable('LoopCount') + 1"))
|
||||
};
|
||||
var loopbackDecision = new FlowSwitch()
|
||||
{
|
||||
Cases = {
|
||||
new FlowSwitchCase("LessThanThree", new Expression("JavaScript", "getVariable('LoopCount') < 3")),
|
||||
},
|
||||
Mode = new(SwitchMode.MatchFirst)
|
||||
};
|
||||
var end = new End();
|
||||
|
||||
|
||||
workflowBuilder.Root = new Flowchart
|
||||
{
|
||||
Variables =
|
||||
{
|
||||
loopVariable
|
||||
},
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
join,
|
||||
incrementLoop,
|
||||
loopbackDecision,
|
||||
end
|
||||
},
|
||||
Connections =
|
||||
{
|
||||
new(start, a),
|
||||
new(a, b),
|
||||
new(a, c),
|
||||
new(a, d),
|
||||
new(b, join),
|
||||
new(c, join),
|
||||
new(d, join),
|
||||
new(join, incrementLoop),
|
||||
new(incrementLoop,loopbackDecision),
|
||||
new(new Endpoint(loopbackDecision, "LessThanThree"), new Endpoint(a)),
|
||||
new(new Endpoint(loopbackDecision, "Default"), new Endpoint(end)),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(WorkflowSubStatus.Finished, result.WorkflowState.SubStatus);
|
||||
Assert.Equal(new[] { "A", "B", "C", "D", "A", "B", "C", "D", "A", "B", "C", "D"}, lines);
|
||||
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Flowchart with a Join activity executed multiple times, bug 6479")]
|
||||
[InlineData(FlowJoinMode.WaitAll)]
|
||||
[InlineData(FlowJoinMode.WaitAny)]
|
||||
public async Task WaitLoopBug6479Test(FlowJoinMode joinMode)
|
||||
{
|
||||
var workflow = new TestWorkflow(workflowBuilder =>
|
||||
{
|
||||
var loopVariable = new Variable<int>("LoopCount", 0);
|
||||
|
||||
var start = new Start();
|
||||
var loopbackSwitch = new FlowSwitch()
|
||||
{
|
||||
Cases = {
|
||||
new FlowSwitchCase("DoLoopback", new Expression("JavaScript", "getVariable('LoopCount') < 3")),
|
||||
},
|
||||
Mode = new(SwitchMode.MatchFirst)
|
||||
};
|
||||
var a = new WriteLine("A");
|
||||
var incrementLoop = new SetVariable()
|
||||
{
|
||||
Variable = loopVariable,
|
||||
Value = new Models.Input<object?>(new Expression("JavaScript", "getVariable('LoopCount') + 1"))
|
||||
};
|
||||
var join = new FlowJoin()
|
||||
{
|
||||
Mode = new(joinMode)
|
||||
};
|
||||
var b = new WriteLine("B");
|
||||
var end = new End();
|
||||
|
||||
|
||||
workflowBuilder.Root = new Flowchart
|
||||
{
|
||||
Variables =
|
||||
{
|
||||
loopVariable
|
||||
},
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
loopbackSwitch,
|
||||
a,
|
||||
incrementLoop,
|
||||
join,
|
||||
b,
|
||||
end
|
||||
},
|
||||
Connections =
|
||||
{
|
||||
new(start, loopbackSwitch),
|
||||
new(new Endpoint(loopbackSwitch, "DoLoopback"), new Endpoint(a)),
|
||||
new(new Endpoint(loopbackSwitch, "DoLoopback"), new Endpoint(incrementLoop)),
|
||||
new(new Endpoint(loopbackSwitch, "Default"), new Endpoint(b)),
|
||||
new(a, join),
|
||||
new(incrementLoop, join),
|
||||
new(join, loopbackSwitch),
|
||||
new(b, end),
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync(workflow);
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(WorkflowSubStatus.Finished, result.WorkflowState.SubStatus);
|
||||
Assert.Equal(new[] { "A", "A", "A", "B" }, lines);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Models;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.FlowchartNextActivity.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.FlowchartNextActivity.Workflows;
|
||||
|
||||
public class FlowchartWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var customActivity = new CustomActivity();
|
||||
var writeLine1 = new WriteLine("Line 1");
|
||||
var writeLine2 = new WriteLine("Line 2");
|
||||
|
||||
builder.Root = new Flowchart
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
customActivity,
|
||||
writeLine1,
|
||||
writeLine2
|
||||
},
|
||||
Connections =
|
||||
{
|
||||
new Connection(new Endpoint(customActivity, "Done"), new Endpoint(writeLine1)),
|
||||
new Connection(new Endpoint(customActivity, "Fake"), new Endpoint(writeLine2)),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.JavaScript.Activities;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Memory;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.HttpRequestWithLiquid;
|
||||
|
||||
/// <summary>
|
||||
/// A workflow that use javascript to get some data, use them with some liquid expressions
|
||||
/// </summary>
|
||||
public class JavascriptAndLiquidWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var products = new Variable<object>("Products", null!).WithStorageDriver<WorkflowInstanceStorageDriver>();
|
||||
var product = new Variable<object>("Product", null!).WithStorageDriver<WorkflowInstanceStorageDriver>();
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Variables = { products, product },
|
||||
Activities =
|
||||
{
|
||||
new RunJavaScript
|
||||
{
|
||||
Script = new(@"setProducts([{""id"":1, ""price"":12.99}, {""id"":2, ""price"":10}, {""id"":3, ""price"":1}])")
|
||||
},
|
||||
new WriteLine(new Expression("Liquid", "First product id: {{ Variables.Products[0].id }}")),
|
||||
new WriteLine(new Expression("Liquid", "First product price rounded: {{ Variables.Products[0].price | round }}")),
|
||||
new WriteLine(new Expression("Liquid", "First product as json: {{ Variables.Products[0] | json }}")),
|
||||
new WriteLine(new Expression("Liquid", "Second product id: {{ Variables.Products[1].id }}")),
|
||||
new RunJavaScript
|
||||
{
|
||||
Script = new(@"variables.Product = {""id"":2, ""price"":10}")
|
||||
},
|
||||
new WriteLine(new Expression("Liquid", "Single product id: {{ Variables.Product.id }}")),
|
||||
new WriteLine(new Expression("Liquid", "Single product as json: {{ Variables.Product | json }}")),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.HttpRequestWithLiquid;
|
||||
|
||||
public sealed class Tests : IDisposable
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.ConfigureElsa(configure => configure.UseHttp())
|
||||
.Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetProducts()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
RunWorkflowResult result = await _workflowRunner.RunAsync(new JavascriptAndLiquidWorkflow());
|
||||
Assert.Equal(WorkflowStatus.Finished, result.WorkflowState.Status);
|
||||
Assert.Empty(result.WorkflowState.Incidents);
|
||||
Assert.Equal(WorkflowSubStatus.Finished, result.WorkflowState.SubStatus);
|
||||
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Contains("First product id: 1", lines);
|
||||
Assert.Contains("First product price rounded: 13", lines);
|
||||
Assert.Contains("First product as json: {\"id\":1,\"price\":12.99}", lines);
|
||||
Assert.Contains("Second product id: 2", lines);
|
||||
|
||||
Assert.Contains("Single product id: 2", lines);
|
||||
Assert.Contains("Single product as json: {\"id\":2,\"price\":10}", lines);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_capturingTextWriter.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins.Workflows;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins;
|
||||
|
||||
public class BraidedWorkflowTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public BraidedWorkflowTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Braided workflows are executed correctly")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<BraidedWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "WriteLine1", "WriteLine2", "WriteLine3", "WriteLine4", "WriteLine5", "WriteLine6", "WriteLine7" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Braided workflows complete the workflow")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync<BraidedWorkflow>();
|
||||
Assert.Equal(WorkflowStatus.Finished, result.WorkflowState.Status);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins.Workflows;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins;
|
||||
|
||||
public class ImplicitWorkflowTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ImplicitWorkflowTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Implicit loop workflows are executed correctly")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<ImplicitLoopWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Start", "Retry", "End" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Implicit loop workflows complete the workflow")]
|
||||
public async Task Test2()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var result = await _workflowRunner.RunAsync<ImplicitLoopWorkflow>();
|
||||
Assert.Equal(WorkflowStatus.Finished, result.WorkflowState.Status);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using Elsa.Common.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using Elsa.Workflows.Runtime.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins;
|
||||
|
||||
public class JoinRunsOnceTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public JoinRunsOnceTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The Join activity executes only once, not twice")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync($"Scenarios/ImplicitJoins/Workflows/join.json");
|
||||
|
||||
// Execute.
|
||||
var state = await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Assert.
|
||||
var journal = await _services.GetRequiredService<IWorkflowExecutionLogStore>().FindManyAsync(new WorkflowExecutionLogRecordFilter
|
||||
{
|
||||
WorkflowInstanceId = state.Id,
|
||||
ActivityId = "802725996be1b582",
|
||||
EventName = "Completed"
|
||||
}, PageArgs.All);
|
||||
|
||||
Assert.Single(journal.Items);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using Elsa.Common.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using Elsa.Workflows.Runtime.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins;
|
||||
|
||||
public class ParallelJoinCompletesTests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ParallelJoinCompletesTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The ParallelForEach activity completes when its Body contains a Join activity")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync("Scenarios/ImplicitJoins/Workflows/parallel-join.json");
|
||||
|
||||
// Execute.
|
||||
var state = await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Assert.
|
||||
var journal = await _services.GetRequiredService<IWorkflowExecutionLogStore>().FindManyAsync(new()
|
||||
{
|
||||
WorkflowInstanceId = state.Id,
|
||||
ActivityId = "70fc1183cd5800f2",
|
||||
EventName = "Completed"
|
||||
}, PageArgs.All);
|
||||
|
||||
Assert.Single(journal.Items);
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins.Workflows;
|
||||
|
||||
public class BraidedWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
var writeLine1 = new WriteLine("WriteLine1");
|
||||
var writeLine2 = new WriteLine("WriteLine2");
|
||||
var writeLine3 = new WriteLine("WriteLine3");
|
||||
var writeLine4 = new WriteLine("WriteLine4");
|
||||
var writeLine5 = new WriteLine("WriteLine5");
|
||||
var writeLine6 = new WriteLine("WriteLine6");
|
||||
var writeLine7 = new WriteLine("WriteLine7");
|
||||
|
||||
workflow.Root = new Flowchart
|
||||
{
|
||||
Start = writeLine1,
|
||||
|
||||
Activities =
|
||||
{
|
||||
writeLine1,
|
||||
writeLine2,
|
||||
writeLine3,
|
||||
writeLine4,
|
||||
writeLine5,
|
||||
writeLine6,
|
||||
writeLine7,
|
||||
},
|
||||
|
||||
Connections =
|
||||
{
|
||||
new Connection(writeLine1, writeLine2),
|
||||
new Connection(writeLine1, writeLine3),
|
||||
|
||||
new Connection(writeLine2, writeLine4),
|
||||
new Connection(writeLine2, writeLine5),
|
||||
|
||||
new Connection(writeLine3, writeLine5),
|
||||
new Connection(writeLine3, writeLine6),
|
||||
|
||||
new Connection(writeLine4, writeLine7),
|
||||
new Connection(writeLine5, writeLine7),
|
||||
new Connection(writeLine6, writeLine7),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImplicitJoins.Workflows;
|
||||
|
||||
public class ImplicitLoopWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var counterVariable = builder.WithVariable(0);
|
||||
var start = new WriteLine("Start");
|
||||
var incrementCounter = new SetVariable<int>(counterVariable, context => counterVariable.Get(context) + 1);
|
||||
var counterGreaterThanOne = new FlowDecision(context => counterVariable.Get(context) > 1);
|
||||
var retry = new WriteLine("Retry");
|
||||
var end = new WriteLine("End");
|
||||
|
||||
builder.Root = new Flowchart
|
||||
{
|
||||
Start = start,
|
||||
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
incrementCounter,
|
||||
counterGreaterThanOne,
|
||||
retry,
|
||||
end
|
||||
},
|
||||
|
||||
Connections =
|
||||
{
|
||||
new Connection(start, incrementCounter),
|
||||
new Connection(incrementCounter, counterGreaterThanOne),
|
||||
new Connection(new Endpoint(counterGreaterThanOne, "False"), new Endpoint(retry)),
|
||||
new Connection(new Endpoint(counterGreaterThanOne, "True"), new Endpoint(end)),
|
||||
new Connection(retry, incrementCounter),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
{
|
||||
"id": "825e9d347e2f3094",
|
||||
"definitionId": "f64e42304661f407",
|
||||
"name": "Joins",
|
||||
"createdAt": "2023-12-13T21:41:53.628415+00:00",
|
||||
"version": 3,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {
|
||||
"Elsa:WorkflowContextProviderTypes": []
|
||||
},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "8a03bf79d15fd48a",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"id": "c7624645ff77c7d0",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a:c7624645ff77c7d0",
|
||||
"name": "Start1",
|
||||
"type": "Elsa.Start",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -400.5,
|
||||
"y": 212
|
||||
},
|
||||
"size": {
|
||||
"width": 102.21875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": null,
|
||||
"id": "281e9ea6d278b231",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a:281e9ea6d278b231",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -160.5,
|
||||
"y": 305
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAny"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "802725996be1b582:input-0"
|
||||
}
|
||||
},
|
||||
"id": "802725996be1b582",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a:802725996be1b582",
|
||||
"name": "FlowJoin1",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 80,
|
||||
"y": 200
|
||||
},
|
||||
"size": {
|
||||
"width": 98.265625,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": null,
|
||||
"id": "bfc88f064cf394ed",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a:bfc88f064cf394ed",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -160,
|
||||
"y": 120
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5467123c7973d011",
|
||||
"nodeId": "Workflow1:8a03bf79d15fd48a:5467123c7973d011",
|
||||
"name": "End1",
|
||||
"type": "Elsa.End",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 274.5,
|
||||
"y": 200
|
||||
},
|
||||
"size": {
|
||||
"width": 94.40625,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "c7624645ff77c7d0",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "bfc88f064cf394ed",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "bfc88f064cf394ed",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "802725996be1b582",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "c7624645ff77c7d0",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "281e9ea6d278b231",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "281e9ea6d278b231",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "802725996be1b582",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "802725996be1b582",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "5467123c7973d011",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
{
|
||||
"id": "2effd8f5f4205a5b",
|
||||
"definitionId": "2da8d4cb0fcfbacd",
|
||||
"name": "Parallel \u002B Join",
|
||||
"createdAt": "2023-12-13T21:42:12.634042+00:00",
|
||||
"version": 2,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {
|
||||
"Elsa:WorkflowContextProviderTypes": []
|
||||
},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "d3350290ed96e720",
|
||||
"nodeId": "Workflow1:d3350290ed96e720",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"items": {
|
||||
"typeName": "Object[]",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "[1,2,3]"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "70fc1183cd5800f2:input-0"
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "b07170f2d68980cd",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2:b07170f2d68980cd",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:45",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"condition": {
|
||||
"typeName": "Boolean",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "false"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "33665f061d96b957:input-0"
|
||||
}
|
||||
},
|
||||
"id": "33665f061d96b957",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2:b07170f2d68980cd:33665f061d96b957",
|
||||
"name": "FlowDecision1",
|
||||
"type": "Elsa.FlowDecision",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -329.140625,
|
||||
"y": -78.5
|
||||
},
|
||||
"size": {
|
||||
"width": 129.515625,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": null,
|
||||
"id": "e27177eb5965bd6b",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2:b07170f2d68980cd:e27177eb5965bd6b",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -40,
|
||||
"y": -160
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": null,
|
||||
"id": "343d233a75d8d8e9",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2:b07170f2d68980cd:343d233a75d8d8e9",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 371.859375,
|
||||
"y": -78.5
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": {
|
||||
"typeName": "Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "WaitAny"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "1f8625e278b74aa3:input-0"
|
||||
}
|
||||
},
|
||||
"id": "1f8625e278b74aa3",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2:b07170f2d68980cd:1f8625e278b74aa3",
|
||||
"name": "FlowJoin1",
|
||||
"type": "Elsa.FlowJoin",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 188.859375,
|
||||
"y": -78.5
|
||||
},
|
||||
"size": {
|
||||
"width": 98.265625,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "33665f061d96b957",
|
||||
"port": "True"
|
||||
},
|
||||
"target": {
|
||||
"activity": "e27177eb5965bd6b",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "e27177eb5965bd6b",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "1f8625e278b74aa3",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "1f8625e278b74aa3",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "343d233a75d8d8e9",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "33665f061d96b957",
|
||||
"port": "False"
|
||||
},
|
||||
"target": {
|
||||
"activity": "1f8625e278b74aa3",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "70fc1183cd5800f2",
|
||||
"nodeId": "Workflow1:d3350290ed96e720:70fc1183cd5800f2",
|
||||
"name": "ParallelForEach1",
|
||||
"type": "Elsa.ParallelForEach",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -260,
|
||||
"y": 140
|
||||
},
|
||||
"size": {
|
||||
"width": 185.203125,
|
||||
"height": 116.015625
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ImportAndExecute;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Workflow imported from file should execute successfully.")]
|
||||
[MemberData(memberName: nameof(GetSpecimen))]
|
||||
public async Task Test1(string workflowFileName, string[] expectedOutput)
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync($"Scenarios/ImportAndExecute/Workflows/{workflowFileName}");
|
||||
|
||||
// Execute.
|
||||
await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Assert.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
|
||||
Assert.Equal(expectedOutput, lines);
|
||||
}
|
||||
|
||||
public static TheoryData<string, string[]> GetSpecimen()
|
||||
{
|
||||
return new TheoryData<string, string[]>
|
||||
{
|
||||
{ "writeline.json", new[] { "Dummy Text" } },
|
||||
{ "implicit-loop.json", new[] { "Do something", "Retry", "Do something", "Done" } }
|
||||
};
|
||||
}
|
||||
}
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
{
|
||||
"id": "0975a7e7cff7421ea03d1cc0247db02b",
|
||||
"definitionId": "68e6bca3d86c4a5a8dfb825f1d5c0875",
|
||||
"name": "Looping construct",
|
||||
"createdAt": "2023-04-18T19:04:50.945222+00:00",
|
||||
"version": 1,
|
||||
"variables": [
|
||||
{
|
||||
"id": "b1198ecccf3f435abe462dc37012cda9",
|
||||
"name": "Counter",
|
||||
"typeName": "Int32",
|
||||
"isArray": false,
|
||||
"value": "0",
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
}
|
||||
],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "Start1",
|
||||
"activities": [
|
||||
{
|
||||
"variable": {
|
||||
"id": "b1198ecccf3f435abe462dc37012cda9",
|
||||
"name": "Counter",
|
||||
"typeName": "Int32",
|
||||
"value": "0",
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
},
|
||||
"value": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "getCounter() \u002B 1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "SetVariable1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "SetVariable1",
|
||||
"type": "Elsa.SetVariable",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2620,
|
||||
"y": 2280
|
||||
}
|
||||
},
|
||||
"displayText": "Increment counter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Done"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine3:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 3220,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "Done"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Retry"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine2:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2460,
|
||||
"y": 2500
|
||||
}
|
||||
},
|
||||
"displayText": "Retry"
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Do something"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2320,
|
||||
"y": 2280
|
||||
}
|
||||
},
|
||||
"displayText": "Do something"
|
||||
}
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"typeName": "Boolean",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "getCounter() \u003E 1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "FlowDecision1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "FlowDecision1",
|
||||
"type": "Elsa.FlowDecision",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2940,
|
||||
"y": 2400
|
||||
}
|
||||
},
|
||||
"displayText": "Counter \u003E 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Start1",
|
||||
"type": "Elsa.Start",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2060,
|
||||
"y": 2380
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": "WriteLine1",
|
||||
"target": "SetVariable1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "FlowDecision1",
|
||||
"target": "WriteLine3",
|
||||
"sourcePort": "True",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "FlowDecision1",
|
||||
"target": "WriteLine2",
|
||||
"sourcePort": "False",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "Start1",
|
||||
"target": "WriteLine1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "WriteLine2",
|
||||
"target": "WriteLine1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
},
|
||||
{
|
||||
"source": "SetVariable1",
|
||||
"target": "FlowDecision1",
|
||||
"sourcePort": "Done",
|
||||
"targetPort": "In"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"id": "3a793167cf6948c899d2f40c3c05cf0b",
|
||||
"definitionId": "11e2b350dae8485498c16d1ce3843829",
|
||||
"name": "Dummy workflow",
|
||||
"createdAt": "2023-04-04T08:35:22.841043+00:00",
|
||||
"version": 1,
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"metadata": {},
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "Flowchart1",
|
||||
"metadata": {},
|
||||
"applicationProperties": {
|
||||
"NotFoundConnectionsKey": []
|
||||
},
|
||||
"start": "WriteLine1",
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Dummy Text"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "WriteLine1:input-1"
|
||||
}
|
||||
},
|
||||
"id": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"customProperties": {},
|
||||
"source": null,
|
||||
"line": null,
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 2256,
|
||||
"y": 2462
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": []
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user