From 3836faf8727ec978a8a507e495c494cd78af842d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 12 Sep 2026 13:57:25 +0100 Subject: [PATCH] Use a shared YavscMessageSender --- src/Yavsc.Api.Test/BillingControllerTests.cs | 114 ++++++++++++++++++ .../Fixtures/ApiWebServerFixture.cs | 24 +++- src/Yavsc.Api/Program.cs | 19 +-- .../Services/YavscMessageSender.cs | 1 + 4 files changed, 141 insertions(+), 17 deletions(-) create mode 100644 src/Yavsc.Api.Test/BillingControllerTests.cs rename src/{Yavsc.Org => Yavsc.Server}/Services/YavscMessageSender.cs (99%) diff --git a/src/Yavsc.Api.Test/BillingControllerTests.cs b/src/Yavsc.Api.Test/BillingControllerTests.cs new file mode 100644 index 000000000..a6445c776 --- /dev/null +++ b/src/Yavsc.Api.Test/BillingControllerTests.cs @@ -0,0 +1,114 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using Microsoft.Extensions.DependencyInjection; +using Yavsc.Api.Test.Fixtures; +using Yavsc.Helpers; +using Yavsc.Models; +using Yavsc.Models.Billing; +using Yavsc.Models.Workflow; +using Yavsc.Tests.Shared; + +namespace Yavsc.Api.Test; + +[Collection("Yavsc Api")] +public sealed class BillingControllerTests : IClassFixture +{ + private readonly ApiWebServerFixture _fixture; + + public BillingControllerTests(ApiWebServerFixture fixture) + { + _fixture = fixture; + } + + private HttpClient NewClient(string subject = "alice", string scope = "api") + { + var handler = new HttpClientHandler + { + ServerCertificateCustomValidationCallback = (_, _, _, _) => true + }; + + var http = new HttpClient(handler) + { + BaseAddress = new Uri(_fixture.BaseAddress) + }; + + http.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", TestTokenIssuer.Issue(subject, scope)); + + return http; + } + + [Fact] + public async Task GetProviderOngoingCommands_returns_current_provider_requests() + { + WorkflowHelpers.ConfigureBillingService(); + _fixture.ResetAndSeedActivityGraph(); + + using (var scope = _fixture.Services.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + var location = db.Locations.Single(); + + db.RdvQueries.Add(new RdvQuery + { + ActivityCode = "dev", + ClientId = "bob", + PerformerId = "alice", + Consent = true, + UserCreated = "alice", + UserModified = "alice", + DateCreated = DateTime.UtcNow.AddMinutes(-10), + DateModified = DateTime.UtcNow.AddMinutes(-8), + EventDate = DateTime.UtcNow.AddDays(1), + Location = location, + Reason = "Rendez-vous fournisseur", + Status = QueryStatus.InProgress, + Description = "Commande fournisseur en cours", + }); + + db.RdvQueries.Add(new RdvQuery + { + ActivityCode = "dev", + ClientId = "alice", + PerformerId = "bob", + Consent = true, + UserCreated = "bob", + UserModified = "bob", + DateCreated = DateTime.UtcNow.AddMinutes(-20), + DateModified = DateTime.UtcNow.AddMinutes(-20), + EventDate = DateTime.UtcNow.AddDays(2), + Location = location, + Reason = "Commande d'un autre prestataire", + Status = QueryStatus.Accepted, + Description = "Autre prestataire", + }); + + db.SaveChanges(); + } + + using var http = NewClient(); + + var response = await http.GetAsync("/api/v1/bill/provider/ongoing", TestContext.Current.CancellationToken); + var body = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + Assert.True(response.StatusCode == HttpStatusCode.OK, $"Unexpected status {(int)response.StatusCode} ({response.StatusCode}): {body}"); + + var payload = await response.Content.ReadFromJsonAsync>(TestContext.Current.CancellationToken); + Assert.NotNull(payload); + Assert.NotEmpty(payload!); + Assert.All(payload!, item => Assert.Equal("alice", item.PerformerId)); + Assert.Contains(payload!, item => item.BillingCode == BillingCodes.Rdv); + } + + private sealed class ProviderOngoingCommandDto + { + public long Id { get; set; } + public string BillingCode { get; set; } = string.Empty; + public string ActivityCode { get; set; } = string.Empty; + public string PerformerId { get; set; } = string.Empty; + public string ClientId { get; set; } = string.Empty; + public QueryStatus Status { get; set; } + public string Description { get; set; } = string.Empty; + } +} diff --git a/src/Yavsc.Api.Test/Fixtures/ApiWebServerFixture.cs b/src/Yavsc.Api.Test/Fixtures/ApiWebServerFixture.cs index e2a8b3376..d8663ed8f 100644 --- a/src/Yavsc.Api.Test/Fixtures/ApiWebServerFixture.cs +++ b/src/Yavsc.Api.Test/Fixtures/ApiWebServerFixture.cs @@ -1,14 +1,17 @@ -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using Yavsc.Controllers; +using Yavsc.Interfaces.Workflow; using Yavsc.Models; +using Yavsc.Models.Google.Messaging; using Yavsc.Models.Haircut; +using Yavsc.Models.Messaging; using Yavsc.Models.Relationship; using Yavsc.Models.Workflow; +using Yavsc.Services; using Yavsc.Tests.Shared; namespace Yavsc.Api.Test.Fixtures; @@ -40,6 +43,10 @@ public sealed class ApiWebServerFixture : WebHostFixture builder.Services.AddControllers() .AddApplicationPart(typeof(ActivityApiController).Assembly); + builder.Services.AddLocalization(); + builder.Services.Configure(_ => { }); + builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddAuthorization(); builder.Services.AddAuthentication("Bearer") @@ -83,6 +90,21 @@ public sealed class ApiWebServerFixture : WebHostFixture public string BaseAddress => Addresses.First(a => a.StartsWith("https://", StringComparison.Ordinal)); + private sealed class NoopMessageSender : IYavscMessageSender + { + public Task NotifyBookQueryAsync(IEnumerable connectionIds, RdvQueryEvent ev) + => Task.FromResult(new MessageWithPayloadResponse()); + + public Task NotifyEstimateAsync(IEnumerable connectionIds, EstimationEvent ev) + => Task.FromResult(new MessageWithPayloadResponse()); + + public Task NotifyHairCutQueryAsync(IEnumerable connectionIds, HairCutQueryEvent ev) + => Task.FromResult(new MessageWithPayloadResponse()); + + public Task NotifyAsync(IEnumerable connectionIds, IEvent yaev) + => Task.FromResult(new MessageWithPayloadResponse()); + } + public void ResetAndSeedActivityGraph() { using var scope = Services.CreateScope(); diff --git a/src/Yavsc.Api/Program.cs b/src/Yavsc.Api/Program.cs index 5269eef1a..8117fb1d4 100644 --- a/src/Yavsc.Api/Program.cs +++ b/src/Yavsc.Api/Program.cs @@ -1,18 +1,6 @@ -/* - Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/ - - Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved. - - Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - Source code and license this software can be found - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. -*/ using Anthropic.SDK; using IdentityModel; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection.Extensions; using Yavsc.Abstract.Interfaces; @@ -91,7 +79,8 @@ internal class Program .TryAddSingleton(); services .AddTransient() - .AddTransient(); + .AddTransient() + .AddTransient(); services.AddTransient(); builder.Services.AddSession(options => { @@ -123,9 +112,7 @@ internal class Program ; app.MapIdentityApi().RequireAuthorization("ApiScope"); app.MapDefaultControllerRoute(); - app.MapGet("/identity", (HttpContext context) => - new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) - ); + app.UseSession(); await app.RunAsync(); diff --git a/src/Yavsc.Org/Services/YavscMessageSender.cs b/src/Yavsc.Server/Services/YavscMessageSender.cs similarity index 99% rename from src/Yavsc.Org/Services/YavscMessageSender.cs rename to src/Yavsc.Server/Services/YavscMessageSender.cs index 7c7f6faa7..3ab43fbee 100644 --- a/src/Yavsc.Org/Services/YavscMessageSender.cs +++ b/src/Yavsc.Server/Services/YavscMessageSender.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Yavsc.Interface;