fix:
No SOFA trend chart or organ-system timeline No GCS trend chart or component history No qSOFA history view
This commit is contained in:
@@ -283,7 +283,7 @@ public class GapAnalysisFixTests : IAsyncLifetime
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
[Fact]
|
||||
public async Task QsofaHistory_ReturnsAlertRecords()
|
||||
public async Task QsofaHistory_ReturnsEvaluationRecords()
|
||||
{
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
@@ -304,20 +304,28 @@ public class GapAnalysisFixTests : IAsyncLifetime
|
||||
db.Patients.Add(patient);
|
||||
db.Encounters.Add(encounter);
|
||||
|
||||
db.ClinicalAlerts.Add(new ClinicalAlert
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
db.QsofaEvaluations.Add(new QsofaEvaluation
|
||||
{
|
||||
Id = Guid.NewGuid(), EncounterId = encounter.Id, PatientId = patient.Id,
|
||||
AlertType = AlertType.QsofaScreen, Severity = AlertSeverity.Warning,
|
||||
Details = "qSOFA >= 2", Status = AlertStatus.Open,
|
||||
TriggeredAt = DateTimeOffset.UtcNow.AddMinutes(-30)
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = encounter.Id,
|
||||
PatientId = patient.Id,
|
||||
ActiveCriteria = 1,
|
||||
RespRate = 24m,
|
||||
EvaluatedAt = now.AddMinutes(-30),
|
||||
CreatedAt = now,
|
||||
});
|
||||
db.ClinicalAlerts.Add(new ClinicalAlert
|
||||
db.QsofaEvaluations.Add(new QsofaEvaluation
|
||||
{
|
||||
Id = Guid.NewGuid(), EncounterId = encounter.Id, PatientId = patient.Id,
|
||||
AlertType = AlertType.QsofaScreen, Severity = AlertSeverity.Warning,
|
||||
Details = "qSOFA >= 2", Status = AlertStatus.Resolved,
|
||||
TriggeredAt = DateTimeOffset.UtcNow.AddMinutes(-10),
|
||||
ResolvedAt = DateTimeOffset.UtcNow
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = encounter.Id,
|
||||
PatientId = patient.Id,
|
||||
ActiveCriteria = 2,
|
||||
RespRate = 24m,
|
||||
SystolicBp = 95m,
|
||||
ScreenAlertFired = true,
|
||||
EvaluatedAt = now.AddMinutes(-10),
|
||||
CreatedAt = now,
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
@@ -325,7 +333,12 @@ public class GapAnalysisFixTests : IAsyncLifetime
|
||||
$"/api/v1/encounters/{encounter.Id}/qsofa/history?limit=10");
|
||||
|
||||
var data = resp.GetProperty("data");
|
||||
data.GetProperty("items").GetArrayLength().Should().Be(2);
|
||||
var items = data.GetProperty("items");
|
||||
items.GetArrayLength().Should().Be(2);
|
||||
|
||||
var latest = items[0];
|
||||
latest.GetProperty("activeCriteria").GetInt32().Should().Be(2);
|
||||
latest.GetProperty("screenAlertFired").GetBoolean().Should().BeTrue();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@@ -2,15 +2,23 @@ using FluentAssertions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StackExchange.Redis;
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
[Collection("Integration")]
|
||||
public class GcsScoringTests : IAsyncLifetime
|
||||
{
|
||||
private readonly ApiFixture _fixture;
|
||||
private readonly HttpClient _client;
|
||||
private Guid _encounterId;
|
||||
private Guid _patientId;
|
||||
|
||||
public GcsScoringTests(ApiFixture fixture) => _fixture = fixture;
|
||||
public GcsScoringTests(ApiFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
_client = fixture.CreateClient();
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
@@ -194,4 +202,58 @@ public class GcsScoringTests : IAsyncLifetime
|
||||
var score = await db.News2Scores.SingleAsync();
|
||||
score.ConsciousnessScore.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GcsHistory_ReturnsPaginatedScores()
|
||||
{
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
db.GcsScores.AddRange(
|
||||
new GcsScore
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = _encounterId,
|
||||
PatientId = _patientId,
|
||||
EyeScore = 4,
|
||||
VerbalScore = 5,
|
||||
MotorScore = 6,
|
||||
TotalScore = 15,
|
||||
Classification = "MILD",
|
||||
CalculatedAt = now.AddHours(-2),
|
||||
CreatedAt = now,
|
||||
},
|
||||
new GcsScore
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
EncounterId = _encounterId,
|
||||
PatientId = _patientId,
|
||||
EyeScore = 2,
|
||||
VerbalScore = 3,
|
||||
MotorScore = 3,
|
||||
TotalScore = 8,
|
||||
Classification = "SEVERE",
|
||||
CalculatedAt = now,
|
||||
CreatedAt = now,
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var resp = await _client.GetAsync(
|
||||
$"/api/v1/encounters/{_encounterId}/gcs/history?limit=10");
|
||||
resp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
var body = await resp.Content.ReadFromJsonAsync<JsonElement>();
|
||||
var items = body.GetProperty("data").GetProperty("items");
|
||||
items.GetArrayLength().Should().Be(2);
|
||||
|
||||
var latest = items[0];
|
||||
latest.GetProperty("totalScore").GetInt32().Should().Be(8);
|
||||
latest.GetProperty("eyeScore").GetInt32().Should().Be(2);
|
||||
latest.GetProperty("verbalScore").GetInt32().Should().Be(3);
|
||||
latest.GetProperty("motorScore").GetInt32().Should().Be(3);
|
||||
|
||||
var earliest = items[1];
|
||||
earliest.GetProperty("totalScore").GetInt32().Should().Be(15);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ public static class DbResetHelper
|
||||
DELETE FROM clinical_alerts;
|
||||
DELETE FROM gcs_scores;
|
||||
DELETE FROM sofa_scores;
|
||||
DELETE FROM qsofa_evaluations;
|
||||
DELETE FROM news2_scores;
|
||||
DELETE FROM observations;
|
||||
DELETE FROM external_resource_identifiers;
|
||||
|
||||
@@ -162,4 +162,25 @@ public class QsofaDetectorTests : IAsyncLifetime
|
||||
exists.Should().BeFalse("non-qSOFA codes must not create Redis state");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CriteriaChange_PersistsEvaluationHistory()
|
||||
{
|
||||
using var scope = _fixture.Services.CreateScope();
|
||||
var detector = scope.ServiceProvider.GetRequiredService<QsofaDetector>();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
await detector.ProcessObservationAsync(_encounterId, _patientId, "RESP_RATE", 24m);
|
||||
await detector.ProcessObservationAsync(_encounterId, _patientId, "SYSTOLIC_BP", 95m);
|
||||
|
||||
var evaluations = await db.QsofaEvaluations
|
||||
.Where(e => e.EncounterId == _encounterId)
|
||||
.OrderBy(e => e.EvaluatedAt)
|
||||
.ToListAsync();
|
||||
|
||||
evaluations.Should().HaveCount(2);
|
||||
evaluations[0].ActiveCriteria.Should().Be(1);
|
||||
evaluations[1].ActiveCriteria.Should().Be(2);
|
||||
evaluations[1].ScreenAlertFired.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user