feat(ui): notification detail modal shows message body + recipients
This commit is contained in:
@@ -29,6 +29,27 @@ public class NotificationReportDetailModalTests : BunitContext
|
||||
private readonly ActorSystem _system = ActorSystem.Create("notif-report-modal-tests");
|
||||
private readonly CommunicationService _comms;
|
||||
|
||||
private NotificationDetailResponse _detailReply =
|
||||
new("d", true, null, new NotificationDetail(
|
||||
NotificationId: "notif-aaaaaaaa-1111-full-id",
|
||||
Type: "Email",
|
||||
ListName: "Ops On-Call",
|
||||
Subject: "Pump fault at Plant-A",
|
||||
Body: "Pump-001 tripped on overcurrent at 14:32. Investigate immediately.",
|
||||
Status: "Parked",
|
||||
RetryCount: 3,
|
||||
LastError: "SMTP timeout connecting to mail relay",
|
||||
ResolvedTargets: "[\"ops@example.com\",\"oncall@example.com\"]",
|
||||
TypeData: null,
|
||||
SourceSiteId: "plant-a",
|
||||
SourceInstanceId: "Pump-001",
|
||||
SourceScript: "PumpFault.csx",
|
||||
SiteEnqueuedAt: DateTimeOffset.UtcNow.AddMinutes(-31),
|
||||
CreatedAt: DateTimeOffset.UtcNow.AddMinutes(-30),
|
||||
LastAttemptAt: DateTimeOffset.UtcNow.AddMinutes(-5),
|
||||
NextAttemptAt: null,
|
||||
DeliveredAt: null));
|
||||
|
||||
private NotificationOutboxQueryResponse _queryReply =
|
||||
new("q", true, null, new List<NotificationSummary>
|
||||
{
|
||||
@@ -149,6 +170,90 @@ public class NotificationReportDetailModalTests : BunitContext
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Modal_FetchesAndShowsBody()
|
||||
{
|
||||
var cut = Render<NotificationReportPage>();
|
||||
cut.WaitForState(() => cut.Markup.Contains("Pump fault at Plant-A"));
|
||||
|
||||
var row = cut.FindAll("tbody tr")
|
||||
.First(r => r.TextContent.Contains("Pump fault at Plant-A"));
|
||||
row.DoubleClick();
|
||||
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var modal = cut.Find(".modal.show");
|
||||
Assert.Contains(
|
||||
"Pump-001 tripped on overcurrent at 14:32. Investigate immediately.",
|
||||
modal.TextContent);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Modal_ShowsRecipients_FromResolvedTargets()
|
||||
{
|
||||
var cut = Render<NotificationReportPage>();
|
||||
cut.WaitForState(() => cut.Markup.Contains("Pump fault at Plant-A"));
|
||||
|
||||
var row = cut.FindAll("tbody tr")
|
||||
.First(r => r.TextContent.Contains("Pump fault at Plant-A"));
|
||||
row.DoubleClick();
|
||||
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var modal = cut.Find(".modal.show");
|
||||
Assert.Contains("ops@example.com", modal.TextContent);
|
||||
Assert.Contains("oncall@example.com", modal.TextContent);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Modal_ShowsListFallback_WhenResolvedTargetsNull()
|
||||
{
|
||||
_detailReply = _detailReply with
|
||||
{
|
||||
Detail = _detailReply.Detail! with { ResolvedTargets = null },
|
||||
};
|
||||
|
||||
var cut = Render<NotificationReportPage>();
|
||||
cut.WaitForState(() => cut.Markup.Contains("Pump fault at Plant-A"));
|
||||
|
||||
var row = cut.FindAll("tbody tr")
|
||||
.First(r => r.TextContent.Contains("Pump fault at Plant-A"));
|
||||
row.DoubleClick();
|
||||
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var modal = cut.Find(".modal.show");
|
||||
Assert.Contains("Not yet resolved", modal.TextContent);
|
||||
Assert.Contains("Ops On-Call", modal.TextContent);
|
||||
Assert.Contains("at delivery time", modal.TextContent);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Modal_ShowsError_WhenDetailFetchFails()
|
||||
{
|
||||
_detailReply = new NotificationDetailResponse("d", false, "detail store unavailable", null);
|
||||
|
||||
var cut = Render<NotificationReportPage>();
|
||||
cut.WaitForState(() => cut.Markup.Contains("Pump fault at Plant-A"));
|
||||
|
||||
var row = cut.FindAll("tbody tr")
|
||||
.First(r => r.TextContent.Contains("Pump fault at Plant-A"));
|
||||
row.DoubleClick();
|
||||
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var modal = cut.Find(".modal.show");
|
||||
// The error surfaces in the body/recipient sections...
|
||||
Assert.Contains("detail store unavailable", modal.TextContent);
|
||||
// ...but the summary fields (from the grid row) still render.
|
||||
Assert.Contains("Ops On-Call", modal.TextContent);
|
||||
Assert.Contains("notif-aaaaaaaa-1111-full-id", modal.TextContent);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
@@ -163,6 +268,10 @@ public class NotificationReportDetailModalTests : BunitContext
|
||||
public ScriptedOutboxActor(NotificationReportDetailModalTests test)
|
||||
{
|
||||
Receive<NotificationOutboxQueryRequest>(_ => Sender.Tell(test._queryReply));
|
||||
Receive<NotificationDetailRequest>(r => Sender.Tell(test._detailReply with
|
||||
{
|
||||
CorrelationId = r.CorrelationId,
|
||||
}));
|
||||
Receive<RetryNotificationRequest>(r =>
|
||||
Sender.Tell(new RetryNotificationResponse(r.CorrelationId, true, null)));
|
||||
Receive<DiscardNotificationRequest>(r =>
|
||||
|
||||
Reference in New Issue
Block a user