Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions TrayApp.Test/StatusReportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ public void Build_WithAStatusAndDetails_AppendsThemInOrder()
Assert.Contains("systemd-inhibit", report, StringComparison.Ordinal);
}

[TestMethod]
public void Build_WithALongDetailLabel_KeepsAGapAndAlignsEveryValue()
{
string report = StatusReport.Build(
"demo",
"on",
[new StatusDetail("Power assertion", () => "held"), new StatusDetail("Inhibitor path", () => "/usr/bin/systemd-inhibit")]);

Assert.Contains("Power assertion: ", report, StringComparison.Ordinal);
Assert.Contains("Inhibitor path: ", report, StringComparison.Ordinal);

string[] rows = report.Split('\n')[1..];
int column = rows[0].IndexOf(':', StringComparison.Ordinal) + 1;
while (rows[0][column] == ' ')
{
column++;
}

foreach (string row in rows)
{
string line = row.TrimEnd('\r');
Assert.AreEqual(' ', line[column - 1], $"Row \"{line}\" has no gap before its value column.");
Assert.AreNotEqual(' ', line[column], $"Row \"{line}\" does not start its value at column {column}.");
}
Comment thread
matt-edmondson marked this conversation as resolved.
Resolved
}

[TestMethod]
public void Build_WithAThrowingDetail_ReportsTheErrorInItsRowAndKeepsTheRest()
{
Expand Down
32 changes: 23 additions & 9 deletions TrayApp/StatusReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace ktsu.TrayApp;
public static class StatusReport
{
private const int LabelWidth = 15;
private const int MinimumGap = 1;

/// <summary>
/// Describes what a tool can do on this machine.
Expand All @@ -33,19 +34,35 @@ public static string Build(string name, string? status, IReadOnlyList<StatusDeta
Ensure.NotNull(name);
Ensure.NotNull(details);

StringBuilder report = new();
report.AppendLine(HelpText.Version(name));
AppendRow(report, "Platform", string.Create(CultureInfo.InvariantCulture, $"{RuntimeInformation.OSDescription.Trim()} ({RuntimeInformation.RuntimeIdentifier})"));
AppendRow(report, "Tray icon", DesktopSession.Explanation);
List<(string Label, string Value)> rows =
[
("Platform", string.Create(CultureInfo.InvariantCulture, $"{RuntimeInformation.OSDescription.Trim()} ({RuntimeInformation.RuntimeIdentifier})")),
("Tray icon", DesktopSession.Explanation),
];

if (status is not null)
{
AppendRow(report, "State", status);
rows.Add(("State", status));
}

foreach (StatusDetail detail in details)
{
AppendRow(report, detail.Label, Read(detail.Value));
rows.Add((detail.Label, Read(detail.Value)));
}

// The value column starts after the longest label, so a long label still has a gap before its value
// and every value lines up with the others.
int labelWidth = LabelWidth;
foreach ((string label, _) in rows)
{
labelWidth = Math.Max(labelWidth, label.Length + MinimumGap + 1);
}

StringBuilder report = new();
report.AppendLine(HelpText.Version(name));
foreach ((string label, string value) in rows)
{
report.AppendLine($"{(label + ':').PadRight(labelWidth)}{value}");
}

// Every row above appended a newline; the report is quoted and compared in tests, so it ends where
Expand Down Expand Up @@ -74,7 +91,4 @@ internal static string Read(Func<string> getter)
return "error: " + ex.Message;
}
}

private static void AppendRow(StringBuilder report, string label, string value) =>
report.AppendLine($"{(label + ':').PadRight(LabelWidth)}{value}");
}
Loading