diff --git a/src/modules/Elsa.Workflows.Core/Services/PropertyUIHandlerResolver.cs b/src/modules/Elsa.Workflows.Core/Services/PropertyUIHandlerResolver.cs index 12feb3cab..17801185c 100644 --- a/src/modules/Elsa.Workflows.Core/Services/PropertyUIHandlerResolver.cs +++ b/src/modules/Elsa.Workflows.Core/Services/PropertyUIHandlerResolver.cs @@ -1,5 +1,6 @@ using System.Reflection; using Elsa.Workflows.Attributes; +using Elsa.Workflows.Models; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows; @@ -24,9 +25,12 @@ public class PropertyUIHandlerResolver(IServiceScopeFactory scopeFactory) : IPro using var scope = scopeFactory.CreateScope(); var uiHintHandlers = scope.ServiceProvider.GetServices(); - if (!string.IsNullOrWhiteSpace(inputAttribute?.UIHint)) + var isWrapperProperty = typeof(Input).IsAssignableFrom(propertyInfo.PropertyType); + var wrapperPropertyType = !isWrapperProperty ? propertyInfo.PropertyType : propertyInfo.PropertyType.GenericTypeArguments[0]; + var uiHint = ActivityDescriber.GetUIHint(wrapperPropertyType, inputAttribute); + if (!string.IsNullOrWhiteSpace(uiHint)) { - var uiHintHandler = uiHintHandlers.FirstOrDefault(x => x.UIHint == inputAttribute.UIHint); + var uiHintHandler = uiHintHandlers.FirstOrDefault(x => x.UIHint == uiHint); if (uiHintHandler != null) { diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/ActivityUIHintDescriberTests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/ActivityUIHintDescriberTests.cs new file mode 100644 index 000000000..d462e47dc --- /dev/null +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/ActivityUIHintDescriberTests.cs @@ -0,0 +1,60 @@ +using Elsa.Expressions.Models; +using Elsa.Extensions; +using Elsa.Testing.Shared; +using Elsa.Workflows.Memory; +using Microsoft.Extensions.DependencyInjection; +using Xunit.Abstractions; +using Elsa.Workflows.UIHints; +using Elsa.Workflows.UIHints.Dropdown; + +namespace Elsa.Workflows.Core.UnitTests; + +public class Tests +{ + private readonly CapturingTextWriter _capturingTextWriter = new(); + private readonly IServiceProvider _services; + + /// + /// Initializes a new instance of the class. + /// + public Tests(ITestOutputHelper testOutputHelper) + { + _services = new TestApplicationBuilder(testOutputHelper) + .WithCapturingTextWriter(_capturingTextWriter) + .ConfigureElsa(elsa => + { + elsa.AddActivity(); + }) + .Build(); + } + + [Fact(DisplayName = "Enum input types get a dropdown UIHint by default")] + public async Task Test1() + { + var activityDescriber = _services.GetRequiredService(); + + var description = await activityDescriber.DescribeActivityAsync(typeof(TestActivity)); + + var inputDescription = description.Inputs.First(); + Assert.Equal(InputUIHints.DropDown, inputDescription.UIHint); + } + + [Fact(DisplayName = "Enum input types get a dropdown UIHint by default")] + public async Task Test2() + { + var activityDescriber = _services.GetRequiredService(); + + var description = await activityDescriber.DescribeActivityAsync(typeof(TestActivity)); + + var inputDescription = description.Inputs.First(); + Assert.True(inputDescription.UISpecifications.ContainsKey(InputUIHints.DropDown)); + Assert.True(inputDescription.UISpecifications[InputUIHints.DropDown] is DropDownProps); + var dropDownProperties = (DropDownProps) inputDescription.UISpecifications[InputUIHints.DropDown]; + + Assert.Collection(dropDownProperties.SelectList.Items, + item => { Assert.Equal("OptionsAreNice", item.Text); Assert.Equal("OptionsAreNice", item.Value); }, + item => { Assert.Equal("ToHave", item.Text); Assert.Equal("ToHave", item.Value); }, + item => { Assert.Equal("IfYouCanChooseThem", item.Text); Assert.Equal("IfYouCanChooseThem", item.Value); }); + } + +} diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestActivity.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestActivity.cs new file mode 100644 index 000000000..c09148b2d --- /dev/null +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestActivity.cs @@ -0,0 +1,29 @@ +using Elsa.Workflows.Attributes; +using System.Text.Json.Serialization; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Elsa.Workflows.Models; + +namespace Elsa.Workflows.Core.UnitTests; + +/// +/// Write a line of text to the console. +/// +[Activity("Elsa", "Test", "Used in Testing - not a real activity")] +public class TestActivity : CodeActivity +{ + /// + /// The text to write. + /// + [Description("The text to write.")] + public Input Option { get; set; } = default!; + + [JsonConstructor] + private TestActivity(string? source = default, int? line = default) : base(source, line) + { + } + /// + public TestActivity(Input option, [CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : this(source, line) => Option = option; + + +} diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestEnumType.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestEnumType.cs new file mode 100644 index 000000000..e991a604c --- /dev/null +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/UIHintSerializiation/TestEnumType.cs @@ -0,0 +1,8 @@ +namespace Elsa.Workflows.Core.UnitTests; + +public enum TestEnumType +{ + OptionsAreNice, + ToHave, + IfYouCanChooseThem +}