diff --git a/Darling/Darling.Tests/Viewer4571Tests.cs b/Darling/Darling.Tests/Viewer4571Tests.cs new file mode 100644 index 0000000000..6a8516d6c2 --- /dev/null +++ b/Darling/Darling.Tests/Viewer4571Tests.cs @@ -0,0 +1,23 @@ +using PerformanceMonitor.PlanAnalysis; +using Xunit; + +namespace Darling.Tests; + +/// +/// Pins the Wait Stats card header's tooltip (#4571), matching erikdarlingdata/PerformanceStudio's +/// desktop viewer: null when there are no waits, otherwise the total wait time and wait-type count. +/// +public class Viewer4571Tests +{ + [Fact] + public void WaitStatsHeaderTooltip_NoWaits_IsNull() + { + Assert.Null(PlanDisplayText.WaitStatsHeaderTooltip(0, 0)); + } + + [Fact] + public void WaitStatsHeaderTooltip_WithWaits_DescribesCountAndTotal() + { + Assert.Equal("1,234 ms of waits across 3 wait types", PlanDisplayText.WaitStatsHeaderTooltip(3, 1234)); + } +} diff --git a/PerformanceMonitor.PlanAnalysis/PlanDisplayText.cs b/PerformanceMonitor.PlanAnalysis/PlanDisplayText.cs index 1641c18ec8..a8b9eab941 100644 --- a/PerformanceMonitor.PlanAnalysis/PlanDisplayText.cs +++ b/PerformanceMonitor.PlanAnalysis/PlanDisplayText.cs @@ -17,6 +17,13 @@ public static class PlanDisplayText public static string? ParseErrorMessage(ParsedPlan plan) => plan.ParseError == null ? null : $"This plan couldn't be parsed: {plan.ParseError}"; + /// + /// The Wait Stats card's header tooltip, matching erikdarlingdata/PerformanceStudio's desktop viewer: + /// shown only when there are waits to describe. + /// + public static string? WaitStatsHeaderTooltip(int waitCount, long totalWaitMs) => + waitCount > 0 ? $"{totalWaitMs:N0} ms of waits across {waitCount} wait types" : null; + /// /// The CPU:Elapsed ratio shown in the runtime summary, matching /// erikdarlingdata/PerformanceStudio@28d4c74's row: CPU time with external-wait time diff --git a/PerformanceMonitor.Ui/PlanViewerControl.Properties.cs b/PerformanceMonitor.Ui/PlanViewerControl.Properties.cs index 29ddfa46cd..fdec547814 100644 --- a/PerformanceMonitor.Ui/PlanViewerControl.Properties.cs +++ b/PerformanceMonitor.Ui/PlanViewerControl.Properties.cs @@ -1067,6 +1067,7 @@ private void ShowWaitStats(List waits, bool isActualPlan) if (waits.Count == 0) { WaitStatsHeader.Text = "Wait Stats"; + WaitStatsHeader.ToolTip = PlanDisplayText.WaitStatsHeaderTooltip(0, 0); WaitStatsEmpty.Text = isActualPlan ? "No wait stats recorded" : "No wait stats (estimated plan)"; @@ -1081,6 +1082,7 @@ private void ShowWaitStats(List waits, bool isActualPlan) var totalWait = sorted.Sum(w => w.WaitTimeMs); WaitStatsHeader.Text = $" Wait Stats \u2014 {totalWait:N0}ms total"; + WaitStatsHeader.ToolTip = PlanDisplayText.WaitStatsHeaderTooltip(sorted.Count, totalWait); var longestName = sorted.Max(w => w.WaitType.Length); var nameColWidth = longestName * 6.5 + 10;