fix(central-ui): exception subtitle parses inner/generic exception names; pill+badge test (Task 11 review)
This commit is contained in:
@@ -667,6 +667,16 @@ public class FlowGraphViewTests : BunitContext
|
||||
[InlineData(FlowStepOutcome.Failed, " ", "boom", "boom")]
|
||||
[InlineData(FlowStepOutcome.Failed, null, "boom", "boom")]
|
||||
[InlineData(FlowStepOutcome.Ok, "System.InvalidOperationException: nope", "boom", null)]
|
||||
// A wrapper chains its inner exceptions on the first line — the innermost is the one to act on.
|
||||
[InlineData(FlowStepOutcome.Failed,
|
||||
"System.AggregateException: One or more errors occurred. (Recipe 42 rejected) ---> System.InvalidOperationException: Recipe 42 rejected\n at X",
|
||||
"boom", "InvalidOperationException: Recipe 42 rejected")]
|
||||
[InlineData(FlowStepOutcome.Failed,
|
||||
"A.Outer: outer ---> B.Middle: middle ---> C.Innermost: the real one",
|
||||
"boom", "Innermost: the real one")]
|
||||
// The namespace is stripped only from the head of the name; a generic suffix stays verbatim.
|
||||
[InlineData(FlowStepOutcome.Failed, "MyApp.RecipeException`1[System.String]: msg", "boom", "RecipeException`1[System.String]: msg")]
|
||||
[InlineData(FlowStepOutcome.Failed, "RecipeException`1[System.String]: msg", "boom", "RecipeException`1[System.String]: msg")]
|
||||
public void ExceptionSubtitle_ParsesTheFirstLineOfTheDetail_OnlyForAFailedStep(
|
||||
FlowStepOutcome outcome, string? detail, string? message, string? expected)
|
||||
{
|
||||
@@ -678,12 +688,31 @@ public class FlowGraphViewTests : BunitContext
|
||||
[Fact]
|
||||
public void LogTitle_NamesOnlyTheNonZeroLevels_WithSingularAndPlural()
|
||||
{
|
||||
FlowLayoutNode Node(IReadOnlyList<FlowLogLine>? logs)
|
||||
=> new("k", FlowLane.Site, 0, 0, 0, LogGraph(logs: logs).Steps[0], null, false);
|
||||
Assert.Equal("1 error", FlowGraphView.LogTitle((1, 0, 0)));
|
||||
Assert.Equal("2 errors, 1 warning", FlowGraphView.LogTitle((2, 1, 0)));
|
||||
Assert.Equal("1 warning, 2 info", FlowGraphView.LogTitle((0, 1, 2)));
|
||||
Assert.Equal("3 info", FlowGraphView.LogTitle((0, 0, 3)));
|
||||
Assert.Equal(string.Empty, FlowGraphView.LogTitle((0, 0, 0)));
|
||||
}
|
||||
|
||||
Assert.Equal("1 error", FlowGraphView.LogTitle(Node([Line("error")])));
|
||||
Assert.Equal("2 errors, 1 warning", FlowGraphView.LogTitle(Node([Line("error"), Line("error"), Line("warn")])));
|
||||
Assert.Equal("1 warning, 2 info", FlowGraphView.LogTitle(Node([Line("warn"), Line("info"), Line("debug")])));
|
||||
Assert.Equal(string.Empty, FlowGraphView.LogTitle(Node(null)));
|
||||
[Fact]
|
||||
public void Render_OutboundNodeWithLogLines_ShowsBothThePillAndTheBadgeInTheFooter()
|
||||
{
|
||||
var correlation = Guid.NewGuid();
|
||||
var step = new FlowStep(Guid.NewGuid(), Root, null, FlowStepKind.ApiCall, FlowLane.External, "Delmia.AckRecipe",
|
||||
"Delivered · sync", T0, 212, FlowStepOutcome.Ok, null, null, null, "site-a", "node-a", "M1", "Delmia.AckRecipe", null,
|
||||
[new FlowLifecycleRow(Guid.NewGuid(), "ApiCall", "Delivered", T0, "node-a", null, 212)],
|
||||
correlation, null, [Line("warn"), Line("info")]);
|
||||
|
||||
var cut = Render<FlowGraphView>(p => p.Add(c => c.Graph, new FlowGraph([step], [], false, false)));
|
||||
|
||||
var foot = cut.Find("g[data-test='flow-node'][data-kind='ApiCall'] .fg-foot");
|
||||
Assert.Equal("Ok", foot.QuerySelector("[data-test='flow-node-pill']")!.TextContent.Trim());
|
||||
Assert.Equal("· sync", foot.QuerySelector(".fg-mode")!.TextContent.Trim());
|
||||
var badge = foot.QuerySelector("[data-test='flow-node-logs']")!;
|
||||
Assert.Equal(["! 1", "≡ 1"], badge.QuerySelectorAll("i").Select(i => i.TextContent.Trim()));
|
||||
Assert.Equal("1 warning, 1 info", badge.GetAttribute("title"));
|
||||
// A pill node has no subtitle line — the pill occupies the footer's left half.
|
||||
Assert.Null(foot.QuerySelector("[data-test='flow-node-subtitle']"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user