diff --git a/test/unit/Elsa.Http.UnitTests/Extensions/StringExtensionsTests.cs b/test/unit/Elsa.Http.UnitTests/Extensions/StringExtensionsTests.cs new file mode 100644 index 000000000..fd3260332 --- /dev/null +++ b/test/unit/Elsa.Http.UnitTests/Extensions/StringExtensionsTests.cs @@ -0,0 +1,20 @@ +using Elsa.Extensions; + +namespace Elsa.Http.UnitTests.Extensions; + +public class StringExtensionsTests +{ + [Theory] + [InlineData("/api/users", "/api/users")] + [InlineData("api/users", "/api/users")] + [InlineData("/api/users/", "/api/users")] + [InlineData("api/users/", "/api/users")] + public void NormalizeRoute_VariousInputs_ReturnsNormalizedPath(string inputPath, string expectedPath) + { + // Act + var normalizedPath = inputPath.NormalizeRoute(); + + // Assert + Assert.Equal(expectedPath, normalizedPath); + } +} diff --git a/test/unit/Elsa.Workflows.Core.UnitTests/Services/ActivityRegistryTests.cs b/test/unit/Elsa.Workflows.Core.UnitTests/Services/ActivityRegistryTests.cs index 3f48e31dd..0ae94391f 100644 --- a/test/unit/Elsa.Workflows.Core.UnitTests/Services/ActivityRegistryTests.cs +++ b/test/unit/Elsa.Workflows.Core.UnitTests/Services/ActivityRegistryTests.cs @@ -1,5 +1,4 @@ using Elsa.Common.Multitenancy; -using Elsa.Workflows; using Elsa.Workflows.Models; using Microsoft.Extensions.Logging; using NSubstitute; @@ -14,42 +13,18 @@ public class ActivityRegistryTests private const string TestActivityType = "TestActivity"; private const string CurrentTenant = "tenant1"; - private readonly ITenantAccessor _tenantAccessor; - private readonly IActivityDescriber _activityDescriber; private readonly ILogger _logger; private readonly ActivityRegistry _registry; public ActivityRegistryTests() { - _tenantAccessor = Substitute.For(); - _activityDescriber = Substitute.For(); + var tenantAccessor = Substitute.For(); + var activityDescriber = Substitute.For(); _logger = Substitute.For>(); - _registry = new ActivityRegistry(_activityDescriber, Array.Empty(), _tenantAccessor, _logger); + _registry = new(activityDescriber, [], tenantAccessor, _logger); // Set default tenant for all tests - _tenantAccessor.TenantId.Returns(CurrentTenant); - } - - private ActivityDescriptor CreateDescriptor(string typeName, int version, string? tenantId) => - new() - { - TypeName = typeName, - Version = version, - TenantId = tenantId, - Kind = ActivityKind.Action - }; - - private void RegisterDescriptors(params ActivityDescriptor[] descriptors) - { - foreach (var descriptor in descriptors) - _registry.Register(descriptor); - } - - private static void AssertDescriptor(ActivityDescriptor? result, string? expectedTenantId, int expectedVersion) - { - Assert.NotNull(result); - Assert.Equal(expectedTenantId, result.TenantId); - Assert.Equal(expectedVersion, result.Version); + tenantAccessor.TenantId.Returns(CurrentTenant); } [Fact] @@ -162,8 +137,6 @@ public class ActivityRegistryTests public async Task RefreshDescriptorsAsync_CalledTwice_DoesNotLogWarnings() { // Arrange - var modifiers = Array.Empty(); - var mockProvider = Substitute.For(); var descriptor1 = new ActivityDescriptor { @@ -186,9 +159,9 @@ public class ActivityRegistryTests }; mockProvider.GetDescriptorsAsync(Arg.Any()) - .ReturnsAsync(new[] { descriptor1, descriptor2 }); - - var providers = new[] { mockProvider.Object }; + .Returns(new ValueTask>([descriptor1, descriptor2])); + + var providers = new[] { mockProvider }; // Act - First refresh await _registry.RefreshDescriptorsAsync(providers); @@ -200,7 +173,7 @@ public class ActivityRegistryTests _logger.DidNotReceive().Log( LogLevel.Warning, Arg.Any(), - Arg.Is((v, t) => v.ToString()!.Contains("was already registered")), + Arg.Is(v => v.ToString()!.Contains("was already registered")), Arg.Any(), Arg.Any>()); @@ -215,8 +188,6 @@ public class ActivityRegistryTests public async Task RefreshDescriptorsAsync_PreservesManualDescriptors() { // Arrange - var modifiers = Array.Empty(); - // Create a manual descriptor var manualDescriptor = new ActivityDescriptor { @@ -243,9 +214,9 @@ public class ActivityRegistryTests }; mockProvider.GetDescriptorsAsync(Arg.Any()) - .ReturnsAsync(new[] { providerDescriptor }); - - var providers = new[] { mockProvider.Object }; + .Returns(new ValueTask>([providerDescriptor])); + + var providers = new[] { mockProvider }; // Act - Refresh with provider await _registry.RefreshDescriptorsAsync(providers); @@ -260,7 +231,7 @@ public class ActivityRegistryTests _logger.DidNotReceive().Log( LogLevel.Warning, Arg.Any(), - Arg.Is((v, t) => v.ToString()!.Contains("ManualActivity")), + Arg.Is(v => v.ToString()!.Contains("ManualActivity")), Arg.Any(), Arg.Any>()); } @@ -269,12 +240,7 @@ public class ActivityRegistryTests public async Task RefreshDescriptorsAsync_LogsWarning_WhenDifferentProvidersRegisterSameActivity() { // Arrange - var modifiers = Array.Empty(); - // Create two different providers with the same activity - var mockProvider1 = Substitute.For(); - var mockProvider2 = Substitute.For(); - var descriptor1 = new ActivityDescriptor { TypeName = "DuplicateActivity", @@ -284,7 +250,7 @@ public class ActivityRegistryTests Description = "From Provider 1", IsBrowsable = true }; - + var descriptor2 = new ActivityDescriptor { TypeName = "DuplicateActivity", @@ -294,24 +260,53 @@ public class ActivityRegistryTests Description = "From Provider 2", IsBrowsable = true }; - - mockProvider1.GetDescriptorsAsync(Arg.Any()) - .ReturnsAsync(new[] { descriptor1 }); - - mockProvider2.GetDescriptorsAsync(Arg.Any()) - .ReturnsAsync(new[] { descriptor2 }); - - var providers = new[] { mockProvider1.Object, mockProvider2.Object }; - + + var provider1 = new Provider1([descriptor1]); + var provider2 = new Provider2([descriptor2]); + var providers = new IActivityProvider[] { provider1, provider2 }; + // Act await _registry.RefreshDescriptorsAsync(providers); - + // Assert - Should log a warning for the duplicate _logger.Received(1).Log( LogLevel.Warning, Arg.Any(), - Arg.Is((v, t) => v.ToString()!.Contains("DuplicateActivity") && v.ToString()!.Contains("was already registered")), + Arg.Is(v => v.ToString()!.Contains("DuplicateActivity") && v.ToString()!.Contains("was already registered")), Arg.Any(), Arg.Any>()); } + + + private ActivityDescriptor CreateDescriptor(string typeName, int version, string? tenantId) => + new() + { + TypeName = typeName, + Version = version, + TenantId = tenantId, + Kind = ActivityKind.Action + }; + + private void RegisterDescriptors(params ActivityDescriptor[] descriptors) + { + foreach (var descriptor in descriptors) + _registry.Register(descriptor); + } + + private static void AssertDescriptor(ActivityDescriptor? result, string? expectedTenantId, int expectedVersion) + { + Assert.NotNull(result); + Assert.Equal(expectedTenantId, result.TenantId); + Assert.Equal(expectedVersion, result.Version); + } + private sealed class Provider1(IEnumerable descriptors) : IActivityProvider + { + public ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) => new(descriptors); + } + + private sealed class Provider2(IEnumerable descriptors) : IActivityProvider + { + public ValueTask> GetDescriptorsAsync(CancellationToken cancellationToken = default) => new(descriptors); + } + } \ No newline at end of file