mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 08:23:12 +00:00
111 lines
4.2 KiB
C#
111 lines
4.2 KiB
C#
using Api.SeaHavenIndustries.Controllers;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using SeaHaven.Services.Interfaces;
|
|
using System.Security.Claims;
|
|
using Xunit;
|
|
|
|
namespace Api.SeaHavenIndustries.Tests;
|
|
|
|
public sealed class WorkOrderReconciliationControllerTests
|
|
{
|
|
[Fact]
|
|
public async Task Admin_trigger_returns_durable_run_and_status_is_queryable()
|
|
{
|
|
var runId = Guid.NewGuid();
|
|
var service = new StubService(runId);
|
|
var controller = new WorkOrderReconciliationController(service);
|
|
|
|
var trigger = Assert.IsType<AcceptedResult>(
|
|
await controller.Trigger(CancellationToken.None));
|
|
Assert.Equal(StatusCodes.Status202Accepted, trigger.StatusCode);
|
|
Assert.Equal(runId, service.LastRunId);
|
|
var status = Assert.IsType<OkObjectResult>(
|
|
await controller.Status(CancellationToken.None));
|
|
Assert.IsType<WorkOrderReconciliationStatus>(status.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Disabled_trigger_returns_sanitized_unavailable_response()
|
|
{
|
|
var controller = new WorkOrderReconciliationController(new StubService(Guid.Empty));
|
|
|
|
var result = Assert.IsType<ObjectResult>(
|
|
await controller.Trigger(CancellationToken.None));
|
|
|
|
Assert.Equal(StatusCodes.Status503ServiceUnavailable, result.StatusCode);
|
|
Assert.DoesNotContain("exception", result.Value!.ToString(), StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void Framework_action_descriptors_expose_only_admin_get_and_post_reconciliation_routes()
|
|
{
|
|
var services = new ServiceCollection();
|
|
services.AddLogging();
|
|
services.AddMvcCore()
|
|
.AddApplicationPart(typeof(WorkOrderReconciliationController).Assembly);
|
|
using var provider = services.BuildServiceProvider();
|
|
var descriptors = provider
|
|
.GetRequiredService<IActionDescriptorCollectionProvider>()
|
|
.ActionDescriptors
|
|
.Items
|
|
.OfType<ControllerActionDescriptor>()
|
|
.Where(d => d.ControllerTypeInfo == typeof(WorkOrderReconciliationController))
|
|
.ToList();
|
|
|
|
var routes = descriptors
|
|
.SelectMany(d => (d.ActionConstraints ?? Array.Empty<IActionConstraintMetadata>())
|
|
.OfType<HttpMethodActionConstraint>()
|
|
.SelectMany(c => c.HttpMethods)
|
|
.Select(method => $"{method} {d.AttributeRouteInfo!.Template}"))
|
|
.ToHashSet(StringComparer.Ordinal);
|
|
|
|
Assert.True(routes.SetEquals(new[]
|
|
{
|
|
"GET api/admin/work-order-reconciliation",
|
|
"POST api/admin/work-order-reconciliation"
|
|
}));
|
|
Assert.All(descriptors, descriptor =>
|
|
Assert.Contains(
|
|
descriptor.ControllerTypeInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true)
|
|
.OfType<AuthorizeAttribute>(),
|
|
attribute => attribute.Roles == "Admin"));
|
|
}
|
|
|
|
private sealed class StubService : IWorkOrderReconciliationService
|
|
{
|
|
private readonly Guid _runId;
|
|
public StubService(Guid runId) => _runId = runId;
|
|
public Guid LastRunId { get; private set; }
|
|
|
|
public Task<WorkOrderReconciliationTriggerResult> TriggerAsync(
|
|
ClaimsPrincipal user,
|
|
string reason,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
LastRunId = _runId;
|
|
return Task.FromResult(new WorkOrderReconciliationTriggerResult(
|
|
_runId != Guid.Empty,
|
|
_runId));
|
|
}
|
|
|
|
public Task<WorkOrderReconciliationStatus> GetStatusAsync(
|
|
ClaimsPrincipal user,
|
|
CancellationToken cancellationToken) =>
|
|
Task.FromResult(new WorkOrderReconciliationStatus(
|
|
_runId,
|
|
"Pending",
|
|
"admin",
|
|
DateTimeOffset.UtcNow,
|
|
null,
|
|
null,
|
|
0,
|
|
0,
|
|
null));
|
|
}
|
|
}
|