From dd2a805c24c083900f1f46a7c95a2d623d1fb4d3 Mon Sep 17 00:00:00 2001 From: Arthur Bassi Date: Fri, 10 Jul 2026 10:56:18 -0300 Subject: [PATCH] fix(work-orders): return 400 for invalid advanced-search custom date range Map ArgumentException from datePreset=custom without dates to BadRequest so the endpoint matches the Phase 4 contract. --- .../WorkOrderControllerSearchTests.cs | 101 ++++++++++++++++++ .../Controllers/WorkOrderController.cs | 13 ++- 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 Api.SeaHavenIndustries.Tests/WorkOrderControllerSearchTests.cs diff --git a/Api.SeaHavenIndustries.Tests/WorkOrderControllerSearchTests.cs b/Api.SeaHavenIndustries.Tests/WorkOrderControllerSearchTests.cs new file mode 100644 index 0000000..61d37c9 --- /dev/null +++ b/Api.SeaHavenIndustries.Tests/WorkOrderControllerSearchTests.cs @@ -0,0 +1,101 @@ +using Api.SeaHavenIndustries.Controllers; +using Api.SeaHavenIndustries.DTOs; +using Data.SeaHavenIndustries; +using FluentAssertions; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Moq; +using SeaHaven.DataServices.Interfaces; +using SeaHaven.Services.DTOs; +using SeaHaven.Services.Helpers; +using SeaHaven.Services.Implementation; +using SeaHaven.Services.Interfaces; +using Xunit; + +namespace Api.SeaHavenIndustries.Tests; + +public class WorkOrderControllerSearchTests +{ + private static ApplicationDbContext NewContext() + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(Guid.NewGuid().ToString()) + .Options; + return new ApplicationDbContext(options); + } + + private static UserManager MockUserManager() + { + var store = new Mock>(); + return new Mock>( + store.Object, null!, null!, null!, null!, null!, null!, null!, null!).Object; + } + + private static WorkOrderController NewController( + ApplicationDbContext ctx, + IWorkOrderAdvancedSearchService advancedSearch) + { + var controller = new WorkOrderController( + MockUserManager(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + ctx, + Mock.Of(), + Mock.Of(), + null!, + null!, + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + advancedSearch); + + controller.ControllerContext = new ControllerContext + { + HttpContext = new DefaultHttpContext + { + User = new System.Security.Claims.ClaimsPrincipal( + new System.Security.Claims.ClaimsIdentity( + new[] + { + new System.Security.Claims.Claim( + System.Security.Claims.ClaimTypes.NameIdentifier, + "test-user") + }, + "Test")) + } + }; + + return controller; + } + + [Fact] + public async Task SearchBoard_WhenCustomPresetMissingDates_ReturnsBadRequest() + { + using var ctx = NewContext(); + var advancedSearch = new WorkOrderAdvancedSearchService( + Mock.Of()); + var controller = NewController(ctx, advancedSearch); + + var result = await controller.SearchBoard(new WorkOrderAdvancedSearchQueryDto + { + DatePreset = WorkOrderAdvancedSearchDatePreset.Custom + }); + + var badRequest = result.Should().BeOfType().Subject; + var body = badRequest.Value.Should().BeOfType().Subject; + body.Status.Should().Be("Error"); + body.Message.Should().Contain("dateFrom"); + } +} diff --git a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs index f227ffd..685c3c6 100644 --- a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs +++ b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs @@ -120,9 +120,16 @@ namespace Api.SeaHavenIndustries.Controllers [HttpGet("board/search")] public async Task SearchBoard([FromQuery] WorkOrderAdvancedSearchQueryDto query) { - var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); - var result = await _advancedSearchService.SearchAsync(query, userId); - return Ok(result); + try + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var result = await _advancedSearchService.SearchAsync(query, userId); + return Ok(result); + } + catch (ArgumentException ex) + { + return BadRequest(new Response { Status = "Error", Message = ex.Message }); + } } [HttpGet("lookups/dispatchers")]