Files
vigilcare-clinical/VigilCareClinicalAPI.Tests/Simulation/SimulationSessionTests.cs
T
voltsrage 80b009fd23
CI / backend (push) Successful in 8m52s
CI / frontend (push) Failing after 1m39s
feature: Self-Service Clinical Testing Sessions
2026-08-06 04:03:04 +08:00

114 lines
3.9 KiB
C#

using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
[Collection("Integration")]
public class SimulationSessionTests : IAsyncLifetime
{
private readonly ApiFixture _fixture;
private ISimulationRunner _runner = null!;
private TestSimulationClientFactory _clientFactory = null!;
public SimulationSessionTests(ApiFixture fixture) => _fixture = fixture;
public async Task InitializeAsync()
{
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
await DbResetHelper.ResetAsync(db);
await DataSeeder.SeedThresholdsOnlyAsync(db, redis);
_runner = _fixture.Services.GetRequiredService<ISimulationRunner>();
_clientFactory = _fixture.SimulationClientFactory;
_clientFactory.HangOnCreate = false;
_clientFactory.FailOnCreate = false;
foreach (var run in _runner.ListRuns())
_runner.Cancel(run.RunId);
await WaitForAsync(() => !_runner.HasActiveRuns());
_runner.ClearRegistry();
}
public Task DisposeAsync()
{
_clientFactory.HangOnCreate = false;
_clientFactory.FailOnCreate = false;
return Task.CompletedTask;
}
[Fact]
public async Task StartSession_StartsAllScenarios()
{
_clientFactory.HangOnCreate = true;
var session = await _runner.StartSessionAsync(
"session-test-two", 60, "tester", CancellationToken.None);
session.RunIds.Should().HaveCount(2);
_runner.ListRuns().Count(r =>
r.Status is SimulationRunStatus.Pending or SimulationRunStatus.Running)
.Should().Be(2);
foreach (var runId in session.RunIds)
_runner.Cancel(runId);
await WaitForAsync(() => !_runner.HasActiveRuns());
}
[Fact]
public async Task StartSession_ExceedingConcurrency_StartsNothing()
{
_clientFactory.HangOnCreate = true;
var act = () => _runner.StartSessionAsync(
"session-test-three", 60, "tester", CancellationToken.None);
var ex = await act.Should().ThrowAsync<ConflictException>();
ex.Which.ErrorCode.Should().Be("SIMULATION_CONCURRENCY_LIMIT");
_runner.ListRuns().Should().BeEmpty();
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
(await db.SimulationRuns.CountAsync()).Should().Be(0);
}
[Fact]
public async Task StartSession_TagsRunsWithSessionId()
{
_clientFactory.HangOnCreate = true;
var session = await _runner.StartSessionAsync(
"session-test-one", null, "tester", CancellationToken.None);
session.SessionId.Should().Be("session-test-one");
var run = _runner.GetRun(session.RunIds[0])!;
run.SessionId.Should().Be("session-test-one");
run.Speed.Should().Be(120); // defaultSpeed from fixture manifest
using var scope = _fixture.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var row = await db.SimulationRuns.SingleAsync(r => r.Id == run.RunId);
row.SessionId.Should().Be("session-test-one");
_runner.Cancel(run.RunId);
await WaitForAsync(() => !_runner.HasActiveRuns());
}
private static async Task WaitForAsync(Func<bool> condition, TimeSpan? timeout = null)
{
var deadline = DateTimeOffset.UtcNow + (timeout ?? TimeSpan.FromSeconds(15));
while (DateTimeOffset.UtcNow < deadline)
{
if (condition())
return;
await Task.Delay(25);
}
throw new TimeoutException("Condition was not met within the timeout.");
}
}