23157d2bcf
Flow Debugger (design 2026-09-05 §5.2): bit NOT NULL DEFAULT 0 column + EF migration 20260906034113 with its docs/plans/sql production twin. CreateApiMethodCommand gains TraceAllCalls=false; UpdateApiMethodCommand gains bool? TraceAllCalls (null = unchanged so an older CLI never resets it). Management result echoes the flag; CLI create/update expose --trace-all-calls; README carries the ~7-rows-per-call warning. Claude-Session: https://claude.ai/code/session_01GSLkkHKz9JrAtmJjmQK3cP
89 lines
3.7 KiB
C#
89 lines
3.7 KiB
C#
using Akka.Actor;
|
|
using Akka.TestKit.Xunit2;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NSubstitute;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.InboundApi;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.ManagementService.Tests;
|
|
|
|
/// <summary>
|
|
/// Flow Debugger design 2026-09-05 §5.2: <c>ApiMethod.TraceAllCalls</c> round-trips through the
|
|
/// Create/Update management commands, defaults to off, and an Update that omits it (an older
|
|
/// CLI) leaves the stored value unchanged.
|
|
/// </summary>
|
|
public class ApiMethodTraceAllCallsTests : TestKit, IDisposable
|
|
{
|
|
private readonly ServiceCollection _services = new();
|
|
private readonly IInboundApiRepository _apiRepo = Substitute.For<IInboundApiRepository>();
|
|
|
|
public ApiMethodTraceAllCallsTests()
|
|
{
|
|
_services.AddScoped(_ => _apiRepo);
|
|
_services.AddScoped(_ => Substitute.For<IAuditService>());
|
|
_apiRepo.SaveChangesAsync(Arg.Any<CancellationToken>()).Returns(1);
|
|
}
|
|
|
|
private IActorRef CreateActor() =>
|
|
Sys.ActorOf(Props.Create(() => new ManagementActor(
|
|
_services.BuildServiceProvider(), NullLogger<ManagementActor>.Instance)));
|
|
|
|
private static ManagementEnvelope Envelope(object command) =>
|
|
new(new AuthenticatedUser("designer", "Designer", new[] { "Designer" }, Array.Empty<string>()),
|
|
command, Guid.NewGuid().ToString("N"));
|
|
|
|
void IDisposable.Dispose() => Shutdown();
|
|
|
|
[Fact]
|
|
public void Commands_DefaultToUntraced_ForTheFiveArgConstructor()
|
|
{
|
|
Assert.False(new CreateApiMethodCommand("m", "return 1;", 30, null, null).TraceAllCalls);
|
|
Assert.Null(new UpdateApiMethodCommand(1, "return 1;", 30, null, null).TraceAllCalls);
|
|
Assert.False(new ApiMethod("m", "return 1;").TraceAllCalls);
|
|
}
|
|
|
|
[Fact]
|
|
public void Create_WithTraceAllCalls_PersistsTheFlag_AndEchoesItInTheResult()
|
|
{
|
|
ApiMethod? added = null;
|
|
_apiRepo.AddApiMethodAsync(Arg.Do<ApiMethod>(m => added = m), Arg.Any<CancellationToken>())
|
|
.Returns(Task.CompletedTask);
|
|
|
|
CreateActor().Tell(Envelope(new CreateApiMethodCommand("Traced", "return 1;", 30, null, null, TraceAllCalls: true)));
|
|
|
|
var response = ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(10));
|
|
Assert.NotNull(added);
|
|
Assert.True(added!.TraceAllCalls);
|
|
Assert.Contains("\"traceAllCalls\":true", response.JsonData.Replace(" ", ""));
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_WithExplicitFalse_ClearsTheFlag()
|
|
{
|
|
var existing = new ApiMethod("M", "return 1;") { Id = 7, TimeoutSeconds = 10, TraceAllCalls = true };
|
|
_apiRepo.GetApiMethodByIdAsync(7, Arg.Any<CancellationToken>()).Returns(existing);
|
|
|
|
CreateActor().Tell(Envelope(new UpdateApiMethodCommand(7, "return 2;", 10, null, null, TraceAllCalls: false)));
|
|
|
|
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(10));
|
|
Assert.False(existing.TraceAllCalls);
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_OmittingTheFlag_LeavesTheStoredValueUnchanged()
|
|
{
|
|
var existing = new ApiMethod("M", "return 1;") { Id = 7, TimeoutSeconds = 10, TraceAllCalls = true };
|
|
_apiRepo.GetApiMethodByIdAsync(7, Arg.Any<CancellationToken>()).Returns(existing);
|
|
|
|
// The 5-arg shape an older CLI sends: TraceAllCalls == null.
|
|
CreateActor().Tell(Envelope(new UpdateApiMethodCommand(7, "return 2;", 10, null, null)));
|
|
|
|
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(10));
|
|
Assert.True(existing.TraceAllCalls);
|
|
Assert.Equal("return 2;", existing.Script);
|
|
}
|
|
}
|