From 8012ecaa73cfcbc0bfee3ad81bfd8044c97e9750 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sun, 1 Feb 2026 04:27:06 -0600 Subject: [PATCH] feat: wip on login endpoint - added basic REPR pattern - added basic vert architecture - implemented basica validation for single test case --- src/FiscalOS.API/Login/Endpoint.cs | 18 ++++++++++++ src/FiscalOS.API/Login/Request.cs | 8 ++++++ src/FiscalOS.API/Program.cs | 3 ++ tests/FiscalOS.API.Tests/Infra/TestApi.cs | 11 ++++++++ .../Integration/LoginTests.cs | 28 +++++++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 src/FiscalOS.API/Login/Endpoint.cs create mode 100644 src/FiscalOS.API/Login/Request.cs create mode 100644 tests/FiscalOS.API.Tests/Infra/TestApi.cs create mode 100644 tests/FiscalOS.API.Tests/Integration/LoginTests.cs diff --git a/src/FiscalOS.API/Login/Endpoint.cs b/src/FiscalOS.API/Login/Endpoint.cs new file mode 100644 index 0000000..a7e9e9e --- /dev/null +++ b/src/FiscalOS.API/Login/Endpoint.cs @@ -0,0 +1,18 @@ +namespace FiscalOS.API.Login; + +internal static class Endpoint +{ + private const string Route = "/login"; + + public static RouteHandlerBuilder MapLoginEndpoint(this WebApplication app) + { + return app.MapPost(Route, HandleAsync); + } + + private static async Task HandleAsync([FromBody] LoginRequest loginRequest) + { + Console.WriteLine(loginRequest.Username); + Console.WriteLine(loginRequest.Password); + return Results.Ok(); + } +} \ No newline at end of file diff --git a/src/FiscalOS.API/Login/Request.cs b/src/FiscalOS.API/Login/Request.cs new file mode 100644 index 0000000..d793832 --- /dev/null +++ b/src/FiscalOS.API/Login/Request.cs @@ -0,0 +1,8 @@ +namespace FiscalOS.API.Login; + +public record LoginRequest( + [Required] + string Username, + [Required] + string Password +); \ No newline at end of file diff --git a/src/FiscalOS.API/Program.cs b/src/FiscalOS.API/Program.cs index 6a4fd66..ed5ab3d 100644 --- a/src/FiscalOS.API/Program.cs +++ b/src/FiscalOS.API/Program.cs @@ -1,5 +1,6 @@ var builder = WebApplication.CreateBuilder(args); +builder.Services.AddValidation(); builder.Services.AddOpenApi(); var app = builder.Build(); @@ -11,4 +12,6 @@ if (app.Environment.IsDevelopment()) app.UseHttpsRedirection(); +app.MapLoginEndpoint(); + app.Run(); \ No newline at end of file diff --git a/tests/FiscalOS.API.Tests/Infra/TestApi.cs b/tests/FiscalOS.API.Tests/Infra/TestApi.cs new file mode 100644 index 0000000..b535b1f --- /dev/null +++ b/tests/FiscalOS.API.Tests/Infra/TestApi.cs @@ -0,0 +1,11 @@ +namespace FiscalOS.API.Tests.Infra; + +public class TestApi : WebApplicationFactory +{ + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + base.ConfigureWebHost(builder); + + builder.ConfigureLogging(static c => c.ClearProviders()); + } +} \ No newline at end of file diff --git a/tests/FiscalOS.API.Tests/Integration/LoginTests.cs b/tests/FiscalOS.API.Tests/Integration/LoginTests.cs new file mode 100644 index 0000000..aa2f856 --- /dev/null +++ b/tests/FiscalOS.API.Tests/Integration/LoginTests.cs @@ -0,0 +1,28 @@ +using System.Net.Http.Json; + +using Microsoft.AspNetCore.Mvc; + +namespace FiscalOS.API.Tests.Integration; + +public class LoginTests(TestApi testApi) : IClassFixture +{ + private readonly TestApi _testApi = testApi; + + [Fact] + public async Task Login_WhenUserSubmitsWithoutUsernameOrPassword_ItShouldReturn400WithProblemDetails() + { + var client = _testApi.CreateClient(); + + var res = await client.PostAsJsonAsync("/login", new { }, TestContext.Current.CancellationToken); + + res.StatusCode.Should().Be(System.Net.HttpStatusCode.BadRequest); + + var problem = await res.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); + + problem!.Errors.Should().BeEquivalentTo(new Dictionary() + { + ["Username"] = ["The Username field is required."], + ["Password"] = ["The Password field is required."] + }); + } +} \ No newline at end of file