feat(auditlog): multi-value AuditLogQueryFilter dimensions
This commit is contained in:
@@ -160,10 +160,10 @@ public class AuditExportEndpointsTests
|
||||
|
||||
await repo.Received().QueryAsync(
|
||||
Arg.Is<AuditLogQueryFilter>(f =>
|
||||
f.Channel == AuditChannel.ApiOutbound &&
|
||||
f.Kind == AuditKind.ApiCall &&
|
||||
f.Status == AuditStatus.Failed &&
|
||||
f.SourceSiteId == "plant-a" &&
|
||||
f.Channels != null && f.Channels.Count == 1 && f.Channels[0] == AuditChannel.ApiOutbound &&
|
||||
f.Kinds != null && f.Kinds.Count == 1 && f.Kinds[0] == AuditKind.ApiCall &&
|
||||
f.Statuses != null && f.Statuses.Count == 1 && f.Statuses[0] == AuditStatus.Failed &&
|
||||
f.SourceSiteIds != null && f.SourceSiteIds.Count == 1 && f.SourceSiteIds[0] == "plant-a" &&
|
||||
f.Target == "PaymentApi" &&
|
||||
f.Actor == "apikey-1" &&
|
||||
f.CorrelationId == Guid.Parse(correlationId) &&
|
||||
@@ -188,10 +188,10 @@ public class AuditExportEndpointsTests
|
||||
|
||||
await repo.Received().QueryAsync(
|
||||
Arg.Is<AuditLogQueryFilter>(f =>
|
||||
f.Channel == null &&
|
||||
f.Kind == null &&
|
||||
f.Status == null &&
|
||||
f.SourceSiteId == null &&
|
||||
f.Channels == null &&
|
||||
f.Kinds == null &&
|
||||
f.Statuses == null &&
|
||||
f.SourceSiteIds == null &&
|
||||
f.Target == null &&
|
||||
f.Actor == null &&
|
||||
f.CorrelationId == null &&
|
||||
@@ -216,7 +216,7 @@ public class AuditExportEndpointsTests
|
||||
_ = await response.Content.ReadAsStringAsync();
|
||||
|
||||
await repo.Received().QueryAsync(
|
||||
Arg.Is<AuditLogQueryFilter>(f => f.Channel == null),
|
||||
Arg.Is<AuditLogQueryFilter>(f => f.Channels == null),
|
||||
Arg.Any<AuditLogPaging>(),
|
||||
Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
@@ -77,7 +77,9 @@ public class AuditFilterBarTests : BunitContext
|
||||
cut.Find("[data-test=\"filter-apply\"]").Click();
|
||||
|
||||
Assert.NotNull(captured);
|
||||
Assert.Equal(AuditChannel.ApiOutbound, captured!.Channel);
|
||||
// Task 8: the filter dimension is multi-value now; ToFilter still collapses
|
||||
// the chip selection to a single-element list (Task 9 widens that).
|
||||
Assert.Equal(new[] { AuditChannel.ApiOutbound }, captured!.Channels);
|
||||
Assert.Equal("Plant-A-OPC", captured.Target);
|
||||
}
|
||||
|
||||
@@ -117,14 +119,14 @@ public class AuditFilterBarTests : BunitContext
|
||||
cut.Find("[data-test=\"filter-apply\"]").Click();
|
||||
|
||||
Assert.NotNull(captured);
|
||||
// Single-value filter contract: Failed leads the non-success set.
|
||||
Assert.Equal(AuditStatus.Failed, captured!.Status);
|
||||
// Single-value collapse contract (Task 8): Failed leads the non-success set.
|
||||
Assert.Equal(new[] { AuditStatus.Failed }, captured!.Statuses);
|
||||
|
||||
// Now pin an explicit Status chip — Errors-only must yield (chip wins).
|
||||
cut.Find("[data-test=\"chip-status-Delivered\"]").Click();
|
||||
cut.Find("[data-test=\"filter-apply\"]").Click();
|
||||
|
||||
Assert.Equal(AuditStatus.Delivered, captured!.Status);
|
||||
Assert.Equal(new[] { AuditStatus.Delivered }, captured!.Statuses);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -36,10 +36,10 @@ public class AuditLogPageExportUrlTests
|
||||
{
|
||||
var corr = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
|
||||
var filter = new AuditLogQueryFilter(
|
||||
Channel: AuditChannel.ApiOutbound,
|
||||
Kind: AuditKind.ApiCall,
|
||||
Status: AuditStatus.Failed,
|
||||
SourceSiteId: "plant-a",
|
||||
Channels: new[] { AuditChannel.ApiOutbound },
|
||||
Kinds: new[] { AuditKind.ApiCall },
|
||||
Statuses: new[] { AuditStatus.Failed },
|
||||
SourceSiteIds: new[] { "plant-a" },
|
||||
Target: "PaymentApi",
|
||||
Actor: "apikey-1",
|
||||
CorrelationId: corr,
|
||||
@@ -65,7 +65,7 @@ public class AuditLogPageExportUrlTests
|
||||
[Fact]
|
||||
public void BuildExportUrl_OnlyChannelSet_OmitsOtherParams()
|
||||
{
|
||||
var filter = new AuditLogQueryFilter(Channel: AuditChannel.Notification);
|
||||
var filter = new AuditLogQueryFilter(Channels: new[] { AuditChannel.Notification });
|
||||
|
||||
var url = AuditLogPage.BuildExportUrl(filter);
|
||||
|
||||
|
||||
@@ -197,7 +197,8 @@ public class AuditLogPageScaffoldTests : BunitContext
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
_queryService.Received().QueryAsync(
|
||||
Arg.Is<AuditLogQueryFilter>(f => f.SourceSiteId == "plant-a"),
|
||||
Arg.Is<AuditLogQueryFilter>(f =>
|
||||
f.SourceSiteIds != null && f.SourceSiteIds.Count == 1 && f.SourceSiteIds[0] == "plant-a"),
|
||||
Arg.Any<AuditLogPaging?>(),
|
||||
Arg.Any<CancellationToken>());
|
||||
});
|
||||
@@ -218,7 +219,8 @@ public class AuditLogPageScaffoldTests : BunitContext
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
_queryService.Received().QueryAsync(
|
||||
Arg.Is<AuditLogQueryFilter>(f => f.Status == AuditStatus.Failed),
|
||||
Arg.Is<AuditLogQueryFilter>(f =>
|
||||
f.Statuses != null && f.Statuses.Count == 1 && f.Statuses[0] == AuditStatus.Failed),
|
||||
Arg.Any<AuditLogPaging?>(),
|
||||
Arg.Any<CancellationToken>());
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@ public class AuditLogQueryServiceTests
|
||||
public async Task QueryAsync_ForwardsFilterAndPaging_ToRepository()
|
||||
{
|
||||
var repo = Substitute.For<IAuditLogRepository>();
|
||||
var filter = new AuditLogQueryFilter(Channel: AuditChannel.ApiOutbound);
|
||||
var filter = new AuditLogQueryFilter(Channels: new[] { AuditChannel.ApiOutbound });
|
||||
var paging = new AuditLogPaging(PageSize: 25);
|
||||
var expected = new List<AuditEvent>
|
||||
{
|
||||
@@ -179,7 +179,7 @@ public class AuditLogQueryServiceTests
|
||||
var scopeFactory = provider.GetRequiredService<IServiceScopeFactory>();
|
||||
var sut = new AuditLogQueryService(scopeFactory, EmptyAggregator());
|
||||
|
||||
var filter = new AuditLogQueryFilter(Channel: AuditChannel.ApiOutbound);
|
||||
var filter = new AuditLogQueryFilter(Channels: new[] { AuditChannel.ApiOutbound });
|
||||
|
||||
// Fire two QueryAsync calls in parallel. With scope-per-query each gets a
|
||||
// fresh DbContext, so this completes cleanly; with a shared scoped context
|
||||
|
||||
Reference in New Issue
Block a user