feat(cli): flow-debug run-script — run a site script by name through the flow debugger

Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
Joseph Doherty
2026-09-08 01:13:15 -04:00
parent 001123d930
commit 067a858ce9
3 changed files with 127 additions and 12 deletions
@@ -24,13 +24,13 @@ public class FlowDebugCommandsTests
private static readonly JsonSerializerOptions CamelCase = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
[Fact]
public void Build_RegistersTheThreeSubcommands_WithTheirRequiredOptions()
public void Build_RegistersTheFourSubcommands_WithTheirRequiredOptions()
{
var group = FlowDebugCommands.Build(Url, Format, Username, Password);
Assert.Equal("flow-debug", group.Name);
var names = group.Subcommands.Select(c => c.Name).ToList();
Assert.Equal(["run-method", "run-value-change", "replay"], names);
Assert.Equal(["run-method", "run-script", "run-value-change", "replay"], names);
var runMethod = group.Subcommands.Single(c => c.Name == "run-method");
Assert.Contains(runMethod.Options, o => o.Name == "--method-id" && o.Required);
@@ -38,6 +38,14 @@ public class FlowDebugCommandsTests
Assert.Contains(runMethod.Options, o => o.Name == "--timeout-seconds" && !o.Required);
Assert.DoesNotContain(runMethod.Options, o => o.Name == "--wait-seconds");
var runScript = group.Subcommands.Single(c => c.Name == "run-script");
Assert.Contains(runScript.Options, o => o.Name == "--instance-id" && o.Required);
Assert.Contains(runScript.Options, o => o.Name == "--script" && o.Required);
Assert.Contains(runScript.Options, o => o.Name == "--params" && !o.Required);
Assert.Contains(runScript.Options, o => o.Name == "--value" && !o.Required);
Assert.Contains(runScript.Options, o => o.Name == "--wait-seconds" && !o.Required);
Assert.Contains(runScript.Options, o => o.Name == "--timeout-seconds" && !o.Required);
var runValueChange = group.Subcommands.Single(c => c.Name == "run-value-change");
Assert.Contains(runValueChange.Options, o => o.Name == "--instance-id" && o.Required);
Assert.Contains(runValueChange.Options, o => o.Name == "--attribute" && o.Required);
@@ -49,6 +57,17 @@ public class FlowDebugCommandsTests
Assert.Contains(replay.Options, o => o.Name == "--execution-id" && o.Required);
}
[Fact]
public void RunScript_Defaults_WaitSeconds45_TimeoutSeconds120()
{
var group = FlowDebugCommands.Build(Url, Format, Username, Password);
var parse = group.Parse("run-script --instance-id 7 --script Manual --params {\"n\":3}");
Assert.Empty(parse.Errors);
var cmd = group.Subcommands.Single(c => c.Name == "run-script");
Assert.Equal(45, parse.GetValue((Option<int>)cmd.Options.Single(o => o.Name == "--wait-seconds")));
Assert.Equal(120, parse.GetValue((Option<int>)cmd.Options.Single(o => o.Name == "--timeout-seconds")));
}
[Fact]
public void RunMethod_TimeoutSecondsDefaultsTo120()
{
@@ -87,6 +106,7 @@ public class FlowDebugCommandsTests
// The CLI derives the wire command name from the record type; a rename on either
// side would throw here rather than at runtime.
Assert.False(string.IsNullOrWhiteSpace(ManagementCommandRegistry.GetCommandName(typeof(FlowDebugRunMethodCommand))));
Assert.False(string.IsNullOrWhiteSpace(ManagementCommandRegistry.GetCommandName(typeof(FlowDebugRunScriptCommand))));
Assert.False(string.IsNullOrWhiteSpace(ManagementCommandRegistry.GetCommandName(typeof(FlowDebugRunValueChangeCommand))));
Assert.False(string.IsNullOrWhiteSpace(ManagementCommandRegistry.GetCommandName(typeof(FlowDebugReplayCommand))));
}