From 36ecb8958700169cd1733fb718eb9881a4f6e0de Mon Sep 17 00:00:00 2001 From: Matthias Gernand Date: Fri, 24 May 2024 09:24:33 +0200 Subject: [PATCH] Re-factored the endpoint group naming. (#10) --- README.md | 2 +- .../Endpoints/Customers/GetCustomer.cs | 3 +- .../Endpoints/Customers/GetCustomers.cs | 3 +- .../Endpoints/GetDiagnostics.cs | 23 ++++++ .../WeatherForecast/GetWeatherForecasts.cs | 5 +- samples/SampleApplication/Program.cs | 3 + .../SampleApplication.csproj | 4 +- .../appsettings.Development.json | 4 +- src/AspNetCore.Endpoints/EndpointBase.cs | 21 ------ src/AspNetCore.Endpoints/EndpointGroup.cs | 67 ------------------ ...Attribute.cs => EndpointGroupAttribute.cs} | 14 ++-- .../EndpointNameAttribute.cs | 8 ++- .../EndpointRouteBuilderExtensions.cs | 70 +++++++++---------- .../ServiceCollectionExtensions.cs | 42 +++++------ src/Directory.Build.props | 2 +- .../AspNetCore.Endpoints.UnitTests.csproj | 8 +-- .../EndpointGroupTests.cs | 43 ------------ .../EndpointRouteBuilderExtensionsTests.cs | 1 + .../EndpointTests.cs | 32 --------- .../EmptyGroupNameFromAttribute.cs | 30 -------- .../AnotherGroup/GroupNameFromAttribute.cs | 30 -------- .../AnotherGroup/GroupNameFromNamespace.cs | 29 -------- .../Endpoints/Customers/GetCustomer.cs | 3 +- .../Endpoints/Customers/GetCustomers.cs | 3 +- .../Endpoints/TopLevelEndpoint.cs | 13 ++++ .../EndpointsAutoRegistrationTests.cs | 1 + .../EndpointsOptionsTests.cs | 5 +- .../GlobalUsings.cs | 1 - .../TestServerFixtureBase.cs | 5 +- 29 files changed, 135 insertions(+), 340 deletions(-) create mode 100644 samples/SampleApplication/Endpoints/GetDiagnostics.cs delete mode 100644 src/AspNetCore.Endpoints/EndpointGroup.cs rename src/AspNetCore.Endpoints/{EndpointGroupNameAttribute.cs => EndpointGroupAttribute.cs} (64%) delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/EndpointGroupTests.cs delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/EndpointTests.cs delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/EmptyGroupNameFromAttribute.cs delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromAttribute.cs delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromNamespace.cs create mode 100644 tests/AspNetCore.Endpoints.UnitTests/Endpoints/TopLevelEndpoint.cs delete mode 100644 tests/AspNetCore.Endpoints.UnitTests/GlobalUsings.cs diff --git a/README.md b/README.md index c2028ea..1dd376b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ the endppoint name id the class name of the endpoint. This default conventions can be overridden by using attributes athe endpoints class level. -- ```[EndpointGroupName("GroupName")]``` +- ```[EndpointGroup("GroupName")]``` The name of the group this endpoint belongs to. diff --git a/samples/SampleApplication/Endpoints/Customers/GetCustomer.cs b/samples/SampleApplication/Endpoints/Customers/GetCustomer.cs index 26e498b..eae9955 100644 --- a/samples/SampleApplication/Endpoints/Customers/GetCustomer.cs +++ b/samples/SampleApplication/Endpoints/Customers/GetCustomer.cs @@ -4,13 +4,14 @@ using MadEyeMatt.AspNetCore.Endpoints; [PublicAPI] + [EndpointGroup("Customers")] public sealed class GetCustomer : EndpointBase { /// public override void Map(IEndpointRouteBuilder endpoints) { endpoints - .MapGet(this.Execute, "{id}") + .MapGet(this.Execute, "customers/{id}") .Produces(200, "application/json"); } diff --git a/samples/SampleApplication/Endpoints/Customers/GetCustomers.cs b/samples/SampleApplication/Endpoints/Customers/GetCustomers.cs index 50e2f6b..37f9687 100644 --- a/samples/SampleApplication/Endpoints/Customers/GetCustomers.cs +++ b/samples/SampleApplication/Endpoints/Customers/GetCustomers.cs @@ -4,13 +4,14 @@ using MadEyeMatt.AspNetCore.Endpoints; [PublicAPI] + [EndpointGroup("Customers")] public sealed class GetCustomers : EndpointBase { /// public override void Map(IEndpointRouteBuilder endpoints) { endpoints - .MapGet(this.Execute) + .MapGet(this.Execute, "customers") .Produces(200, "application/json"); } diff --git a/samples/SampleApplication/Endpoints/GetDiagnostics.cs b/samples/SampleApplication/Endpoints/GetDiagnostics.cs new file mode 100644 index 0000000..5028f73 --- /dev/null +++ b/samples/SampleApplication/Endpoints/GetDiagnostics.cs @@ -0,0 +1,23 @@ +namespace SampleApplication.Endpoints +{ + using JetBrains.Annotations; + using MadEyeMatt.AspNetCore.Endpoints; + + [PublicAPI] + [EndpointGroup("Diagnostics")] + public sealed class GetDiagnostics : EndpointBase + { + /// + public override void Map(IEndpointRouteBuilder endpoints) + { + endpoints + .MapGet(this.Execute, "diag") + .Produces(200, "application/json"); + } + + public async Task Execute(HttpContext httpContext) + { + return Results.Ok("Diagnostics"); + } + } +} diff --git a/samples/SampleApplication/Endpoints/WeatherForecast/GetWeatherForecasts.cs b/samples/SampleApplication/Endpoints/WeatherForecast/GetWeatherForecasts.cs index f6dc84f..a3af092 100644 --- a/samples/SampleApplication/Endpoints/WeatherForecast/GetWeatherForecasts.cs +++ b/samples/SampleApplication/Endpoints/WeatherForecast/GetWeatherForecasts.cs @@ -4,8 +4,7 @@ using MadEyeMatt.AspNetCore.Endpoints; [PublicAPI] - [EndpointName("SomeOtherName")] - [EndpointGroupName("weather_forecast")] + [EndpointName("Weather")] public sealed class GetWeatherForecasts : EndpointBase { private string[] summaries = new string[] @@ -16,7 +15,7 @@ public sealed class GetWeatherForecasts : EndpointBase /// public override void Map(IEndpointRouteBuilder endpoints) { - endpoints.MapGet(this.Execute); + endpoints.MapGet(this.Execute, "weather"); } public async Task> Execute(HttpContext httpContext) diff --git a/samples/SampleApplication/Program.cs b/samples/SampleApplication/Program.cs index 1d7bb06..237dead 100644 --- a/samples/SampleApplication/Program.cs +++ b/samples/SampleApplication/Program.cs @@ -9,6 +9,9 @@ public static void Main(string[] args) { WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + // Add the endpoints as services. + builder.Services.AddEndpoints(); + // Add services to the container. builder.Services.AddAuthorization(); diff --git a/samples/SampleApplication/SampleApplication.csproj b/samples/SampleApplication/SampleApplication.csproj index b281817..261656d 100644 --- a/samples/SampleApplication/SampleApplication.csproj +++ b/samples/SampleApplication/SampleApplication.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/SampleApplication/appsettings.Development.json b/samples/SampleApplication/appsettings.Development.json index a34cd70..680eddb 100644 --- a/samples/SampleApplication/appsettings.Development.json +++ b/samples/SampleApplication/appsettings.Development.json @@ -1,8 +1,8 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Debug", + "Microsoft.AspNetCore": "Debug" } } } diff --git a/src/AspNetCore.Endpoints/EndpointBase.cs b/src/AspNetCore.Endpoints/EndpointBase.cs index 791b90e..350c4c4 100644 --- a/src/AspNetCore.Endpoints/EndpointBase.cs +++ b/src/AspNetCore.Endpoints/EndpointBase.cs @@ -1,8 +1,5 @@ namespace MadEyeMatt.AspNetCore.Endpoints { - using System; - using System.Linq; - using System.Reflection; using JetBrains.Annotations; using Microsoft.AspNetCore.Routing; @@ -12,24 +9,6 @@ [PublicAPI] public abstract class EndpointBase : IEndpoint { - /// - /// Initializes a new instance of the type. - /// - protected EndpointBase() - { - Type groupType = this.GetType(); - - string groupName = groupType.GetCustomAttribute()?.GroupName?.Trim() ?? - groupType.Namespace?.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Last(); - - this.Group = new EndpointGroup(groupName); - } - - /// - /// Gets the endpoint group. - /// - public EndpointGroup Group { get; } - /// /// Maps the endpoint. /// diff --git a/src/AspNetCore.Endpoints/EndpointGroup.cs b/src/AspNetCore.Endpoints/EndpointGroup.cs deleted file mode 100644 index 550576e..0000000 --- a/src/AspNetCore.Endpoints/EndpointGroup.cs +++ /dev/null @@ -1,67 +0,0 @@ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - -namespace MadEyeMatt.AspNetCore.Endpoints -{ - using System; - using JetBrains.Annotations; - - /// - /// A named endpoint group. - /// - [PublicAPI] - public sealed class EndpointGroup : IEquatable - { - /// - /// Initializes a new instance of the type. - /// - /// - public EndpointGroup(string groupName) - { -#if NET7_0 - if (string.IsNullOrWhiteSpace(groupName)) - { - throw new ArgumentException(nameof(groupName)); - } -#else - ArgumentException.ThrowIfNullOrWhiteSpace(groupName); -#endif - - this.Name = groupName; - } - - /// - /// Gets the group groupName. - /// - public string Name { get; } - - /// - public bool Equals(EndpointGroup other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return string.Equals(this.Name, other.Name, StringComparison.InvariantCultureIgnoreCase); - } - - /// - public override bool Equals(object obj) - { - return ReferenceEquals(this, obj) || obj is EndpointGroup other && this.Equals(other); - } - - /// - public override int GetHashCode() - { - return (this.Name != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(this.Name) : 0); - } - - public static bool operator ==(EndpointGroup left, EndpointGroup right) - { - return Equals(left, right); - } - - public static bool operator !=(EndpointGroup left, EndpointGroup right) - { - return !Equals(left, right); - } - } -} \ No newline at end of file diff --git a/src/AspNetCore.Endpoints/EndpointGroupNameAttribute.cs b/src/AspNetCore.Endpoints/EndpointGroupAttribute.cs similarity index 64% rename from src/AspNetCore.Endpoints/EndpointGroupNameAttribute.cs rename to src/AspNetCore.Endpoints/EndpointGroupAttribute.cs index 0fd9011..5f0243d 100644 --- a/src/AspNetCore.Endpoints/EndpointGroupNameAttribute.cs +++ b/src/AspNetCore.Endpoints/EndpointGroupAttribute.cs @@ -8,20 +8,22 @@ /// [PublicAPI] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] - public sealed class EndpointGroupNameAttribute : Attribute + public sealed class EndpointGroupAttribute : Attribute { /// - /// Initializes a new instance of the type. + /// Initializes a new instance of the type. /// - /// - public EndpointGroupNameAttribute(string groupName) + /// + public EndpointGroupAttribute(string group) { - this.GroupName = groupName; + ArgumentException.ThrowIfNullOrEmpty(group); + + this.Group = group; } /// /// Gets the group name. /// - public string GroupName { get; } + public string Group { get; } } } \ No newline at end of file diff --git a/src/AspNetCore.Endpoints/EndpointNameAttribute.cs b/src/AspNetCore.Endpoints/EndpointNameAttribute.cs index c7f5310..012956a 100644 --- a/src/AspNetCore.Endpoints/EndpointNameAttribute.cs +++ b/src/AspNetCore.Endpoints/EndpointNameAttribute.cs @@ -13,10 +13,12 @@ public sealed class EndpointNameAttribute : Attribute /// /// Initializes a new instance of the type. /// - /// - public EndpointNameAttribute(string handlerName) + /// + public EndpointNameAttribute(string name) { - this.Name = handlerName; + ArgumentException.ThrowIfNullOrEmpty(name); + + this.Name = name; } /// diff --git a/src/AspNetCore.Endpoints/EndpointRouteBuilderExtensions.cs b/src/AspNetCore.Endpoints/EndpointRouteBuilderExtensions.cs index efe7b79..0509fbf 100644 --- a/src/AspNetCore.Endpoints/EndpointRouteBuilderExtensions.cs +++ b/src/AspNetCore.Endpoints/EndpointRouteBuilderExtensions.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; + using System.Runtime.CompilerServices; using JetBrains.Annotations; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; @@ -38,13 +39,14 @@ public static IEndpointRouteBuilder MapEndpoints(this IEndpointRouteBuilder buil endpoints.Add(endpoint); } - foreach (IGrouping grouping in endpoints.GroupBy(x => x.Group)) + EndpointsOptions options = builder.ServiceProvider.GetRequiredService>().Value; + string globalPrefix = options.EndpointsRoutePrefix?.Trim('/') ?? "api"; + + RouteGroupBuilder groupBuilder = builder.MapGroup(globalPrefix); + + foreach (EndpointBase endpoint in endpoints) { - RouteGroupBuilder groupEndpoints = builder.MapGroup(grouping.Key); - foreach (EndpointBase endpoint in grouping) - { - endpoint.Map(groupEndpoints); - } + endpoint.Map(groupBuilder); } return builder; @@ -67,7 +69,8 @@ public static RouteHandlerBuilder MapGet(this IEndpointRouteBuilder endpoints, D return endpoints .MapGet(pattern, handler) - .WithName(handler.Method.GetEndpointName()); + .WithName(handler) + .WithTags(handler); } /// @@ -87,7 +90,8 @@ public static RouteHandlerBuilder MapPost(this IEndpointRouteBuilder endpoints, return endpoints .MapPost(pattern, handler) - .WithName(handler.Method.GetEndpointName()); + .WithName(handler) + .WithTags(handler); } /// @@ -107,7 +111,8 @@ public static RouteHandlerBuilder MapPut(this IEndpointRouteBuilder endpoints, D return endpoints .MapPut(pattern, handler) - .WithName(handler.Method.GetEndpointName()); + .WithName(handler) + .WithTags(handler); } /// @@ -127,7 +132,8 @@ public static RouteHandlerBuilder MapPatch(this IEndpointRouteBuilder endpoints, return endpoints .MapPatch(pattern, handler) - .WithName(handler.Method.GetEndpointName()); + .WithName(handler) + .WithTags(handler); } /// @@ -147,27 +153,8 @@ public static RouteHandlerBuilder MapDelete(this IEndpointRouteBuilder endpoints return endpoints .MapDelete(pattern, handler) - .WithName(handler.Method.GetEndpointName()); - } - - private static RouteGroupBuilder MapGroup(this IEndpointRouteBuilder builder, EndpointGroup group) - { - ArgumentNullException.ThrowIfNull(group); - - EndpointsOptions options = builder.ServiceProvider.GetRequiredService>().Value; - string globalPrefix = options.EndpointsRoutePrefix?.Trim('/'); - - string prefix = string.IsNullOrWhiteSpace(globalPrefix) - ? $"/{group.Name.ToLowerInvariant()}" - : $"/{globalPrefix}/{group.Name.ToLowerInvariant()}"; - - RouteGroupBuilder groupBuilder = builder - .MapGroup(prefix) - .WithTags(group.Name); - - options.MapGroup?.Invoke(groupBuilder); - - return groupBuilder; + .WithName(handler) + .WithTags(handler); } private static bool IsAnonymous(this MethodInfo method) @@ -176,14 +163,25 @@ private static bool IsAnonymous(this MethodInfo method) return method.Name.Any(invalidChars.Contains); } - private static string GetEndpointName(this MethodInfo method) + private static RouteHandlerBuilder WithName(this RouteHandlerBuilder builder, Delegate handler) { - Type declaringType = method.DeclaringType; + EndpointNameAttribute endpointNameAttribute = handler.Method.DeclaringType?.GetCustomAttribute(); + string name = endpointNameAttribute is not null + ? endpointNameAttribute.Name + : handler.Method.DeclaringType?.Name ?? "Endpoints"; - ArgumentNullException.ThrowIfNull(declaringType); + return builder.WithName(name); + } - string name = declaringType.GetCustomAttribute()?.Name ?? declaringType.Name; - return name; + private static RouteHandlerBuilder WithTags(this RouteHandlerBuilder builder, Delegate handler) + { + EndpointGroupAttribute endpointGroupAttribute = handler.Method.DeclaringType?.GetCustomAttribute(); + if (endpointGroupAttribute is not null) + { + builder = builder.WithTags(endpointGroupAttribute.Group); + } + + return builder; } } } diff --git a/src/AspNetCore.Endpoints/ServiceCollectionExtensions.cs b/src/AspNetCore.Endpoints/ServiceCollectionExtensions.cs index 952ecf3..0192fc2 100644 --- a/src/AspNetCore.Endpoints/ServiceCollectionExtensions.cs +++ b/src/AspNetCore.Endpoints/ServiceCollectionExtensions.cs @@ -1,22 +1,22 @@ -//namespace MadEyeMatt.AspNetCore.Endpoints -//{ -// using JetBrains.Annotations; -// using Microsoft.Extensions.DependencyInjection; +namespace MadEyeMatt.AspNetCore.Endpoints +{ + using JetBrains.Annotations; + using Microsoft.Extensions.DependencyInjection; -// /// -// /// Extension methods for the type. -// /// -// [PublicAPI] -// public static class ServiceCollectionExtensions -// { -// /// -// /// Adds the endpoint types as services to enable ctor injection. -// /// -// /// -// /// -// public static IServiceCollection AddEndpoints(this IServiceCollection services) -// { -// return services; -// } -// } -//} \ No newline at end of file + /// + /// Extension methods for the type. + /// + [PublicAPI] + public static class ServiceCollectionExtensions + { + /// + /// Adds the endpoint types as services to enable ctor injection. + /// + /// + /// + public static IServiceCollection AddEndpoints(this IServiceCollection services) + { + return services; + } + } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index fec67c5..008deda 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -29,7 +29,7 @@ - 8.0.5 + 8.1.0 $(VersionPrefix) $(VersionPrefix) diff --git a/tests/AspNetCore.Endpoints.UnitTests/AspNetCore.Endpoints.UnitTests.csproj b/tests/AspNetCore.Endpoints.UnitTests/AspNetCore.Endpoints.UnitTests.csproj index 63a8320..b761c6c 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/AspNetCore.Endpoints.UnitTests.csproj +++ b/tests/AspNetCore.Endpoints.UnitTests/AspNetCore.Endpoints.UnitTests.csproj @@ -11,12 +11,12 @@ - - - + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/AspNetCore.Endpoints.UnitTests/EndpointGroupTests.cs b/tests/AspNetCore.Endpoints.UnitTests/EndpointGroupTests.cs deleted file mode 100644 index 2a7ac03..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/EndpointGroupTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace AspNetCore.Endpoints.UnitTests -{ - using System; - using FluentAssertions; - using MadEyeMatt.AspNetCore.Endpoints; - - public class EndpointGroupTests - { - [Test] - [TestCase("")] - [TestCase(" ")] - [TestCase(null)] - public void ShouldThrowIfGroupNameIsEmpty(string? groupName) - { - Action action = () => - { - EndpointGroup _ = new EndpointGroup(groupName); - }; - - action.Should().Throw(); - } - - [Test] - public void ShouldCompareByName_NotEqual() - { - EndpointGroup endpointGroup1 = new EndpointGroup("One"); - EndpointGroup endpointGroup2 = new EndpointGroup("Two"); - - bool equal = endpointGroup1 == endpointGroup2; - equal.Should().BeFalse(); - } - - [Test] - public void ShouldCompareByName_Equal() - { - EndpointGroup endpointGroup1 = new EndpointGroup("One"); - EndpointGroup endpointGroup2 = new EndpointGroup("One"); - - bool equal = endpointGroup1 == endpointGroup2; - equal.Should().BeTrue(); - } - } -} diff --git a/tests/AspNetCore.Endpoints.UnitTests/EndpointRouteBuilderExtensionsTests.cs b/tests/AspNetCore.Endpoints.UnitTests/EndpointRouteBuilderExtensionsTests.cs index 789f4ce..e5df446 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/EndpointRouteBuilderExtensionsTests.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/EndpointRouteBuilderExtensionsTests.cs @@ -3,6 +3,7 @@ using System; using AspNetCore.Endpoints.UnitTests.Endpoints.Extensions; using FluentAssertions; + using NUnit.Framework; public class EndpointRouteBuilderExtensionsTests { diff --git a/tests/AspNetCore.Endpoints.UnitTests/EndpointTests.cs b/tests/AspNetCore.Endpoints.UnitTests/EndpointTests.cs deleted file mode 100644 index 9502a1c..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/EndpointTests.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace AspNetCore.Endpoints.UnitTests -{ - using AspNetCore.Endpoints.UnitTests.Endpoints.AnotherGroup; - using FluentAssertions; - - public class EndpointTests - { - [Test] - public void ShouldDeriveGroupNameFromNamespace() - { - GroupNameFromNamespace endpoint = new GroupNameFromNamespace(); - - endpoint.Group.Name.Should().Be("AnotherGroup"); - } - - [Test] - public void ShouldDeriveGroupNameFromAttribute() - { - GroupNameFromAttribute endpoint = new GroupNameFromAttribute(); - - endpoint.Group.Name.Should().Be("AttributeGroupName"); - } - - [Test] - public void ShouldDeriveGroupNameFromNamespaceIfAttributeHasEmptyName() - { - EmptyGroupNameFromAttribute endpoint = new EmptyGroupNameFromAttribute(); - - endpoint.Group.Name.Should().Be("AnotherGroup"); - } - } -} \ No newline at end of file diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/EmptyGroupNameFromAttribute.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/EmptyGroupNameFromAttribute.cs deleted file mode 100644 index 8dccb98..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/EmptyGroupNameFromAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace AspNetCore.Endpoints.UnitTests.Endpoints.AnotherGroup -{ - using System.Threading.Tasks; - using AspNetCore.Endpoints.UnitTests.Endpoints.Customers; - using JetBrains.Annotations; - using MadEyeMatt.AspNetCore.Endpoints; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Routing; - - [PublicAPI] - [MadEyeMatt.AspNetCore.Endpoints.EndpointGroupName(null)] - public sealed class EmptyGroupNameFromAttribute : EndpointBase - { - /// - public override void Map(IEndpointRouteBuilder endpoints) - { - endpoints - .MapGet(this.Execute, "{id}") - .Produces(200, "application/json"); - } - - public async Task Execute(HttpContext httpContext, string id) - { - return Results.Ok(new Customer - { - Name = "John Connor" - }); - } - } -} \ No newline at end of file diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromAttribute.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromAttribute.cs deleted file mode 100644 index a36f7ce..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace AspNetCore.Endpoints.UnitTests.Endpoints.AnotherGroup -{ - using System.Threading.Tasks; - using AspNetCore.Endpoints.UnitTests.Endpoints.Customers; - using JetBrains.Annotations; - using MadEyeMatt.AspNetCore.Endpoints; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Routing; - - [PublicAPI] - [MadEyeMatt.AspNetCore.Endpoints.EndpointGroupName("AttributeGroupName")] - public sealed class GroupNameFromAttribute : EndpointBase - { - /// - public override void Map(IEndpointRouteBuilder endpoints) - { - endpoints - .MapGet(this.Execute, "{id}") - .Produces(200, "application/json"); - } - - public async Task Execute(HttpContext httpContext, string id) - { - return Results.Ok(new Customer - { - Name = "John Connor" - }); - } - } -} \ No newline at end of file diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromNamespace.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromNamespace.cs deleted file mode 100644 index ed91702..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/AnotherGroup/GroupNameFromNamespace.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace AspNetCore.Endpoints.UnitTests.Endpoints.AnotherGroup -{ - using System.Threading.Tasks; - using AspNetCore.Endpoints.UnitTests.Endpoints.Customers; - using JetBrains.Annotations; - using MadEyeMatt.AspNetCore.Endpoints; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Routing; - - [PublicAPI] - public sealed class GroupNameFromNamespace : EndpointBase - { - /// - public override void Map(IEndpointRouteBuilder endpoints) - { - endpoints - .MapGet(this.Execute, "{id}") - .Produces(200, "application/json"); - } - - public async Task Execute(HttpContext httpContext, string id) - { - return Results.Ok(new Customer - { - Name = "John Connor" - }); - } - } -} \ No newline at end of file diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomer.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomer.cs index ae56e7b..ef2c6ce 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomer.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomer.cs @@ -7,13 +7,14 @@ using Microsoft.AspNetCore.Routing; [PublicAPI] + [EndpointGroup("Customers")] public sealed class GetCustomer : EndpointBase { /// public override void Map(IEndpointRouteBuilder endpoints) { endpoints - .MapGet(this.Execute, "{id}") + .MapGet(this.Execute, "customers/{id}") .Produces(200, "application/json"); } diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomers.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomers.cs index 0efa94c..717e591 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomers.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/Customers/GetCustomers.cs @@ -7,13 +7,14 @@ using Microsoft.AspNetCore.Routing; [PublicAPI] + [EndpointGroup("Customers")] public sealed class GetCustomers : EndpointBase { /// public override void Map(IEndpointRouteBuilder endpoints) { endpoints - .MapGet(this.Execute) + .MapGet(this.Execute, "customers") .Produces(200, "application/json"); } diff --git a/tests/AspNetCore.Endpoints.UnitTests/Endpoints/TopLevelEndpoint.cs b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/TopLevelEndpoint.cs new file mode 100644 index 0000000..c67ca7c --- /dev/null +++ b/tests/AspNetCore.Endpoints.UnitTests/Endpoints/TopLevelEndpoint.cs @@ -0,0 +1,13 @@ +namespace AspNetCore.Endpoints.UnitTests.Endpoints +{ + using MadEyeMatt.AspNetCore.Endpoints; + using Microsoft.AspNetCore.Routing; + + public class TopLevelEndpoint : EndpointBase + { + /// + public override void Map(IEndpointRouteBuilder endpoints) + { + } + } +} diff --git a/tests/AspNetCore.Endpoints.UnitTests/EndpointsAutoRegistrationTests.cs b/tests/AspNetCore.Endpoints.UnitTests/EndpointsAutoRegistrationTests.cs index aa90b49..aa916e0 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/EndpointsAutoRegistrationTests.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/EndpointsAutoRegistrationTests.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; + using NUnit.Framework; [TestFixture] public class EndpointsAutoRegistrationTests : TestServerFixtureBase diff --git a/tests/AspNetCore.Endpoints.UnitTests/EndpointsOptionsTests.cs b/tests/AspNetCore.Endpoints.UnitTests/EndpointsOptionsTests.cs index eeee2bc..866a08c 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/EndpointsOptionsTests.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/EndpointsOptionsTests.cs @@ -8,6 +8,7 @@ using MadEyeMatt.AspNetCore.Endpoints; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; [TestFixture("endpoints")] [TestFixture("")] @@ -45,7 +46,7 @@ public async Task ShouldRegisterEndpoint_GetCustomers() { HttpClient client = this.CreateClient(); - string path = $"{this.prefix}/customers"; + string path = $"{this.prefix ?? "api"}/customers"; HttpResponseMessage response = await client.GetAsync(path.TrimStart('/')); response.StatusCode.Should().Be(HttpStatusCode.OK); @@ -59,7 +60,7 @@ public async Task ShouldRegisterEndpoint_GetCustomer() { HttpClient client = this.CreateClient(); - string path = $"{this.prefix}/customers/20ac7bae93464ade8803ec34f0cf0b5b"; + string path = $"{this.prefix ?? "api"}/customers/20ac7bae93464ade8803ec34f0cf0b5b"; HttpResponseMessage response = await client.GetAsync(path.TrimStart('/')); response.StatusCode.Should().Be(HttpStatusCode.OK); diff --git a/tests/AspNetCore.Endpoints.UnitTests/GlobalUsings.cs b/tests/AspNetCore.Endpoints.UnitTests/GlobalUsings.cs deleted file mode 100644 index cefced4..0000000 --- a/tests/AspNetCore.Endpoints.UnitTests/GlobalUsings.cs +++ /dev/null @@ -1 +0,0 @@ -global using NUnit.Framework; \ No newline at end of file diff --git a/tests/AspNetCore.Endpoints.UnitTests/TestServerFixtureBase.cs b/tests/AspNetCore.Endpoints.UnitTests/TestServerFixtureBase.cs index e8dacc1..9596473 100644 --- a/tests/AspNetCore.Endpoints.UnitTests/TestServerFixtureBase.cs +++ b/tests/AspNetCore.Endpoints.UnitTests/TestServerFixtureBase.cs @@ -12,14 +12,15 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + using NUnit.Framework; public abstract class TestServerFixtureBase { private readonly CancellationTokenSource cancellationTokenSource; private readonly List clients; - private WebApplication? app; - private TestServer? server; + private WebApplication app; + private TestServer server; protected TestServerFixtureBase() {