From e6df8ea954edb16ce1cbd7dcdad4d95b432d02a7 Mon Sep 17 00:00:00 2001 From: "lucas.hipolito" Date: Wed, 8 Oct 2025 14:59:59 +0200 Subject: [PATCH] More unit tests for set variable --- .../Helpers/ActivityTestHelper.cs | 3 +- .../Primitives/SetVariableTests.cs | 422 +++++++++++++++++- 2 files changed, 422 insertions(+), 3 deletions(-) diff --git a/test/unit/Elsa.Activities.UnitTests/Helpers/ActivityTestHelper.cs b/test/unit/Elsa.Activities.UnitTests/Helpers/ActivityTestHelper.cs index d5cf222fd..9b01d48f0 100644 --- a/test/unit/Elsa.Activities.UnitTests/Helpers/ActivityTestHelper.cs +++ b/test/unit/Elsa.Activities.UnitTests/Helpers/ActivityTestHelper.cs @@ -25,7 +25,7 @@ public static class ActivityTestHelper /// evaluating inputs, and executing the activity. /// /// The activity to execute - /// Task representing the async execution + /// The ActivityExecutionContext used for execution public static async Task ExecuteActivityAsync(IActivity activity) { var context = CreateMinimalActivityExecutionContext(activity, out var serviceProvider); @@ -35,6 +35,7 @@ public static class ActivityTestHelper await SetupInputValuesInMemoryAsync(activity, context, serviceProvider); await context.EvaluateInputPropertiesAsync(); await activity.ExecuteAsync(context); + return context; } diff --git a/test/unit/Elsa.Activities.UnitTests/Primitives/SetVariableTests.cs b/test/unit/Elsa.Activities.UnitTests/Primitives/SetVariableTests.cs index e5ccb3b13..f94ba1812 100644 --- a/test/unit/Elsa.Activities.UnitTests/Primitives/SetVariableTests.cs +++ b/test/unit/Elsa.Activities.UnitTests/Primitives/SetVariableTests.cs @@ -1,12 +1,14 @@ using Elsa.Activities.UnitTests.Helpers; using Elsa.Workflows; +using Elsa.Expressions.Models; +using System.Text.Json; namespace Elsa.Activities.UnitTests.Primitives; public class SetVariableTests { [Fact] - public async Task Should_Set_Variable() + public async Task Should_Set_Variable_Integer() { // Arrange var variable = new Variable("myVar", 0, "myVar"); @@ -21,7 +23,7 @@ public class SetVariableTests } [Fact] - public async Task Should_Set_Variable_From_Expression() + public async Task Should_Set_Variable_String() { // Arrange var variable = new Variable("myStringVar", "", "myStringVar"); @@ -34,4 +36,420 @@ public class SetVariableTests var result = variable.Get(context); Assert.Equal("Hello World", result); } + + [Fact] + public async Task Should_Overwrite_Existing_Variable() + { + // Arrange + var variable = new Variable("existingVar", 100, "inputId"); + var setVariable = new SetVariable(variable, new Input(200, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert - verify the original value was overwritten + var result = variable.Get(context); + Assert.Equal(200, result); + } + + [Fact] + public async Task Should_Assign_Null_Value() + { + // Arrange + var variable = new Variable("nullVar", "initial", "nullVar"); + var setVariable = new SetVariable(variable, new Input((string)null!, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Null(result); + } + + [Fact] + public async Task Should_Set_Variable_With_Special_Characters() + { + // Arrange + var variable = new Variable("special_var-123", "", "specialVar"); + const string specialValue = "Special chars: !@#$%^&*()_+-=[]{}|;':\",./<>?"; + var setVariable = new SetVariable(variable, new Input(specialValue, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal(specialValue, result); + } + + [Fact] + public async Task Should_Serialize_Complex_Object() + { + // Arrange + var complexObject = new ComplexTestObject + { + Id = 123, + Name = "Test Object", + Properties = new Dictionary + { + {"prop1", "value1"}, + {"prop2", 456}, + {"prop3", true} + }, + Items = ["item1", "item2", "item3"] + }; + + var variable = new Variable("complexVar", null!, "complexVar"); + var setVariable = new SetVariable(variable, new Input(complexObject, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.NotNull(result); + Assert.Equal(complexObject.Id, result.Id); + Assert.Equal(complexObject.Name, result.Name); + Assert.Equal(complexObject.Properties.Count, result.Properties.Count); + Assert.Equal(complexObject.Items.Length, result.Items.Length); + } + + [Fact] + public async Task Should_Assign_Large_Payload() + { + // Arrange + var largePayload = new string('A', 1024 * 1024); + var variable = new Variable("largeVar", "", "largeVar"); + var setVariable = new SetVariable(variable, new Input(largePayload, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal(largePayload.Length, result.Length); + Assert.Equal(largePayload, result); + } + + [Fact] + public async Task Should_Handle_Case_Sensitivity_On_Variable_Names() + { + // Arrange + var variable1 = new Variable("CaseSensitive", "value1", "var1"); + var variable2 = new Variable("casesensitive", "value2", "var2"); + + var setVariable1 = new SetVariable(variable1, new Input("updated1", "input1")); + var setVariable2 = new SetVariable(variable2, new Input("updated2", "input2")); + + // Act + var context1 = await ActivityTestHelper.ExecuteActivityAsync(setVariable1); + var context2 = await ActivityTestHelper.ExecuteActivityAsync(setVariable2); + + // Assert - Variables with different casing should be treated as separate + var result1 = variable1.Get(context1); + var result2 = variable2.Get(context2); + + Assert.Equal("updated1", result1); + Assert.Equal("updated2", result2); + } + + [Fact] + public async Task Should_Reassign_Variable_Multiple_Times() + { + // Arrange + var variable = new Variable("multiVar", 0, "multiVar"); + + // Act - Multiple assignments + var setVariable1 = new SetVariable(variable, new Input(10, "input1")); + var context1 = await ActivityTestHelper.ExecuteActivityAsync(setVariable1); + var result1 = variable.Get(context1); + + var setVariable2 = new SetVariable(variable, new Input(20, "input2")); + var context2 = await ActivityTestHelper.ExecuteActivityAsync(setVariable2); + var result2 = variable.Get(context2); + + var setVariable3 = new SetVariable(variable, new Input(30, "input3")); + var context3 = await ActivityTestHelper.ExecuteActivityAsync(setVariable3); + var result3 = variable.Get(context3); + + // Assert - Each execution should update the variable + Assert.Equal(10, result1); + Assert.Equal(20, result2); + Assert.Equal(30, result3); + } + + [Fact] + public async Task Should_Handle_Boolean_Values() + { + // Arrange + var variable = new Variable("boolVar", false, "boolVar"); + var setVariable = new SetVariable(variable, new Input(true, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.True(result); + } + + [Fact] + public async Task Should_Handle_DateTime_Values() + { + // Arrange + var testDate = new DateTime(2025, 10, 8, 14, 30, 0); + var variable = new Variable("dateVar", DateTime.MinValue, "dateVar"); + var setVariable = new SetVariable(variable, new Input(testDate, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal(testDate, result); + } + + [Fact] + public async Task Should_Handle_Decimal_Values() + { + // Arrange + var decimalValue = 123.456789m; + var variable = new Variable("decimalVar", 0m, "decimalVar"); + var setVariable = new SetVariable(variable, new Input(decimalValue, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal(decimalValue, result); + } + + [Fact] + public async Task Should_Handle_Array_Values() + { + // Arrange + var arrayValue = new[] { "item1", "item2", "item3" }; + var variable = new Variable("arrayVar", null!, "arrayVar"); + var setVariable = new SetVariable(variable, new Input(arrayValue, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.NotNull(result); + Assert.Equal(arrayValue.Length, result.Length); + Assert.Equal(arrayValue, result); + } + + [Fact] + public async Task Should_Handle_Dictionary_Values() + { + // Arrange + var dictionaryValue = new Dictionary + { + {"key1", "value1"}, + {"key2", 123}, + {"key3", true} + }; + var variable = new Variable>("dictVar", null!, "dictVar"); + var setVariable = new SetVariable>(variable, new Input>(dictionaryValue, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.NotNull(result); + Assert.Equal(dictionaryValue.Count, result.Count); + Assert.Equal(dictionaryValue["key1"], result["key1"]); + Assert.Equal(dictionaryValue["key2"], result["key2"]); + Assert.Equal(dictionaryValue["key3"], result["key3"]); + } + + [Fact] + public async Task Should_Evaluate_Variable_Name_Via_Expression() + { + // Arrange - Use an expression for the variable name + var dynamicVariableName = "dynamic_var_" + DateTime.Now.Ticks; + var variable = new Variable(dynamicVariableName, "", "dynamicVar"); + var setVariable = new SetVariable(variable, new Input("Dynamic Value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("Dynamic Value", result); + Assert.Equal(dynamicVariableName, variable.Name); + } + + [Fact] + public async Task Should_Evaluate_Value_Via_Expression() + { + // Arrange - Use a computed expression for the value + var computedValue = $"Computed at {DateTime.Now:yyyy-MM-dd HH:mm:ss}"; + var variable = new Variable("expressionVar", "", "expressionVar"); + var setVariable = new SetVariable(variable, new Input(computedValue, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal(computedValue, result); + Assert.Contains("Computed at", result); + } + + [Fact] + public async Task Should_Handle_Expression_That_Returns_Null() + { + // Arrange - Expression that evaluates to null + var variable = new Variable("nullExpressionVar", "initial", "nullExpressionVar"); + var setVariable = new SetVariable(variable, new Input((string)null!, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Null(result); + } + + [Fact] + public async Task Should_Handle_Undefined_Expression_Result() + { + // Arrange - Test handling of undefined/default values + var variable = new Variable("undefinedVar", null, "undefinedVar"); + var setVariable = new SetVariable(variable, new Input((int?)null, "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Null(result); + } + + [Fact] + public async Task Should_Handle_Zero_Length_Variable_Name() + { + // Arrange + var variable = new Variable(string.Empty, "test", "emptyNameVar"); + var setVariable = new SetVariable(variable, new Input("value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("value", result); + } + + [Fact] + public async Task Should_Handle_Unicode_Variable_Names() + { + // Arrange - Test with Unicode characters in variable names + var unicodeVariableName = "变量名_متغیر_переменная_🚀"; + var variable = new Variable(unicodeVariableName, "", "unicodeVar"); + var setVariable = new SetVariable(variable, new Input("Unicode Value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("Unicode Value", result); + Assert.Equal(unicodeVariableName, variable.Name); + } + + [Fact] + public async Task Should_Handle_Extremely_Long_Variable_Name() + { + // Arrange - Test with very long variable name + var longVariableName = new string('a', 1000); + var variable = new Variable(longVariableName, "", "longNameVar"); + var setVariable = new SetVariable(variable, new Input("Long Name Value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("Long Name Value", result); + Assert.Equal(1000, variable.Name.Length); + } + + [Fact] + public async Task Should_Handle_Numeric_Variable_Names() + { + // Arrange - Test with numeric variable names + var numericVariableName = "12345"; + var variable = new Variable(numericVariableName, "", "numericVar"); + var setVariable = new SetVariable(variable, new Input("Numeric Name Value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("Numeric Name Value", result); + Assert.Equal(numericVariableName, variable.Name); + } + + [Fact] + public async Task Should_Handle_Variable_Name_With_Spaces() + { + // Arrange - Test with spaces in variable names + var spacedVariableName = "variable with spaces"; + var variable = new Variable(spacedVariableName, "", "spacedVar"); + var setVariable = new SetVariable(variable, new Input("Spaced Name Value", "inputId")); + + // Act + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + + // Assert + var result = variable.Get(context); + Assert.Equal("Spaced Name Value", result); + Assert.Equal(spacedVariableName, variable.Name); + } + + [Fact] + public async Task Should_Handle_Concurrent_Variable_Updates() + { + // Arrange - Test thread safety with concurrent updates + var variable = new Variable("concurrentVar", 0, "concurrentVar"); + var tasks = new List>(); + + // Act - Create multiple concurrent assignments + for (int i = 1; i <= 10; i++) + { + var value = i; + tasks.Add(Task.Run(async () => + { + var setVariable = new SetVariable(variable, new Input(value, $"input{value}")); + var context = await ActivityTestHelper.ExecuteActivityAsync(setVariable); + return variable.Get(context); + })); + } + + var results = await Task.WhenAll(tasks); + + // Assert - All operations should complete successfully + Assert.Equal(10, results.Length); + Assert.All(results, result => Assert.True(result >= 1 && result <= 10)); + } +} + +/// +/// Complex test object for serialization testing +/// +public class ComplexTestObject +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public Dictionary Properties { get; set; } = new(); + public string[] Items { get; set; } = []; } \ No newline at end of file