feat: stitch page-printer tables into one roster and add chapter team-count tokens
When New page per record is off, a single-table template shares one header across records. Event and team pages can print regional/state team counts and nationals eligibility. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
using Core.Printing;
|
||||
|
||||
namespace Tests.Printing;
|
||||
|
||||
[TestFixture]
|
||||
public class MarkdownTableStencil_Tests
|
||||
{
|
||||
private const string Roster = """
|
||||
| Name | Grade |
|
||||
| --- | --- |
|
||||
| {{LastNameFirstName}} | {{Grade}} |
|
||||
""";
|
||||
|
||||
[Test]
|
||||
public void TryParse_SingleTable_SplitsPrefixHeaderBodySuffix()
|
||||
{
|
||||
var template = """
|
||||
# Rankings
|
||||
|
||||
| Name | 1st |
|
||||
| --- | --- |
|
||||
| {{LastNameFirstName}} | {{Rank1}} |
|
||||
|
||||
{{Legend}}
|
||||
""";
|
||||
|
||||
Assert.That(MarkdownTableStencil.TryParse(template, out var stencil), Is.True);
|
||||
Assert.That(stencil!.Prefix, Does.Contain("# Rankings"));
|
||||
Assert.That(stencil.Header, Does.Contain("| Name | 1st |"));
|
||||
Assert.That(stencil.Header, Does.Contain("| --- | --- |"));
|
||||
Assert.That(stencil.Body.Trim(), Is.EqualTo("| {{LastNameFirstName}} | {{Rank1}} |"));
|
||||
Assert.That(stencil.Suffix, Does.Contain("{{Legend}}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_NoTable_Fails()
|
||||
{
|
||||
Assert.That(MarkdownTableStencil.TryParse("# Interview\n\n{{FirstName}}", out _), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_TwoTables_Fails()
|
||||
{
|
||||
var template = """
|
||||
| Grade | Time |
|
||||
| --- | --- |
|
||||
| {{Grade}} | {{Interview Time}} |
|
||||
|
||||
| 1st | 2nd |
|
||||
| --- | --- |
|
||||
| {{Rank1}} | {{Rank2}} |
|
||||
""";
|
||||
|
||||
Assert.That(MarkdownTableStencil.TryParse(template, out _), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParse_HeaderOnly_Fails()
|
||||
{
|
||||
Assert.That(MarkdownTableStencil.TryParse("| Name |\n| --- |\n", out _), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Stitch_TwoStudents_HeaderOnceAndTwoBodyRows()
|
||||
{
|
||||
Assert.That(MarkdownTableStencil.TryParse(Roster, out var stencil), Is.True);
|
||||
|
||||
var merged = stencil!.Stitch(
|
||||
string.Empty,
|
||||
[
|
||||
NoteTemplateMerger.Merge(stencil.Body, Map(("LastNameFirstName", "Cole, Aria"), ("Grade", "6"))),
|
||||
NoteTemplateMerger.Merge(stencil.Body, Map(("LastNameFirstName", "Dean, Lucas"), ("Grade", "7")))
|
||||
],
|
||||
string.Empty);
|
||||
|
||||
Assert.That(CountOccurrences(merged, "| Name | Grade |"), Is.EqualTo(1));
|
||||
Assert.That(CountOccurrences(merged, "| --- | --- |"), Is.EqualTo(1));
|
||||
Assert.That(merged, Does.Contain("| Cole, Aria | 6 |"));
|
||||
Assert.That(merged, Does.Contain("| Dean, Lucas | 7 |"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Stitch_AttributesRow_RepeatsPerRecord()
|
||||
{
|
||||
var template = """
|
||||
| 1st | 2nd |
|
||||
| --- | --- |
|
||||
| {{Rank1}} | {{Rank2}} |
|
||||
| {{Rank1.Attributes}} | {{Rank2.Attributes}} |
|
||||
""";
|
||||
|
||||
Assert.That(MarkdownTableStencil.TryParse(template, out var stencil), Is.True);
|
||||
|
||||
var merged = stencil!.Stitch(
|
||||
string.Empty,
|
||||
[
|
||||
NoteTemplateMerger.Merge(stencil.Body, Map(("Rank1", "Coding"), ("Rank2", "Flight"), ("Rank1.Attributes", "I"), ("Rank2.Attributes", "T"))),
|
||||
NoteTemplateMerger.Merge(stencil.Body, Map(("Rank1", "Drone"), ("Rank2", "Robotics"), ("Rank1.Attributes", "R"), ("Rank2.Attributes", "O")))
|
||||
],
|
||||
string.Empty);
|
||||
|
||||
Assert.That(CountOccurrences(merged, "| Coding | Flight |"), Is.EqualTo(1));
|
||||
Assert.That(CountOccurrences(merged, "| I | T |"), Is.EqualTo(1));
|
||||
Assert.That(CountOccurrences(merged, "| Drone | Robotics |"), Is.EqualTo(1));
|
||||
Assert.That(CountOccurrences(merged, "| R | O |"), Is.EqualTo(1));
|
||||
Assert.That(CountOccurrences(merged, "| --- | --- |"), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> Map(params (string Key, string Value)[] pairs)
|
||||
{
|
||||
var tokens = PrintTokenMap.Create();
|
||||
foreach (var (key, value) in pairs)
|
||||
tokens[key] = value;
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private static int CountOccurrences(string haystack, string needle)
|
||||
{
|
||||
var count = 0;
|
||||
var index = 0;
|
||||
while ((index = haystack.IndexOf(needle, index, StringComparison.Ordinal)) >= 0)
|
||||
{
|
||||
count++;
|
||||
index += needle.Length;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,13 @@ public class PrintFieldCatalog_Tests
|
||||
{
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Team), Does.Contain("EventName"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Team), Does.Contain("EventAttributes"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Team), Does.Contain("NationalEligibility"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Team), Does.Contain("RegionalTeamCount"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Team), Does.Contain("StateTeamCount"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain("RegionalEvent"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain("NationalEligibility"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain("RegionalTeamCount"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain("StateTeamCount"));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain(NoteTemplateMerger.RankedStudentsToken));
|
||||
Assert.That(PrintFieldCatalog.BuiltInFor(PrintEntityType.Event), Does.Contain("EventAttributes"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user