using FluentAssertions; using StellaOps.Microservice; using StellaOps.Router.Common.Models; using Xunit; namespace StellaOps.Microservice.Tests; public class EndpointRegistryTests { private static EndpointDescriptor CreateEndpoint(string method, string path, Type? handlerType = null) { return new EndpointDescriptor { ServiceName = "test-service", Version = "1.0.0", Method = method, Path = path, HandlerType = handlerType }; } [Fact] public void TryMatch_ExactMatch_ReturnsEndpoint() { var registry = new EndpointRegistry(); var endpoint = CreateEndpoint("GET", "/api/users"); registry.Register(endpoint); var result = registry.TryMatch("GET", "/api/users", out var match); result.Should().BeTrue(); match.Should().NotBeNull(); match!.Endpoint.Should().Be(endpoint); match.PathParameters.Should().BeEmpty(); } [Fact] public void TryMatch_MethodMismatch_ReturnsFalse() { var registry = new EndpointRegistry(); registry.Register(CreateEndpoint("GET", "/api/users")); var result = registry.TryMatch("POST", "/api/users", out var match); result.Should().BeFalse(); match.Should().BeNull(); } [Fact] public void TryMatch_PathMismatch_ReturnsFalse() { var registry = new EndpointRegistry(); registry.Register(CreateEndpoint("GET", "/api/users")); var result = registry.TryMatch("GET", "/api/products", out var match); result.Should().BeFalse(); match.Should().BeNull(); } [Fact] public void TryMatch_WithPathParameter_ExtractsParameter() { var registry = new EndpointRegistry(); registry.Register(CreateEndpoint("GET", "/api/users/{id}")); var result = registry.TryMatch("GET", "/api/users/123", out var match); result.Should().BeTrue(); match.Should().NotBeNull(); match!.PathParameters.Should().ContainKey("id"); match.PathParameters["id"].Should().Be("123"); } [Fact] public void TryMatch_MethodCaseInsensitive_ReturnsMatch() { var registry = new EndpointRegistry(); registry.Register(CreateEndpoint("GET", "/api/users")); var result = registry.TryMatch("get", "/api/users", out var match); result.Should().BeTrue(); match.Should().NotBeNull(); } [Fact] public void TryMatch_PathCaseInsensitive_ReturnsMatch() { var registry = new EndpointRegistry(); registry.Register(CreateEndpoint("GET", "/api/users")); var result = registry.TryMatch("GET", "/API/USERS", out var match); result.Should().BeTrue(); match.Should().NotBeNull(); } [Fact] public void RegisterAll_MultipeEndpoints_AllRegistered() { var registry = new EndpointRegistry(); var endpoints = new[] { CreateEndpoint("GET", "/api/users"), CreateEndpoint("POST", "/api/users"), CreateEndpoint("GET", "/api/users/{id}") }; registry.RegisterAll(endpoints); registry.GetAllEndpoints().Should().HaveCount(3); } [Fact] public void GetAllEndpoints_ReturnsAllRegistered() { var registry = new EndpointRegistry(); var endpoint1 = CreateEndpoint("GET", "/api/users"); var endpoint2 = CreateEndpoint("POST", "/api/users"); registry.Register(endpoint1); registry.Register(endpoint2); var all = registry.GetAllEndpoints(); all.Should().HaveCount(2); all.Should().Contain(endpoint1); all.Should().Contain(endpoint2); } [Fact] public void TryMatch_FirstMatchWins_WhenMultiplePossible() { var registry = new EndpointRegistry(); var endpoint1 = CreateEndpoint("GET", "/api/users/{id}"); var endpoint2 = CreateEndpoint("GET", "/api/{resource}/{id}"); registry.Register(endpoint1); registry.Register(endpoint2); var result = registry.TryMatch("GET", "/api/users/123", out var match); result.Should().BeTrue(); match.Should().NotBeNull(); // First registered endpoint should match match!.Endpoint.Should().Be(endpoint1); } [Fact] public void TryMatch_EmptyRegistry_ReturnsFalse() { var registry = new EndpointRegistry(); var result = registry.TryMatch("GET", "/api/users", out var match); result.Should().BeFalse(); match.Should().BeNull(); } [Fact] public void Constructor_CaseSensitive_RespectsSetting() { var registry = new EndpointRegistry(caseInsensitive: false); registry.Register(CreateEndpoint("GET", "/api/users")); var result = registry.TryMatch("GET", "/API/USERS", out var match); result.Should().BeFalse(); } }