Use a shared YavscMessageSender

This commit is contained in:
Paul Schneider 2026-09-12 13:57:25 +01:00
commit 3836faf872
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
4 changed files with 141 additions and 17 deletions

View file

@ -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<ApiWebServerFixture>
{
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<ApplicationDbContext>();
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<List<ProviderOngoingCommandDto>>(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;
}
}

View file

@ -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<GoogleAuthSettings>(_ => { });
builder.Services.AddTransient<IBillingService, BillingService>();
builder.Services.AddTransient<IYavscMessageSender, NoopMessageSender>();
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<MessageWithPayloadResponse> NotifyBookQueryAsync(IEnumerable<string> connectionIds, RdvQueryEvent ev)
=> Task.FromResult(new MessageWithPayloadResponse());
public Task<MessageWithPayloadResponse> NotifyEstimateAsync(IEnumerable<string> connectionIds, EstimationEvent ev)
=> Task.FromResult(new MessageWithPayloadResponse());
public Task<MessageWithPayloadResponse> NotifyHairCutQueryAsync(IEnumerable<string> connectionIds, HairCutQueryEvent ev)
=> Task.FromResult(new MessageWithPayloadResponse());
public Task<MessageWithPayloadResponse> NotifyAsync(IEnumerable<string> connectionIds, IEvent yaev)
=> Task.FromResult(new MessageWithPayloadResponse());
}
public void ResetAndSeedActivityGraph()
{
using var scope = Services.CreateScope();

View file

@ -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<ISmtpClientFactory, SmtpClientFactory>();
services
.AddTransient<IBillingService, BillingService>()
.AddTransient<ICalendarManager, CalendarManager>();
.AddTransient<ICalendarManager, CalendarManager>()
.AddTransient<IYavscMessageSender, YavscMessageSender>();
services.AddTransient<IFileSystemAuthManager, FileSystemAuthManager>();
builder.Services.AddSession(options =>
{
@ -123,9 +112,7 @@ internal class Program
;
app.MapIdentityApi<ApplicationUser>().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();

View file

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Yavsc.Interface;