fix(central-ui): FlowDebugService — re-flatten on each instance selection; safe Ask fallback
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -623,9 +623,9 @@ public sealed class FlowDebugServiceTests : IDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The picker, the prediction and the run of one instance share ONE flatten for the life of
|
||||
/// the scoped service (design 2026-09-08 §5) — a regression here means every keystroke on the
|
||||
/// page re-walks the template chain.
|
||||
/// One picker selection costs ONE flatten: the prediction and the run that follow it read the
|
||||
/// entry <see cref="IFlowDebugService.GetInstanceScriptsAsync"/> just refreshed (design
|
||||
/// 2026-09-08 §5). A regression here means every keystroke re-walks the template chain.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task GetInstanceScripts_ThenPredict_ThenRun_FlattenOnce()
|
||||
@@ -641,6 +641,35 @@ public sealed class FlowDebugServiceTests : IDisposable
|
||||
await _pipeline.Received(1).FlattenAndValidateAsync(9, Arg.Any<CancellationToken>(), false, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A scoped service lives for the whole Blazor circuit, so re-selecting the instance must
|
||||
/// re-flatten — otherwise a template edit or a redeploy mid-session leaves the picker, the
|
||||
/// parameter form and the Ask sizing stale for the rest of the session.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task GetInstanceScripts_CalledAgain_ReflattensAndRefreshes()
|
||||
{
|
||||
_templates.GetInstanceByIdAsync(9, Arg.Any<CancellationToken>())
|
||||
.Returns(new Instance("Sim01") { Id = 9, TemplateId = 10, SiteId = 1 });
|
||||
static Result<FlatteningPipelineResult> Flattened(params ResolvedScript[] scripts)
|
||||
=> Result<FlatteningPipelineResult>.Success(new FlatteningPipelineResult(
|
||||
new FlattenedConfiguration { InstanceUniqueName = "Sim01", TemplateId = 10, SiteId = 1, Scripts = scripts },
|
||||
"h", new ValidationResult()));
|
||||
_pipeline.FlattenAndValidateAsync(9, Arg.Any<CancellationToken>(), false, null).Returns(
|
||||
Flattened(new ResolvedScript { CanonicalName = "Manual", Code = "x", TriggerType = "Call" }),
|
||||
Flattened(
|
||||
new ResolvedScript { CanonicalName = "Manual", Code = "x", TriggerType = "Call" },
|
||||
new ResolvedScript { CanonicalName = "Added", Code = "x", TriggerType = "Call" }));
|
||||
var svc = CreateService(reply: null);
|
||||
|
||||
var first = await svc.GetInstanceScriptsAsync(9);
|
||||
var second = await svc.GetInstanceScriptsAsync(9);
|
||||
|
||||
Assert.Equal(["Manual"], first.Select(o => o.CanonicalName).ToList());
|
||||
Assert.Equal(["Added", "Manual"], second.Select(o => o.CanonicalName).ToList());
|
||||
await _pipeline.Received(2).FlattenAndValidateAsync(9, Arg.Any<CancellationToken>(), false, null);
|
||||
}
|
||||
|
||||
private sealed class StubAuth : AuthenticationStateProvider
|
||||
{
|
||||
private readonly ClaimsPrincipal _user;
|
||||
|
||||
Reference in New Issue
Block a user