From d6c75654b0b459cd48fd838b8fb5d8b34ac02161 Mon Sep 17 00:00:00 2001 From: ThompsonNye Date: Sun, 25 Aug 2024 13:39:00 +0200 Subject: [PATCH] Use wrapper class for get all api endpoints To enable e.g. pagination in the future --- src/WebApi/Cars/GetCars.cs | 31 ++++++++-- src/WebApi/Consumptions/GetConsumptions.cs | 60 +++++++++++++------ .../Cars/GetCarsTests.cs | 16 ++--- .../Consumptions/GetConsumptionsTests.cs | 8 +-- 4 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/WebApi/Cars/GetCars.cs b/src/WebApi/Cars/GetCars.cs index 4bbeb1a..14d0c5e 100644 --- a/src/WebApi/Cars/GetCars.cs +++ b/src/WebApi/Cars/GetCars.cs @@ -1,27 +1,46 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Vegasco.WebApi.Persistence; namespace Vegasco.WebApi.Cars; public static class GetCars { - public record Response(Guid Id, string Name); + public class ApiResponse + { + public IEnumerable Cars { get; set; } = []; + } + + public record ResponseDto(Guid Id, string Name); + + public class Request + { + [FromQuery(Name = "page")] public int? Page { get; set; } + [FromQuery(Name = "pageSize")] public int? PageSize { get; set; } + } public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) { return builder .MapGet("cars", Endpoint) + .WithDescription("Returns all cars") .WithTags("Cars"); } - private static async Task Endpoint( + private static async Task> Endpoint( + [AsParameters] Request request, ApplicationDbContext dbContext, CancellationToken cancellationToken) { - var cars = await dbContext.Cars - .Select(x => new Response(x.Id.Value, x.Name)) + List cars = await dbContext.Cars + .Select(x => new ResponseDto(x.Id.Value, x.Name)) .ToListAsync(cancellationToken); - return TypedResults.Ok(cars); + var response = new ApiResponse + { + Cars = cars + }; + return TypedResults.Ok(response); } } diff --git a/src/WebApi/Consumptions/GetConsumptions.cs b/src/WebApi/Consumptions/GetConsumptions.cs index bc13cee..9168366 100644 --- a/src/WebApi/Consumptions/GetConsumptions.cs +++ b/src/WebApi/Consumptions/GetConsumptions.cs @@ -1,27 +1,53 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; using Vegasco.WebApi.Persistence; namespace Vegasco.WebApi.Consumptions; public static class GetConsumptions { - public record Response(Guid Id, DateTimeOffset DateTime, double Distance, double Amount, bool IgnoreInCalculation, Guid CarId); + public class ApiResponse + { + public IEnumerable Consumptions { get; set; } = []; + } - public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) - { - return builder - .MapGet("consumptions", Endpoint) - .WithTags("Consumptions"); - } + public record ResponseDto( + Guid Id, + DateTimeOffset DateTime, + double Distance, + double Amount, + bool IgnoreInCalculation, + Guid CarId); - private static async Task Endpoint( - ApplicationDbContext dbContext, - CancellationToken cancellationToken) - { - var consumptions = await dbContext.Consumptions - .Select(x => new Response(x.Id.Value, x.DateTime, x.Distance, x.Amount, x.IgnoreInCalculation, x.CarId.Value)) - .ToListAsync(cancellationToken); + public class Request + { + [FromQuery(Name = "page")] public int? Page { get; set; } + [FromQuery(Name = "pageSize")] public int? PageSize { get; set; } + } - return TypedResults.Ok(consumptions); - } + public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) + { + return builder + .MapGet("consumptions", Endpoint) + .WithDescription("Returns all consumption entries") + .WithTags("Consumptions"); + } + + private static async Task> Endpoint( + [AsParameters] Request request, + ApplicationDbContext dbContext, + CancellationToken cancellationToken) + { + List consumptions = await dbContext.Consumptions + .Select(x => + new ResponseDto(x.Id.Value, x.DateTime, x.Distance, x.Amount, x.IgnoreInCalculation, x.CarId.Value)) + .ToListAsync(cancellationToken); + + var apiResponse = new ApiResponse + { + Consumptions = consumptions + }; + return TypedResults.Ok(apiResponse); + } } \ No newline at end of file diff --git a/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs b/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs index b94c864..5924713 100644 --- a/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs +++ b/tests/WebApi.Tests.Integration/Cars/GetCarsTests.cs @@ -23,12 +23,12 @@ public class GetCarsTests : IAsyncLifetime // Arrange // Act - var response = await _factory.HttpClient.GetAsync("v1/cars"); + using HttpResponseMessage response = await _factory.HttpClient.GetAsync("v1/cars"); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var cars = await response.Content.ReadFromJsonAsync>(); - cars.Should().BeEmpty(); + var apiResponse = await response.Content.ReadFromJsonAsync(); + apiResponse!.Cars.Should().BeEmpty(); } [Fact] @@ -40,8 +40,8 @@ public class GetCarsTests : IAsyncLifetime const int numberOfCars = 5; for (var i = 0; i < numberOfCars; i++) { - var createCarRequest = _carFaker.CreateCarRequest(); - var createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); + CreateCar.Request createCarRequest = _carFaker.CreateCarRequest(); + HttpResponseMessage createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest); createCarResponse.EnsureSuccessStatusCode(); var createdCar = await createCarResponse.Content.ReadFromJsonAsync(); @@ -49,12 +49,12 @@ public class GetCarsTests : IAsyncLifetime } // Act - var response = await _factory.HttpClient.GetAsync("v1/cars"); + using HttpResponseMessage response = await _factory.HttpClient.GetAsync("v1/cars"); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var cars = await response.Content.ReadFromJsonAsync>(); - cars.Should().BeEquivalentTo(createdCars); + var apiResponse = await response.Content.ReadFromJsonAsync(); + apiResponse!.Cars.Should().BeEquivalentTo(createdCars); } public Task InitializeAsync() => Task.CompletedTask; diff --git a/tests/WebApi.Tests.Integration/Consumptions/GetConsumptionsTests.cs b/tests/WebApi.Tests.Integration/Consumptions/GetConsumptionsTests.cs index 553879b..dc919ee 100644 --- a/tests/WebApi.Tests.Integration/Consumptions/GetConsumptionsTests.cs +++ b/tests/WebApi.Tests.Integration/Consumptions/GetConsumptionsTests.cs @@ -42,8 +42,8 @@ public class GetConsumptionsTests : IAsyncLifetime // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var consumptions = await response.Content.ReadFromJsonAsync>(); - consumptions.Should().BeEquivalentTo(createdConsumptions); + var apiResponse = await response.Content.ReadFromJsonAsync(); + apiResponse!.Consumptions.Should().BeEquivalentTo(createdConsumptions); } [Fact] @@ -56,8 +56,8 @@ public class GetConsumptionsTests : IAsyncLifetime // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); - var consumptions = await response.Content.ReadFromJsonAsync>(); - consumptions.Should().BeEmpty(); + var apiResponse = await response.Content.ReadFromJsonAsync(); + apiResponse!.Consumptions.Should().BeEmpty(); } private async Task CreateConsumptionAsync()