using System.Text.Json; using Microsoft.JSInterop; using RpgRoller.Components; namespace RpgRoller.Tests; public sealed class WorkspaceQueryServiceTests { private sealed class StubJsRuntime(Func handler) : IJSRuntime { public ValueTask InvokeAsync(string identifier, object?[]? args) { return ValueTask.FromResult((TValue)handler(identifier, args, typeof(TValue))!); } public ValueTask InvokeAsync(string identifier, CancellationToken cancellationToken, object?[]? args) { return InvokeAsync(identifier, args); } } [Fact] public async Task GetCampaignsAsync_UsesCampaignsApiEndpoint() { var queryService = new WorkspaceQueryService(new RpgRollerApiClient( new StubJsRuntime((identifier, args, returnType) => { Assert.Equal("rpgRollerApi.request", identifier); Assert.Equal("GET", args![0]); Assert.Equal("/api/campaigns", args[1]); Assert.Null(args[2]); return CreateJsApiResponse(args: new { ok = true, status = 200, data = new[] { new CampaignSummary(Guid.NewGuid(), "Alpha", "d6", new CampaignGmSummary(Guid.NewGuid(), "GM"), 1) } }, returnType); }))); var campaigns = await queryService.GetCampaignsAsync(); var campaign = Assert.Single(campaigns); Assert.Equal("Alpha", campaign.Name); } [Fact] public async Task GetMeAsync_MapsUnauthorizedApiResponseToApiRequestException() { var queryService = new WorkspaceQueryService(new RpgRollerApiClient( new StubJsRuntime((identifier, args, returnType) => { Assert.Equal("rpgRollerApi.request", identifier); Assert.Equal("GET", args![0]); Assert.Equal("/api/me", args[1]); return CreateJsApiResponse(args: new { ok = false, status = 401, error = "You must be logged in.", code = "unauthorized", data = (object?)null }, returnType); }))); var exception = await Assert.ThrowsAsync(queryService.GetMeAsync); Assert.Equal(401, exception.StatusCode); Assert.Equal("You must be logged in.", exception.Message); Assert.Equal("unauthorized", exception.ErrorCode); } private static object CreateJsApiResponse(object args, Type returnType) { var json = JsonSerializer.Serialize(args); return JsonSerializer.Deserialize(json, returnType, JsonOptions)!; } private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); }