Add unit and integration tests for SetOutput activity
- Introduced unit tests for `SetOutput` to validate single, multiple, and dynamic output scenarios. - Added integration tests covering workflows with `SetOutput` activity, ensuring correct output handling. - Simplified test setups by leveraging `ActivityTestFixture`.
This commit is contained in:
parent
762f23dbc3
commit
8a61fa4045
|
|
@ -0,0 +1,135 @@
|
|||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Management.Activities.SetOutput;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Activities.IntegrationTests;
|
||||
|
||||
public class SetOutputTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly CapturingTextWriter _capturingTextWriter = new();
|
||||
|
||||
public SetOutputTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_services = new TestApplicationBuilder(testOutputHelper)
|
||||
.WithCapturingTextWriter(_capturingTextWriter)
|
||||
.AddWorkflow<BasicWorkflowOutputWorkflow>()
|
||||
.AddWorkflow<MultipleOutputsWorkflow>()
|
||||
.AddWorkflow<DynamicOutputValueWorkflow>()
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "SetOutput sets workflow execution context output")]
|
||||
public async Task SetOutput_Should_Set_Workflow_Output()
|
||||
{
|
||||
// Arrange
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Act
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync<BasicWorkflowOutputWorkflow>();
|
||||
|
||||
// Assert
|
||||
Assert.Contains("Message", workflowState.Output.Keys);
|
||||
Assert.Equal("Hello, World!", workflowState.Output["Message"]);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "SetOutput can set multiple outputs")]
|
||||
public async Task SetOutput_Should_Set_Multiple_Outputs()
|
||||
{
|
||||
// Arrange
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Act
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync<MultipleOutputsWorkflow>();
|
||||
|
||||
// Assert
|
||||
Assert.Contains("FirstName", workflowState.Output.Keys);
|
||||
Assert.Contains("LastName", workflowState.Output.Keys);
|
||||
Assert.Contains("Age", workflowState.Output.Keys);
|
||||
|
||||
Assert.Equal("John", workflowState.Output["FirstName"]);
|
||||
Assert.Equal("Doe", workflowState.Output["LastName"]);
|
||||
Assert.Equal(30, workflowState.Output["Age"]);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "SetOutput handles dynamic output values")]
|
||||
public async Task SetOutput_Should_Handle_Dynamic_Values()
|
||||
{
|
||||
// Arrange
|
||||
await _services.PopulateRegistriesAsync();
|
||||
|
||||
// Act
|
||||
var workflowState = await _services.RunWorkflowUntilEndAsync<DynamicOutputValueWorkflow>();
|
||||
|
||||
// Assert
|
||||
Assert.Contains("Greeting", workflowState.Output.Keys);
|
||||
var greeting = workflowState.Output["Greeting"] as string;
|
||||
Assert.NotNull(greeting);
|
||||
Assert.StartsWith("Hello at ", greeting);
|
||||
}
|
||||
}
|
||||
|
||||
// Test Workflows
|
||||
|
||||
/// <summary>
|
||||
/// Basic workflow that uses SetOutput to set a workflow output
|
||||
/// </summary>
|
||||
public class BasicWorkflowOutputWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new SetOutput
|
||||
{
|
||||
OutputName = new("Message"),
|
||||
OutputValue = new("Hello, World!")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Workflow that sets multiple outputs using SetOutput
|
||||
/// </summary>
|
||||
public class MultipleOutputsWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new Sequence
|
||||
{
|
||||
Activities =
|
||||
{
|
||||
new SetOutput
|
||||
{
|
||||
OutputName = new("FirstName"),
|
||||
OutputValue = new("John")
|
||||
},
|
||||
new SetOutput
|
||||
{
|
||||
OutputName = new("LastName"),
|
||||
OutputValue = new("Doe")
|
||||
},
|
||||
new SetOutput
|
||||
{
|
||||
OutputName = new("Age"),
|
||||
OutputValue = new(30)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Workflow that uses dynamic values with SetOutput
|
||||
/// </summary>
|
||||
public class DynamicOutputValueWorkflow : WorkflowBase
|
||||
{
|
||||
protected override void Build(IWorkflowBuilder workflow)
|
||||
{
|
||||
workflow.Root = new SetOutput
|
||||
{
|
||||
OutputName = new("Greeting"),
|
||||
OutputValue = new(context => $"Hello at {DateTime.UtcNow:yyyy-MM-dd HH:mm}")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -11,15 +11,15 @@ namespace Elsa.Workflows.IntegrationTests.Scenarios.CompositesPassingData;
|
|||
/// </summary>
|
||||
public class AddTextSubWorkflow : Composite
|
||||
{
|
||||
public Input<string> A { get; set; } = default!;
|
||||
public Output<string> B { get; set; } = default!;
|
||||
public Input<string> A { get; set; } = null!;
|
||||
public Output<string> B { get; set; } = null!;
|
||||
|
||||
public AddTextSubWorkflow()
|
||||
{
|
||||
var setOutput = new SetOutput()
|
||||
{
|
||||
OutputName = new Input<string>("B"),
|
||||
OutputValue = new Input<object?>(context => "hi there " + A.Get(context))
|
||||
OutputName = new("B"),
|
||||
OutputValue = new(context => "hi there " + A.Get(context))
|
||||
};
|
||||
|
||||
Root = new Sequence
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows;
|
||||
using Elsa.Workflows.Management.Activities.SetOutput;
|
||||
|
||||
namespace Elsa.Activities.UnitTests.Composition;
|
||||
|
||||
public class SetOutputTests
|
||||
{
|
||||
private const string DefaultOutputName = "Result";
|
||||
|
||||
[Theory]
|
||||
[InlineData("test output")]
|
||||
[InlineData("string value")]
|
||||
[InlineData(42)]
|
||||
[InlineData(true)]
|
||||
[InlineData(3.14)]
|
||||
[InlineData("")]
|
||||
public async Task Should_Set_Workflow_Output_With_Value(object expectedValue)
|
||||
{
|
||||
// Act
|
||||
var context = await ExecuteSetOutputAsync(DefaultOutputName, expectedValue);
|
||||
|
||||
// Assert
|
||||
AssertOutputEquals(context, DefaultOutputName, expectedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Set_Workflow_Output_With_Null_Value()
|
||||
{
|
||||
// Act
|
||||
var context = await ExecuteSetOutputAsync(DefaultOutputName, null);
|
||||
|
||||
// Assert
|
||||
Assert.True(context.WorkflowExecutionContext.Output.ContainsKey(DefaultOutputName));
|
||||
Assert.Null(context.WorkflowExecutionContext.Output[DefaultOutputName]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Set_Output_With_Complex_Object()
|
||||
{
|
||||
// Arrange
|
||||
var expectedValue = new { Name = "Test", Value = 42 };
|
||||
|
||||
// Act
|
||||
var context = await ExecuteSetOutputAsync(DefaultOutputName, expectedValue);
|
||||
|
||||
// Assert
|
||||
AssertOutputEquals(context, DefaultOutputName, expectedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Update_Workflow_Output_Multiple_Times()
|
||||
{
|
||||
// Arrange
|
||||
const string outputName = "Counter";
|
||||
var firstValue = 1;
|
||||
var secondValue = 2;
|
||||
|
||||
// Act
|
||||
var context1 = await ExecuteSetOutputAsync(outputName, firstValue);
|
||||
var context2 = await ExecuteSetOutputAsync(outputName, secondValue,
|
||||
ctx => ctx.WorkflowExecutionContext.Output[outputName] = firstValue);
|
||||
|
||||
// Assert
|
||||
AssertOutputEquals(context1, outputName, firstValue);
|
||||
AssertOutputEquals(context2, outputName, secondValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Set_Different_Output_Names()
|
||||
{
|
||||
// Arrange
|
||||
const string output1Name = "FirstOutput";
|
||||
const string output2Name = "SecondOutput";
|
||||
const string value1 = "value1";
|
||||
const int value2 = 42;
|
||||
|
||||
// Act
|
||||
var context1 = await ExecuteSetOutputAsync(output1Name, value1);
|
||||
var context2 = await ExecuteSetOutputAsync(output2Name, value2,
|
||||
ctx => ctx.WorkflowExecutionContext.Output[output1Name] = value1);
|
||||
|
||||
// Assert
|
||||
AssertOutputEquals(context1, output1Name, value1);
|
||||
AssertOutputEquals(context2, output1Name, value1);
|
||||
AssertOutputEquals(context2, output2Name, value2);
|
||||
}
|
||||
|
||||
private static async Task<ActivityExecutionContext> ExecuteSetOutputAsync(
|
||||
string outputName,
|
||||
object? outputValue,
|
||||
Action<ActivityExecutionContext>? configureContext = null)
|
||||
{
|
||||
var setOutput = CreateSetOutputActivity(outputName, outputValue);
|
||||
var fixture = new ActivityTestFixture(setOutput);
|
||||
|
||||
if (configureContext != null)
|
||||
fixture.ConfigureContext(configureContext);
|
||||
|
||||
return await fixture.ExecuteAsync();
|
||||
}
|
||||
|
||||
private static SetOutput CreateSetOutputActivity(string outputName, object? outputValue) => new()
|
||||
{
|
||||
OutputName = new(outputName),
|
||||
OutputValue = new(outputValue)
|
||||
};
|
||||
|
||||
private static void AssertOutputEquals(ActivityExecutionContext context, string outputName, object? expectedValue)
|
||||
{
|
||||
var actualValue = context.WorkflowExecutionContext.Output[outputName];
|
||||
Assert.Equal(expectedValue, actualValue);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue