From 8a1c898bf7edc3300f890816d8f9a12592a4b61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20Malini=C4=87?= <94437690+boma96@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:07:57 +0200 Subject: [PATCH] Add support for default values (#153) * Support default values * Add support for specifying default values --- .../Builders/WorkflowDefinitionBuilder.cs | 3 +- .../Util/DefaultValueAttribute.cs | 12 ++++ .../ConductorSharp.Engine.Tests.csproj | 2 + .../Integration/WorkflowBuilderTests.cs | 12 ++++ .../Samples/Workflows/DefaultValueWorkflow.cs | 32 ++++++++++ .../Workflows/DefaultValueWorkflow.json | 58 +++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/ConductorSharp.Engine/Util/DefaultValueAttribute.cs create mode 100644 test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.cs create mode 100644 test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.json diff --git a/src/ConductorSharp.Engine/Builders/WorkflowDefinitionBuilder.cs b/src/ConductorSharp.Engine/Builders/WorkflowDefinitionBuilder.cs index f821a60a..c95bf07b 100644 --- a/src/ConductorSharp.Engine/Builders/WorkflowDefinitionBuilder.cs +++ b/src/ConductorSharp.Engine/Builders/WorkflowDefinitionBuilder.cs @@ -108,6 +108,7 @@ public WorkflowDefinition Build() foreach (var prop in props) { var isRequired = prop.GetCustomAttribute(); + var defaultValue = prop.GetCustomAttribute()?.DefaultValue ?? string.Empty; var description = prop.GetDocSection("summary"); var propertyName = NamingUtil.GetParameterName(prop); @@ -116,7 +117,7 @@ public WorkflowDefinition Build() BuildContext.Inputs.Add( new JProperty( propertyName, - new JObject { new JProperty("value", ""), new JProperty("description", $"{description} {requiredString}"), } + new JObject { new JProperty("value", defaultValue), new JProperty("description", $"{description} {requiredString}"), } ) ); } diff --git a/src/ConductorSharp.Engine/Util/DefaultValueAttribute.cs b/src/ConductorSharp.Engine/Util/DefaultValueAttribute.cs new file mode 100644 index 00000000..c76561f6 --- /dev/null +++ b/src/ConductorSharp.Engine/Util/DefaultValueAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConductorSharp.Engine.Util +{ + [AttributeUsage(AttributeTargets.Property)] + public class DefaultValueAttribute : Attribute + { + internal object DefaultValue { get; } + + public DefaultValueAttribute(object defaultValue) => DefaultValue = defaultValue; + } +} diff --git a/test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csproj b/test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csproj index 9a7ed0aa..0ca7320f 100644 --- a/test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csproj +++ b/test/ConductorSharp.Engine.Tests/ConductorSharp.Engine.Tests.csproj @@ -15,6 +15,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/test/ConductorSharp.Engine.Tests/Integration/WorkflowBuilderTests.cs b/test/ConductorSharp.Engine.Tests/Integration/WorkflowBuilderTests.cs index d146e288..d6bf933a 100644 --- a/test/ConductorSharp.Engine.Tests/Integration/WorkflowBuilderTests.cs +++ b/test/ConductorSharp.Engine.Tests/Integration/WorkflowBuilderTests.cs @@ -49,6 +49,7 @@ public WorkflowBuilderTests() _containerBuilder.RegisterWorkflow(); _containerBuilder.RegisterWorkflow(); _containerBuilder.RegisterWorkflow(); + _containerBuilder.RegisterWorkflow(); _container = _containerBuilder.Build(); } @@ -236,6 +237,7 @@ public void BuilderReturnsCorrectDefinitionHumanWorkflow() Assert.Equal(expectedDefinition, definition); } + [Fact] public void BuilderReturnsCorrectDefinitionWaitTaskWorkflow() { var definition = GetDefinitionFromWorkflow(); @@ -244,6 +246,7 @@ public void BuilderReturnsCorrectDefinitionWaitTaskWorkflow() Assert.Equal(expectedDefinition, definition); } + [Fact] public void BuilderReturnsCorrectDefinitionIndexerWorkflow() { var definition = GetDefinitionFromWorkflow(); @@ -252,6 +255,15 @@ public void BuilderReturnsCorrectDefinitionIndexerWorkflow() Assert.Equal(expectedDefinition, definition); } + [Fact] + public void BuilderReturnsCorrectDefinitionDefaultValueWorkflow() + { + var definition = GetDefinitionFromWorkflow(); + var expectedDefinition = EmbeddedFileHelper.GetLinesFromEmbeddedFile("~/Samples/Workflows/DefaultValueWorkflow.json"); + + Assert.Equal(expectedDefinition, definition); + } + private string GetDefinitionFromWorkflow() where TNameable : INameable { var workflow = _container.Resolve>().First(a => a.Name == NamingUtil.NameOf()); diff --git a/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.cs b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.cs new file mode 100644 index 00000000..40570036 --- /dev/null +++ b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConductorSharp.Engine.Tests.Samples.Workflows +{ + public class DefaultValueWorkflowInput : WorkflowInput + { + [DefaultValue("Default name")] + public string Name { get; set; } + + [DefaultValue("Default address")] + public string Address { get; set; } + } + + public class DefaultValueWorkflowOutput : WorkflowOutput { } + + public class DefaultValueWorkflow : Workflow + { + public EmailPrepareV1 PrepareEmail { get; set; } + + public DefaultValueWorkflow(WorkflowDefinitionBuilder builder) + : base(builder) { } + + public override void BuildDefinition() + { + _builder.AddTask(wf => wf.PrepareEmail, wf => new() { Name = wf.WorkflowInput.Name, Address = wf.WorkflowInput.Address }); + } + } +} diff --git a/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.json b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.json new file mode 100644 index 00000000..afd68817 --- /dev/null +++ b/test/ConductorSharp.Engine.Tests/Samples/Workflows/DefaultValueWorkflow.json @@ -0,0 +1,58 @@ +{ + "ownerApp": null, + "createTime": 0, + "updateTime": 0, + "createdBy": null, + "updatedBy": null, + "name": "default_value_workflow", + "description": "{\"description\":null,\"labels\":null}", + "version": 1, + "tasks": [ + { + "queryExpression": null, + "name": "EMAIL_prepare", + "taskReferenceName": "prepare_email", + "description": "{\"description\":null}", + "inputParameters": { + "name": "${workflow.input.name}", + "address": "${workflow.input.address}" + }, + "type": "SIMPLE", + "dynamicTaskNameParam": null, + "caseValueParam": null, + "caseExpression": null, + "expression": null, + "evaluatorType": null, + "scriptExpression": null, + "decisionCases": null, + "dynamicForkJoinTasksParam": null, + "dynamicForkTasksParam": null, + "dynamicForkTasksInputParamName": null, + "defaultCase": null, + "forkTasks": null, + "startDelay": 0, + "subWorkflowParam": null, + "joinOn": null, + "sink": null, + "optional": false, + "taskDefinition": null, + "rateLimited": false, + "defaultExclusiveJoinTask": null, + "asyncComplete": false, + "loopCondition": null, + "loopOver": null + } + ], + "inputParameters": [ + "{\"name\":{\"value\":\"Default name\",\"description\":\" (optional)\"},\"address\":{\"value\":\"Default address\",\"description\":\" (optional)\"}}" + ], + "outputParameters": null, + "failureWorkflow": null, + "schemaVersion": 2, + "restartable": true, + "workflowStatusListenerEnabled": true, + "ownerEmail": null, + "timeoutPolicy": null, + "timeoutSeconds": 0, + "variables": null +} \ No newline at end of file