diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor index 1dbca632..1f74b668 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor @@ -122,7 +122,7 @@ { @line.OccurredAtUtc.ToUniversalTime().ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) - @line.Level + @line.Level @line.Source @line.Message @@ -449,9 +449,10 @@ { if (Step?.EventId != _tabStepId) { - // A different step: open on Log when it threw (D8), and start over on All. + // A different step: open on Log when it threw (D8), otherwise keep the operator's current + // tab when the new step still has it, and start the level filter over on All. _tabStepId = Step?.EventId; - _tab = HasException ? "Log" : "Input"; + _tab = HasException ? "Log" : (VisibleTabs.Contains(_tab) ? _tab : "Input"); _warnOnly = false; } else if (!VisibleTabs.Contains(_tab)) diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs index 2d9155d3..1c805e22 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs @@ -362,4 +362,58 @@ public class FlowStepDetailTests : BunitContext Assert.Contains("Tag write was not confirmed", row.QuerySelector(".fsd-line-exc")!.TextContent); Assert.Contains("System.TimeoutException", row.QuerySelector("details pre")!.TextContent); } + + [Fact] + public void SwitchingSteps_KeepsAStillValidTab() + { + var a = ScriptStep(FlowStepOutcome.Ok, "ProcessRecipeDownload", Guid.NewGuid()); + var b = ScriptStep(FlowStepOutcome.Ok, "AckRecipe", Guid.NewGuid()); + + var cut = Render(p => p.Add(x => x.Step, a)); + cut.Find("[data-test=flow-step-tab-timing]").Click(); + Assert.Contains("active", cut.Find("[data-test=flow-step-tab-timing]").ClassName); + + cut.Render(p => p.Add(x => x.Step, b)); + + Assert.Contains("active", cut.Find("[data-test=flow-step-tab-timing]").ClassName); + Assert.DoesNotContain("active", cut.Find("[data-test=flow-step-tab-input]").ClassName); + } + + [Fact] + public void RefreshingTheSameStep_KeepsTheTabAndTheLevelFilter() + { + // The page re-reads outcomes after a Live run and hands back a NEW FlowStep instance carrying + // the same EventId plus whatever rows have landed since — that must not disturb the panel. + var eventId = Guid.NewGuid(); + var exec = Guid.NewGuid(); + FlowStep Refreshed(IReadOnlyList logs) + => new(eventId, exec, null, FlowStepKind.ScriptRun, FlowLane.Site, "ProcessRecipeDownload", + "sub", T0, 1731, FlowStepOutcome.Failed, "{}", "{}", "Recipe 42 rejected by Galaxy (code 7)", + "site-a", "node-a", "DelmiaSim01", "ProcessRecipeDownload", null, null, null, ExceptionDetail, logs); + + var first = Refreshed([Line("info", "Recipe 42 requested", seq: 1), Line("warn", "ResultCode 7", seq: 2)]); + var cut = Render(p => p.Add(x => x.Step, first)); + + Assert.Equal("Log (2)", cut.Find("[data-test=flow-step-tab-log]").TextContent.Trim()); + cut.Find("[data-test=flow-step-log-filter-warn]").Click(); + Assert.Single(cut.FindAll("[data-test=flow-step-log-lines] tr[data-level]")); + cut.Find("[data-test=flow-step-tab-timing]").Click(); + + cut.Render(p => p.Add(x => x.Step, Refreshed( + [ + Line("info", "Recipe 42 requested", seq: 1), + Line("warn", "ResultCode 7", seq: 2), + Line("error", "Rejecting recipe 42", seq: 3), + ]))); + + Assert.Contains("active", cut.Find("[data-test=flow-step-tab-timing]").ClassName); + Assert.Equal("Log (3)", cut.Find("[data-test=flow-step-tab-log]").TextContent.Trim()); + + cut.Find("[data-test=flow-step-tab-log]").Click(); + Assert.Contains("btn-secondary", cut.Find("[data-test=flow-step-log-filter-warn]").ClassName); + var rows = cut.FindAll("[data-test=flow-step-log-lines] tr[data-level]"); + Assert.Equal(2, rows.Count); + Assert.Equal("warn", rows[0].GetAttribute("data-level")); + Assert.Equal("error", rows[1].GetAttribute("data-level")); + } }