Files
Nonemm/tests/Nonemm.Session.Tests/StatisticsTableTests.cs
T
erikbrockoandClaude Opus 5 6e24e00ec8 Copy the statistics table and graph to the clipboard
Copy All takes whichever tab is open, as N1MM's does: the table off the table
tab, a picture of the graph off the graph tab. Copy Table as Text and Copy
Graph as Image do either one from either tab.

`StatisticsTable` lays the pivot out as the window prints it — the headings,
the rows, the Total line — and pads it into columns for the text form, so the
grid, the clipboard and Print to File all say the same thing.

X11 asks for a picture when the other program pastes rather than when it is
copied, so the bitmap given to the clipboard is held until the clipboard is
given a different one. Disposing it at the end of the copy killed the program
on the next paste; the table pasted into a second Avalonia program reads back
lined up, and the picture reads back as a 916x438 bitmap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PdAYHcdRktqKry7nk414TU
2026-09-04 07:59:22 +00:00

79 lines
2.5 KiB
C#

using Nonemm.Core;
namespace Nonemm.Session.Tests;
public class StatisticsTableTests
{
private static readonly DateTime Start = new(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static Qso Contact(double kilohertz, Mode? mode = null, int minute = 0) => new()
{
Id = Qso.NewId(),
TimestampUtc = Start.AddMinutes(minute),
Call = Callsign.Parse("DL1ABC"),
Frequency = Frequency.FromKilohertz(kilohertz),
Mode = mode ?? Modes.Cw,
ContestName = "CQWW",
};
private static StatisticsTable Of(IReadOnlyList<Qso> log, string row = "Band", string column = "Mode") =>
StatisticsTable.Of(StatisticsPivot.Of(
log,
StatisticsFields.Find(StatisticsFields.Rows, row),
StatisticsFields.Find(StatisticsFields.Columns, column),
Start));
[Fact]
public void HeadsTheCountsWithTheColumnValuesAndEndsWithTotAndAccum()
{
StatisticsTable table = Of([Contact(14_030), Contact(7_030, Modes.Usb)]);
Assert.Equal(["Band", "CW", "USB", "Tot", "Accum"], table.Headings);
Assert.Equal(1, table.LabelColumns);
}
[Fact]
public void PutsTheTotalLineLast()
{
StatisticsTable table = Of([Contact(14_030), Contact(14_040), Contact(7_030)]);
Assert.Equal(["40M", "1", "1", "1"], table.Rows[0]);
Assert.Equal(["20M", "2", "2", "3"], table.Rows[1]);
Assert.Equal(["Total", "3", "3", "3"], table.Rows[^1]);
}
[Fact]
public void LinesTheColumnsUpUnderTheirHeadings()
{
string text = Of([Contact(14_030), Contact(3_530, Modes.Usb), Contact(3_540, Modes.Usb)]).ToText();
Assert.Equal(
"""
Band CW USB Tot Accum
80M 2 2 2
20M 1 1 3
Total 1 2 3 3
""",
text.TrimEnd('\n'));
}
[Fact]
public void KeepsTheTwoLabelColumnsOfAFieldThatHasThem()
{
StatisticsTable table = Of([Contact(14_030, minute: 5), Contact(14_040, minute: 70)], row: "Hour");
Assert.Equal(2, table.LabelColumns);
Assert.Equal(["Day", "Hr", "CW", "Tot", "Accum"], table.Headings);
Assert.Equal(["2026-01-01", "00", "1", "1", "1"], table.Rows[0]);
Assert.Equal(["Total", "", "2", "2", "2"], table.Rows[^1]);
}
[Fact]
public void LeavesNoSpacesHangingOffTheEndOfALine()
{
string text = Of([Contact(14_030)]).ToText();
Assert.All(text.Split('\n'), line => Assert.Equal(line.TrimEnd(), line));
}
}