Add project files.
This commit is contained in:
@@ -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": []
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.IncidentStrategies;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.Incidents.Statics;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.Incidents.Workflows;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Incidents;
|
||||
|
||||
public class IncidentStrategyTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
|
||||
public IncidentStrategyTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.AddWorkflow<FaultyWorkflow>()
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Workflows with a Fault strategy do not continue after a fault")]
|
||||
[InlineData(typeof(FaultStrategy), new[] { "Start", "Step 1a", "Step 2a" }, WorkflowSubStatus.Faulted)]
|
||||
[InlineData(typeof(ContinueWithIncidentsStrategy), new[] { "Start", "Step 1a", "Step 2a", "Step 1b" }, WorkflowSubStatus.Suspended)]
|
||||
public async Task Test0(Type incidentStrategyType, string[] expectedOutput, WorkflowSubStatus expectedSubStatus)
|
||||
{
|
||||
TestSettings.IncidentStrategyType = incidentStrategyType;
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync<FaultyWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(expectedOutput, lines);
|
||||
Assert.Equal(expectedSubStatus, workflowState.SubStatus);
|
||||
Assert.Equal(1, workflowState.Incidents.Count);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
using Elsa.Workflows.IncidentStrategies;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Incidents.Statics;
|
||||
|
||||
public static class TestSettings
|
||||
{
|
||||
public static Type IncidentStrategyType { get; set; } = typeof(FaultStrategy);
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Activities;
|
||||
using Elsa.Workflows.Activities.Flowchart.Models;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.Incidents.Statics;
|
||||
using Elsa.Workflows.Runtime.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.Incidents.Workflows;
|
||||
|
||||
public class FaultyWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var start = new WriteLine("Start");
|
||||
var step1A = new WriteLine("Step 1a");
|
||||
var event1 = new Event("Event 1");
|
||||
var step1B = new WriteLine("Step 1b");
|
||||
var step2A = new WriteLine("Step 2a");
|
||||
var event2 = new Event("Event 2");
|
||||
var step2B = new WriteLine("Step 2b");
|
||||
var fault = Fault.Create("Whoops!", "Test", "Test");
|
||||
|
||||
builder.WorkflowOptions.IncidentStrategyType = TestSettings.IncidentStrategyType;
|
||||
|
||||
builder.Root = new Flowchart
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
start,
|
||||
step1A,
|
||||
event1,
|
||||
step1B,
|
||||
step2A,
|
||||
event2,
|
||||
step2B,
|
||||
fault
|
||||
},
|
||||
|
||||
Connections = new[]
|
||||
{
|
||||
new Connection(start, step1A),
|
||||
new Connection(step1A, event1),
|
||||
new Connection(event1, step1B),
|
||||
|
||||
new Connection(start, step2A),
|
||||
new Connection(step2A, fault),
|
||||
new Connection(fault, event2),
|
||||
new Connection(event2, step2B),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
using System.Text;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.JavaScript.Contracts;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptFunctions;
|
||||
|
||||
public class BytesAndStringEncodingTests
|
||||
{
|
||||
private readonly IJavaScriptEvaluator _evaluator;
|
||||
private readonly ExpressionExecutionContext _expressionContext;
|
||||
|
||||
public BytesAndStringEncodingTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
var testOutputHelper1 = testOutputHelper ?? throw new ArgumentNullException(nameof(testOutputHelper));
|
||||
var services = new TestApplicationBuilder(testOutputHelper1).Build();
|
||||
_evaluator = services.GetRequiredService<IJavaScriptEvaluator>();
|
||||
_expressionContext = new ExpressionExecutionContext(services, new MemoryRegister());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ByteArrayToString_ConvertsTo_String()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var script = "bytesToString(getData())";
|
||||
_expressionContext.SetVariable("Data", bytes);
|
||||
var result = (string)(await _evaluator.EvaluateAsync(script, typeof(string), _expressionContext))!;
|
||||
|
||||
Assert.Equal(data, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ByteArrayFromString_ConvertsTo_ByteArray()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var script = "bytesFromString(getData())";
|
||||
_expressionContext.SetVariable("Data", data);
|
||||
var result = (byte[])(await _evaluator.EvaluateAsync(script, typeof(byte[]), _expressionContext))!;
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
|
||||
Assert.Equal(bytes, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ByteArrayToBase64_ConvertsTo_Base64()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
var script = "bytesToBase64(getData())";
|
||||
_expressionContext.SetVariable("Data", bytes);
|
||||
var result = (string)(await _evaluator.EvaluateAsync(script, typeof(string), _expressionContext))!;
|
||||
|
||||
Assert.Equal(base64, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ByteArrayFromBase64_ConvertsTo_ByteArray()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
var script = "bytesFromBase64(getData())";
|
||||
_expressionContext.SetVariable("Data", base64);
|
||||
var result = (byte[])(await _evaluator.EvaluateAsync(script, typeof(byte[]), _expressionContext))!;
|
||||
|
||||
Assert.Equal(bytes, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StringToBase64_ConvertsTo_Base64()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
var script = "stringToBase64(getData())";
|
||||
_expressionContext.SetVariable("Data", data);
|
||||
var result = (string)(await _evaluator.EvaluateAsync(script, typeof(string), _expressionContext))!;
|
||||
|
||||
Assert.Equal(base64, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StringFromBase64_ConvertsTo_String()
|
||||
{
|
||||
const string data = "Hello World!";
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var base64 = Convert.ToBase64String(bytes);
|
||||
var script = "stringFromBase64(getData())";
|
||||
_expressionContext.SetVariable("Data", base64);
|
||||
var result = (string)(await _evaluator.EvaluateAsync(script, typeof(string), _expressionContext))!;
|
||||
|
||||
Assert.Equal(data, result);
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using System.Dynamic;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.JavaScript.Contracts;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptListsAndArrays;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
private readonly IJavaScriptEvaluator _evaluator;
|
||||
private readonly ExpressionExecutionContext _expressionContext;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
var testOutputHelper1 = testOutputHelper ?? throw new ArgumentNullException(nameof(testOutputHelper));
|
||||
var services = new TestApplicationBuilder(testOutputHelper1).Build();
|
||||
_evaluator = services.GetRequiredService<IJavaScriptEvaluator>();
|
||||
_expressionContext = new ExpressionExecutionContext(services, new MemoryRegister());
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Workflow inputs containing .NET lists on dynamic objects are converted to arrays for use in JavaScript.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
dynamic dynamicObject = new ExpandoObject();
|
||||
|
||||
dynamicObject.List = new List<string>
|
||||
{
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
};
|
||||
var script = "getObj().List.filter(x => x === 'b').length === 1";
|
||||
_expressionContext.SetVariable("obj", (object)dynamicObject);
|
||||
var result = await _evaluator.EvaluateAsync(script, typeof(bool), _expressionContext);
|
||||
|
||||
Assert.True((bool)result!);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Can access list properties as arrays")]
|
||||
public async Task Test2()
|
||||
{
|
||||
var person = new ExpandoObject();
|
||||
var magicNumbers = new[]
|
||||
{
|
||||
42, 43, 44
|
||||
};
|
||||
var order1 = new ExpandoObject();
|
||||
|
||||
order1.TryAdd("magicNumbers", magicNumbers);
|
||||
person.TryAdd("orders", new[]
|
||||
{
|
||||
order1
|
||||
});
|
||||
person.TryAdd("name", "John");
|
||||
person.TryAdd("age", 12);
|
||||
|
||||
var languages = new List<object>
|
||||
{
|
||||
"English",
|
||||
"French"
|
||||
};
|
||||
|
||||
person.TryAdd("languages", languages);
|
||||
|
||||
var obj = new ExpandoObject();
|
||||
obj.TryAdd("persons", new List<object>
|
||||
{
|
||||
person
|
||||
});
|
||||
|
||||
var name = await _evaluator.EvaluateAsync("o.persons.filter(x => x.age == 12)[0].name", typeof(string), _expressionContext, configureEngine: engine => engine.SetValue("o", obj));
|
||||
var language = await _evaluator.EvaluateAsync("o.persons[0].languages.filter(x => x == 'English')[0]", typeof(string), _expressionContext, configureEngine: engine => engine.SetValue("o", obj));
|
||||
var magicNumber = await _evaluator.EvaluateAsync("o.persons[0].orders[0].magicNumbers[1]", typeof(int), _expressionContext, configureEngine: engine => engine.SetValue("o", obj));
|
||||
Assert.Equal("John", name);
|
||||
Assert.Equal("English", language);
|
||||
Assert.Equal(43, magicNumber);
|
||||
}
|
||||
|
||||
[Theory(DisplayName = "Can sort array and list properties as mutable arrays")]
|
||||
[MemberData(nameof(ArraySortEnumerableData))]
|
||||
// See also:
|
||||
// - https://github.com/sebastienros/jint/issues/1942
|
||||
// - https://github.com/elsa-workflows/elsa-core/issues/5912
|
||||
public async Task Test5(IEnumerable<double> collection)
|
||||
{
|
||||
dynamic dynamicObject = new ExpandoObject();
|
||||
dynamicObject.Items = collection;
|
||||
var script = """
|
||||
const model = variables.Model;
|
||||
model.Items.sort((a, b) => a - b);
|
||||
return model;
|
||||
""";
|
||||
_expressionContext.SetVariable("Model", (object)dynamicObject);
|
||||
dynamicObject = (ExpandoObject)(await _evaluator.EvaluateAsync(script, typeof(ExpandoObject), _expressionContext))!;
|
||||
var items = ((object[])dynamicObject.Items).Cast<double>().ToArray();
|
||||
|
||||
Assert.Equal([2, 4, 8], items);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ArraySortEnumerableData = new object[][]
|
||||
{
|
||||
[
|
||||
new double[]
|
||||
{
|
||||
8, 4, 2
|
||||
}
|
||||
],
|
||||
[
|
||||
new List<double>
|
||||
{
|
||||
8,
|
||||
4,
|
||||
2
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
using System.Dynamic;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptNativeVariables;
|
||||
|
||||
public class Data
|
||||
{
|
||||
public static ExpandoObject CreateCustomerModel()
|
||||
{
|
||||
dynamic customer = new ExpandoObject();
|
||||
customer.Name = "John Doe";
|
||||
customer.Age = 42;
|
||||
customer.Orders = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
Id = 1,
|
||||
Product = "Apple",
|
||||
Price = 10
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 3,
|
||||
Product = "Orange",
|
||||
Price = 30
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = 2,
|
||||
Product = "Banana",
|
||||
Price = 20
|
||||
}
|
||||
};
|
||||
return customer;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptNativeVariables;
|
||||
|
||||
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 JavaScript activity can access and modify native variables")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<JavaScriptWorkflow>();
|
||||
await _workflowRunner.RunAsync(workflow);
|
||||
var line1 = _capturingTextWriter.Lines.ToList().ElementAt(0);
|
||||
var line2 = _capturingTextWriter.Lines.ToList().ElementAt(1);
|
||||
var line3 = _capturingTextWriter.Lines.ToList().ElementAt(2);
|
||||
Assert.Equal("Jane Doe", line1);
|
||||
Assert.Equal("Apple, Banana, Orange", line2);
|
||||
Assert.Equal("jane.doe@acme.com", line3);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Elsa.JavaScript.Activities;
|
||||
using Elsa.JavaScript.Models;
|
||||
using Elsa.Workflows.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptNativeVariables;
|
||||
|
||||
public class JavaScriptWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.WithDefinitionId(Guid.NewGuid().ToString());
|
||||
var customerVariable = workflow.WithVariable("customer", Data.CreateCustomerModel());
|
||||
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new RunJavaScript
|
||||
{
|
||||
Script = new("""
|
||||
const customer = variables.customer;
|
||||
customer.Name = 'Jane Doe';
|
||||
customer.Orders.sort((a, b) => a.Product.localeCompare(b.Product));
|
||||
variables.customer = {...customer, Email: 'jane.doe@acme.com'};
|
||||
""")
|
||||
},
|
||||
new WriteLine(JavaScriptExpression.Create("variables.customer.Name")),
|
||||
new WriteLine(JavaScriptExpression.Create("variables.customer.Orders.map(x => x.Product).join(', ')")),
|
||||
new WriteLine(JavaScriptExpression.Create("variables.customer.Email"))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.State;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectSerialization;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for serializing and deserializing JSON objects containing reserved keywords such as $id.
|
||||
/// </summary>
|
||||
public class Tests
|
||||
{
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IWorkflowStateSerializer _workflowStateSerializer;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_workflowStateSerializer = _services.GetRequiredService<IWorkflowStateSerializer>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "User-objects containing $id don't break deserialization into ExpandoObject.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import workflow.
|
||||
var workflowFileName = "Scenarios/JsonObjectSerialization/Workflows/instance-serialization.json";
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync(workflowFileName);
|
||||
|
||||
// Execute.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId);
|
||||
|
||||
// Serialize workflow state.
|
||||
var serializedWorkflowState = _workflowStateSerializer.Serialize(workflowState);
|
||||
|
||||
// Attempt to deserialize workflow state.
|
||||
_workflowStateSerializer.Deserialize<WorkflowState>(serializedWorkflowState);
|
||||
|
||||
// If we reach this point, the test has passed. Otherwise, an exception would have been thrown.
|
||||
}
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"id": "b78e443339b5bf1e",
|
||||
"definitionId": "861e51cdbe07931",
|
||||
"name": "Instance Serialization",
|
||||
"description": "This workflow stores a user-JSON object containing $id as a field, which should not affect the deserialization process form JSON back into ExpandoObject.",
|
||||
"createdAt": "2023-11-23T15:18:12.805077+00:00",
|
||||
"version": 13,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [
|
||||
{
|
||||
"id": "d4f37df0c6781767",
|
||||
"name": "Variable1",
|
||||
"typeName": "Object",
|
||||
"isArray": false,
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
},
|
||||
{
|
||||
"id": "4e256dab27d33eac",
|
||||
"name": "Variable2",
|
||||
"typeName": "Object",
|
||||
"isArray": false,
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
}
|
||||
],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": false,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "35cdc2a3529d9b55",
|
||||
"nodeId": "Workflow1:35cdc2a3529d9b55",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:47",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"variable": {
|
||||
"id": "d4f37df0c6781767",
|
||||
"name": "Variable1",
|
||||
"typeName": "Object",
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
},
|
||||
"value": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "return {\n \u0022inputSchema\u0022: {\n \u0022$schema\u0022: \u0022http://json-schema.org/draft-07/schema#\u0022,\n \u0022title\u0022: \u0022Inform front-office afd 2.0 input schema\u0022,\n \u0022description\u0022: \u0022Schema of the AFD 2.0 message that is sent to the front-office\u0022,\n \u0022$id\u0022: \u0022#/definitions/inform-front-office-input-afd\u0022,\n \u0022type\u0022: \u0022object\u0022\n }\n}"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "d4f32ee0ad659ba5:input-0"
|
||||
}
|
||||
},
|
||||
"id": "d4f32ee0ad659ba5",
|
||||
"nodeId": "Workflow1:35cdc2a3529d9b55:d4f32ee0ad659ba5",
|
||||
"name": "SetVariable1",
|
||||
"type": "Elsa.SetVariable",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -456.5988464355469,
|
||||
"y": -104.93463134765625
|
||||
},
|
||||
"size": {
|
||||
"width": 153.828125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"variable": {
|
||||
"id": "4e256dab27d33eac",
|
||||
"name": "Variable2",
|
||||
"typeName": "Object",
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
},
|
||||
"value": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "JavaScript",
|
||||
"value": "return getVariable1()"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "31c60a181a1a66d8:input-0"
|
||||
}
|
||||
},
|
||||
"id": "31c60a181a1a66d8",
|
||||
"nodeId": "Workflow1:35cdc2a3529d9b55:31c60a181a1a66d8",
|
||||
"name": "SetVariable2",
|
||||
"type": "Elsa.SetVariable",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -210.69132232666016,
|
||||
"y": -104.93463134765625
|
||||
},
|
||||
"size": {
|
||||
"width": 153.828125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "d4f32ee0ad659ba5",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "31c60a181a1a66d8",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Elsa.Extensions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectToObjectRemainsJsonObject.Activities;
|
||||
|
||||
public class JsonObjectProducer : CodeActivity<JsonObject>
|
||||
{
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var value = new JsonObject
|
||||
{
|
||||
["Foo"] = new JsonObject
|
||||
{
|
||||
["Bar"] = "Baz"
|
||||
}
|
||||
};
|
||||
|
||||
context.SetResult(value);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectToObjectRemainsJsonObject.Activities;
|
||||
|
||||
public class ObjectProcessor : CodeActivity<object>
|
||||
{
|
||||
public Input<object> Value { get; set; } = default!;
|
||||
|
||||
protected override void Execute(ActivityExecutionContext context)
|
||||
{
|
||||
var value = Value.Get(context);
|
||||
context.SetResult(value);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectToObjectRemainsJsonObject;
|
||||
|
||||
public class JsonObjectJintTests
|
||||
{
|
||||
private readonly IWorkflowRunner _workflowRunner;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public JsonObjectJintTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).WithCapturingTextWriter(_capturingTextWriter).Build();
|
||||
_services.GetRequiredService<IWorkflowBuilderFactory>();
|
||||
_workflowRunner = _services.GetRequiredService<IWorkflowRunner>();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "The produced JsonObject remains JsonObject and does not become JsonElement (which does not support index notation)")]
|
||||
public async Task Test1()
|
||||
{
|
||||
await _services.PopulateRegistriesAsync();
|
||||
await _workflowRunner.RunAsync<Workflows.TestWorkflow>();
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Baz" }, lines);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.JavaScript.Models;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectToObjectRemainsJsonObject.Activities;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.JsonObjectToObjectRemainsJsonObject.Workflows;
|
||||
|
||||
public class TestWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var item = builder.WithVariable<JsonObject>("item", default!);
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new JsonObjectProducer
|
||||
{
|
||||
Result = new(item)
|
||||
},
|
||||
new ObjectProcessor
|
||||
{
|
||||
Value = new(JavaScriptExpression.Create("getItem()"), new MemoryBlockReference()),
|
||||
Result = new(item)
|
||||
},
|
||||
new WriteLine(JavaScriptExpression.Create("getItem()['Foo']['Bar']"))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ParentChildCompletion;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for mapping an activity's output directly to the workflow's output definition.
|
||||
/// </summary>
|
||||
public class Tests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public Tests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper).Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Parent workflow invoking child workflow as activity completes successfully.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import child workflow.
|
||||
var childWorkflowFilename = "Scenarios/ParentChildCompletion/Workflows/child.json";
|
||||
await _services.ImportWorkflowDefinitionAsync(childWorkflowFilename);
|
||||
|
||||
// Import parent workflow.
|
||||
var parentWorkflowFilename = "Scenarios/ParentChildCompletion/Workflows/parent.json";
|
||||
var parentWorkflowDefinition = await _services.ImportWorkflowDefinitionAsync(parentWorkflowFilename);
|
||||
|
||||
// Execute.
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync(parentWorkflowDefinition.DefinitionId);
|
||||
|
||||
// Assert expected status
|
||||
Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
|
||||
}
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
{
|
||||
"id": "c8109a84c584c83c",
|
||||
"definitionId": "3dcdbf22d29d6e60",
|
||||
"name": "Subworkflow test",
|
||||
"createdAt": "2023-11-10T13:03:21.734094+00:00",
|
||||
"version": 4,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [
|
||||
{
|
||||
"id": "c0dbe71ceb21ee4f",
|
||||
"name": "Variable1",
|
||||
"typeName": "Object",
|
||||
"isArray": false,
|
||||
"storageDriverTypeName": "Elsa.Workflows.Services.WorkflowStorageDriver, Elsa.Workflows.Core"
|
||||
}
|
||||
],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [
|
||||
"Success",
|
||||
"Failure"
|
||||
],
|
||||
"customProperties": {},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"usableAsActivity": true,
|
||||
"autoUpdateConsumingWorkflows": true
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "2492a1125f14bc2d",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:47",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "test"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "a3625dd2e8405265:input-0"
|
||||
}
|
||||
},
|
||||
"id": "a3625dd2e8405265",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:a3625dd2e8405265",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": true,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -174,
|
||||
"y": 302
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "1"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "31d29bf86b2b62cb:input-0"
|
||||
}
|
||||
},
|
||||
"id": "31d29bf86b2b62cb",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:31d29bf86b2b62cb",
|
||||
"name": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 132.6484375,
|
||||
"y": 292
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "11"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "57576570e00a4c70:input-0"
|
||||
}
|
||||
},
|
||||
"id": "57576570e00a4c70",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:57576570e00a4c70",
|
||||
"name": "WriteLine5",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 449.6484375,
|
||||
"y": 280
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "22"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "caa57f31b8d0e0d1:input-0"
|
||||
}
|
||||
},
|
||||
"id": "caa57f31b8d0e0d1",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:caa57f31b8d0e0d1",
|
||||
"name": "WriteLine4",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 449.6484375,
|
||||
"y": 563
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"script": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "return {\u0022prop1\u0022:\u0022ceva\u0022}"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "fb20dbd8777282b2:input-0"
|
||||
}
|
||||
},
|
||||
"possibleOutcomes": null,
|
||||
"result": {
|
||||
"typeName": "Object",
|
||||
"memoryReference": {
|
||||
"id": "c0dbe71ceb21ee4f"
|
||||
}
|
||||
},
|
||||
"id": "fb20dbd8777282b2",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:fb20dbd8777282b2",
|
||||
"name": "RunJavaScript1",
|
||||
"type": "Elsa.RunJavaScript",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 114.453125,
|
||||
"y": 563
|
||||
},
|
||||
"size": {
|
||||
"width": 175.6875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"outcomes": {
|
||||
"typeName": "Object",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Success"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "8654ab45535f4069:input-0"
|
||||
}
|
||||
},
|
||||
"id": "8654ab45535f4069",
|
||||
"nodeId": "Workflow1:2492a1125f14bc2d:8654ab45535f4069",
|
||||
"name": "Complete1",
|
||||
"type": "Elsa.Complete",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 738.7582397460938,
|
||||
"y": 690.54443359375
|
||||
},
|
||||
"size": {
|
||||
"width": 136.8125,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "a3625dd2e8405265",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "31d29bf86b2b62cb",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "31d29bf86b2b62cb",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "57576570e00a4c70",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "fb20dbd8777282b2",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "caa57f31b8d0e0d1",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "a3625dd2e8405265",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "fb20dbd8777282b2",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "caa57f31b8d0e0d1",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "8654ab45535f4069",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"id": "34991d27edc12ae5",
|
||||
"definitionId": "89d6fe82a11fbed6",
|
||||
"name": "Mainworkflow test",
|
||||
"createdAt": "2023-11-10T21:01:49.123204+00:00",
|
||||
"version": 2,
|
||||
"toolVersion": "3.0.0.0",
|
||||
"variables": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"outcomes": [],
|
||||
"customProperties": {
|
||||
"Elsa:WorkflowContextProviderTypes": []
|
||||
},
|
||||
"isReadonly": false,
|
||||
"isLatest": true,
|
||||
"isPublished": true,
|
||||
"options": {
|
||||
"autoUpdateConsumingWorkflows": false
|
||||
},
|
||||
"root": {
|
||||
"type": "Elsa.Flowchart",
|
||||
"version": 1,
|
||||
"id": "f9071ee83c88d765",
|
||||
"nodeId": "Workflow1:f9071ee83c88d765",
|
||||
"metadata": {},
|
||||
"customProperties": {
|
||||
"source": "FlowchartJsonConverter.cs:47",
|
||||
"notFoundConnections": [],
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"activities": [
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Success"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "77069142b8b9da15:input-0"
|
||||
}
|
||||
},
|
||||
"id": "77069142b8b9da15",
|
||||
"nodeId": "Workflow1:f9071ee83c88d765:77069142b8b9da15",
|
||||
"name": "WriteLine2",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 231.8203125,
|
||||
"y": 200
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Failure"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "34e3dcda423f3c1c:input-0"
|
||||
}
|
||||
},
|
||||
"id": "34e3dcda423f3c1c",
|
||||
"nodeId": "Workflow1:f9071ee83c88d765:34e3dcda423f3c1c",
|
||||
"name": "WriteLine3",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": 231.8203125,
|
||||
"y": 393
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Start"
|
||||
},
|
||||
"memoryReference": {
|
||||
"id": "8b7bf9cd03c066fa:input-0"
|
||||
}
|
||||
},
|
||||
"id": "8b7bf9cd03c066fa",
|
||||
"nodeId": "Workflow1:f9071ee83c88d765:8b7bf9cd03c066fa",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -340,
|
||||
"y": 309
|
||||
},
|
||||
"size": {
|
||||
"width": 139.296875,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"workflowDefinitionId": "b8b45fd4dbffad5d",
|
||||
"workflowDefinitionVersionId": "24dd11bc73a881d5",
|
||||
"latestAvailablePublishedVersion": 7,
|
||||
"latestAvailablePublishedVersionId": "24dd11bc73a881d5",
|
||||
"id": "abcd6d3d391bfe10",
|
||||
"nodeId": "Workflow1:f9071ee83c88d765:abcd6d3d391bfe10",
|
||||
"name": "SubworkflowTest1",
|
||||
"type": "SubworkflowTest",
|
||||
"version": 7,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {
|
||||
"designer": {
|
||||
"position": {
|
||||
"x": -54,
|
||||
"y": 309
|
||||
},
|
||||
"size": {
|
||||
"width": 157.09375,
|
||||
"height": 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"source": {
|
||||
"activity": "8b7bf9cd03c066fa",
|
||||
"port": "Done"
|
||||
},
|
||||
"target": {
|
||||
"activity": "abcd6d3d391bfe10",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "abcd6d3d391bfe10",
|
||||
"port": "Success"
|
||||
},
|
||||
"target": {
|
||||
"activity": "77069142b8b9da15",
|
||||
"port": "In"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": {
|
||||
"activity": "abcd6d3d391bfe10",
|
||||
"port": "Failure"
|
||||
},
|
||||
"target": {
|
||||
"activity": "34e3dcda423f3c1c",
|
||||
"port": "In"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using Elsa.Testing.Shared;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.ParentChildInputs;
|
||||
|
||||
/// <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();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Child activity receives workflow input from parent even if same name.")]
|
||||
public async Task Test1()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import child workflow.
|
||||
var childFileName = $"Scenarios/ParentChildInputs/Workflows/child.json";
|
||||
await _services.ImportWorkflowDefinitionAsync(childFileName);
|
||||
|
||||
// Import parent workflow.
|
||||
var parentFileName = $"Scenarios/ParentChildInputs/Workflows/parent1.json";
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync(parentFileName);
|
||||
|
||||
// Execute.
|
||||
var input = new Dictionary<string, object> { ["Input1"] = "Foo" };
|
||||
await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId, input);
|
||||
|
||||
// Assert expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Parent: Foo", "Child: Bar" }, lines);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Child activity receives input from parent event if same name and does not use global workflow input.")]
|
||||
public async Task Test2()
|
||||
{
|
||||
// Populate registries.
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Import child workflow.
|
||||
var childFileName = $"Scenarios/ParentChildInputs/Workflows/child.json";
|
||||
await _services.ImportWorkflowDefinitionAsync(childFileName);
|
||||
|
||||
// Import parent workflow.
|
||||
var parentFileName = $"Scenarios/ParentChildInputs/Workflows/parent2.json";
|
||||
var workflowDefinition = await _services.ImportWorkflowDefinitionAsync(parentFileName);
|
||||
|
||||
// Execute.
|
||||
var input = new Dictionary<string, object> { ["Input1"] = "Foo" };
|
||||
await _services.RunWorkflowUntilEndAsync(workflowDefinition.DefinitionId, input);
|
||||
|
||||
// Assert expected output.
|
||||
var lines = _capturingTextWriter.Lines.ToList();
|
||||
Assert.Equal(new[] { "Parent: Foo", "Child: Foo" }, lines);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user