Fix Liquid expressions not working in sub-workflows (workflow-as-activity) (#6678)
* Initial plan for issue * Fix Liquid expressions not working in sub-workflows Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>
This commit is contained in:
parent
144edc3a85
commit
b9697a9e28
|
|
@ -75,10 +75,18 @@ internal class ConfigureLiquidEngine : INotificationHandler<RenderingLiquidTempl
|
|||
|
||||
private Task<FluidValue> GetInput(ExpressionExecutionContext context, string key, TemplateOptions options)
|
||||
{
|
||||
var workflowExecutionContext = context.GetWorkflowExecutionContext();
|
||||
var input = workflowExecutionContext.Input.TryGetValue(key, out var value) ? value : default;
|
||||
// First, check if the current activity has inputs
|
||||
if (context.TryGetActivityExecutionContext(out var activityExecutionContext) &&
|
||||
activityExecutionContext.Input.TryGetValue(key, out var activityValue))
|
||||
{
|
||||
return Task.FromResult(activityValue == null ? NilValue.Instance : FluidValue.Create(activityValue, options));
|
||||
}
|
||||
|
||||
return Task.FromResult(input == null ? NilValue.Instance : FluidValue.Create(value, options));
|
||||
// Fall back to workflow inputs if activity inputs don't contain the key
|
||||
var workflowExecutionContext = context.GetWorkflowExecutionContext();
|
||||
var input = workflowExecutionContext.Input.TryGetValue(key, out var workflowValue) ? workflowValue : default;
|
||||
|
||||
return Task.FromResult(input == null ? NilValue.Instance : FluidValue.Create(workflowValue, options));
|
||||
}
|
||||
|
||||
private static object? GetVariableInScope(ExpressionExecutionContext context, string variableName)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.LiquidSubWorkflow;
|
||||
|
||||
public class LiquidSubWorkflowTests
|
||||
{
|
||||
private readonly ITestOutputHelper _testOutputHelper;
|
||||
|
||||
public LiquidSubWorkflowTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_testOutputHelper = testOutputHelper;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldBeAbleToUseLiquidExpressionsToReadInputInSubWorkflows()
|
||||
{
|
||||
// Arrange.
|
||||
var services = new TestApplicationBuilder()
|
||||
.WithCapturingTextWriter()
|
||||
.Build();
|
||||
|
||||
var workflowRunner = services.GetRequiredService<IWorkflowRunner>();
|
||||
|
||||
// Act.
|
||||
await workflowRunner.RunAsync<LiquidParentWorkflow>();
|
||||
|
||||
// Assert.
|
||||
var capturedOutput = services.GetRequiredService<StringWriter>();
|
||||
var output = capturedOutput.ToString();
|
||||
_testOutputHelper.WriteLine(output);
|
||||
|
||||
// Verify that the liquid expressions were able to read the input values.
|
||||
Assert.Contains("Person: John Doe, Email: john@example.com", output);
|
||||
Assert.Contains("Sub workflow result: John Doe - john@example.com", output);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Management.Activities.SetOutput;
|
||||
using Elsa.Workflows.Memory;
|
||||
using Elsa.Workflows.Models;
|
||||
using Elsa.Expressions.Models;
|
||||
|
||||
namespace Elsa.Workflows.IntegrationTests.Scenarios.LiquidSubWorkflow;
|
||||
|
||||
/// <summary>
|
||||
/// A sub-workflow that reads input using liquid expressions
|
||||
/// </summary>
|
||||
public class LiquidSubWorkflow : WorkflowBase
|
||||
{
|
||||
public Input<string> PersonName { get; set; } = default!;
|
||||
public Input<string> PersonEmail { get; set; } = default!;
|
||||
public Output<string> Result { get; set; } = default!;
|
||||
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var resultVariable = new Variable<string>("Result");
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Variables = { resultVariable },
|
||||
Activities =
|
||||
{
|
||||
// Use liquid to read inputs
|
||||
new WriteLine(new Expression("Liquid", "Person: {{ Input.PersonName }}, Email: {{ Input.PersonEmail }}")),
|
||||
|
||||
// Set the result with liquid expression
|
||||
new SetVariable
|
||||
{
|
||||
Variable = resultVariable,
|
||||
Value = new Expression("Liquid", "{{ Input.PersonName }} - {{ Input.PersonEmail }}")
|
||||
},
|
||||
|
||||
// Set output
|
||||
new SetOutput
|
||||
{
|
||||
OutputName = new("Result"),
|
||||
OutputValue = new(resultVariable)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A main workflow that uses the sub-workflow as an activity
|
||||
/// </summary>
|
||||
public class LiquidParentWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder builder)
|
||||
{
|
||||
var resultVariable = new Variable<string>("Result");
|
||||
|
||||
var subWorkflow = new LiquidSubWorkflow
|
||||
{
|
||||
PersonName = new("John Doe"),
|
||||
PersonEmail = new("john@example.com"),
|
||||
Result = new(resultVariable)
|
||||
};
|
||||
|
||||
builder.Variables.Add(resultVariable);
|
||||
|
||||
builder.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
subWorkflow,
|
||||
new WriteLine(context => $"Sub workflow result: {resultVariable.Get(context)}")
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue