merge: audit-config query fix + rig live-probe seed (register rows 46, 48) — ValueTuple serialized as {} fixed with AuditLogQueryResult record + ITuple guard; docker/seed-live-probe.sh
This commit is contained in:
@@ -238,6 +238,85 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
Assert.Equal(envelope.CorrelationId, response.CorrelationId);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// 2b. Configuration-change audit query -- result must not serialize to "{}"
|
||||
// ========================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Deferred-work register row 46: <c>audit-config query</c> returned the literal
|
||||
/// <c>{}</c> for every filter combination against the rig even though the
|
||||
/// <c>AuditLogEntries</c> rows were present. The handler returned the repository's
|
||||
/// <c>(Entries, TotalCount)</c> ValueTuple straight to <c>SerializeResult</c>, and
|
||||
/// System.Text.Json writes properties only — a tuple's <c>Item1</c>/<c>Item2</c> are
|
||||
/// fields, so the whole payload vanished with no error anywhere. Pins that the rows
|
||||
/// and the total actually reach the wire.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void QueryAuditLogCommand_ReturnsEntriesAndTotalCount()
|
||||
{
|
||||
var uiRepo = Substitute.For<ICentralUiRepository>();
|
||||
var entries = new List<Commons.Entities.Audit.AuditLogEntry>
|
||||
{
|
||||
new("alice", "Created", "Template", "7", "PumpTemplate")
|
||||
{
|
||||
Id = 1,
|
||||
Timestamp = new DateTimeOffset(2026, 8, 15, 12, 0, 0, TimeSpan.Zero)
|
||||
}
|
||||
};
|
||||
uiRepo.GetAuditLogEntriesAsync(
|
||||
Arg.Any<string?>(), Arg.Any<string?>(), Arg.Any<string?>(),
|
||||
Arg.Any<DateTimeOffset?>(), Arg.Any<DateTimeOffset?>(),
|
||||
Arg.Any<string?>(), Arg.Any<string?>(), Arg.Any<Guid?>(),
|
||||
Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||
.Returns(((IReadOnlyList<Commons.Entities.Audit.AuditLogEntry>)entries, 137));
|
||||
_services.AddScoped(_ => uiRepo);
|
||||
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(new QueryAuditLogCommand(PageSize: 25), "Administrator");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
Assert.NotEqual("{}", response.JsonData);
|
||||
Assert.Contains("PumpTemplate", response.JsonData);
|
||||
Assert.Contains("\"entries\"", response.JsonData);
|
||||
Assert.Contains("\"totalCount\":137", response.JsonData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guard for the whole class of bug behind row 46: any handler that returns a tuple
|
||||
/// silently serializes to <c>{}</c>. <see cref="ManagementActor.SerializeResult"/>
|
||||
/// now rejects tuples outright so the next occurrence is a loud failure rather than
|
||||
/// an empty response.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SerializeResult_TupleResult_ThrowsInsteadOfEmittingEmptyObject()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(
|
||||
() => ManagementActor.SerializeResult((new[] { "a" }, 1)));
|
||||
|
||||
Assert.Contains("tuple", ex.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pins the positive half of the guard: the named result record the handler now
|
||||
/// returns serializes to a populated, camelCased object.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SerializeResult_AuditLogQueryResult_EmitsEntriesAndTotalCount()
|
||||
{
|
||||
var json = ManagementActor.SerializeResult(new AuditLogQueryResult(
|
||||
new List<Commons.Entities.Audit.AuditLogEntry>
|
||||
{
|
||||
new("bob", "Deleted", "Instance", "3", "Pump1")
|
||||
},
|
||||
42));
|
||||
|
||||
Assert.Contains("\"entries\"", json);
|
||||
Assert.Contains("\"totalCount\":42", json);
|
||||
Assert.Contains("Pump1", json);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// 3. Template list test -- verify data flows through
|
||||
// ========================================================================
|
||||
|
||||
Reference in New Issue
Block a user