|
| 1 | +using MarkupString.Ansi; |
| 2 | +using MarkupString.Html; |
| 3 | +using MarkupString.Layout; |
| 4 | + |
| 5 | +namespace MarkupString.Tests.Layout; |
| 6 | + |
| 7 | +/// <summary>Several titles in one line or box edge: each at its side, the ones that do not fit left out in order.</summary> |
| 8 | +public class EdgeTitleTests |
| 9 | +{ |
| 10 | + private static readonly MarkupRegistry Registry = MarkupRegistry.Empty.WithAnsi().WithHtml(); |
| 11 | + |
| 12 | + private static MarkupText P(string text) => MarkupText.Plain(text); |
| 13 | + |
| 14 | + private static string Line(Block block, int width) => BlockLayout.Build(block, width).ToPlainText(); |
| 15 | + |
| 16 | + private static Rule LeftMiddleRight() => new(P("A")) |
| 17 | + { |
| 18 | + Border = BorderStyle.Mush, |
| 19 | + TitleAlignment = Alignment.Left, |
| 20 | + Titles = [new EdgeTitle(P("B")), new EdgeTitle(P("C"), Alignment.Right)], |
| 21 | + }; |
| 22 | + |
| 23 | + private static Rule PoseHeader() => new(P("Wren")) |
| 24 | + { |
| 25 | + Border = BorderStyle.Mush, |
| 26 | + TitleAlignment = Alignment.Left, |
| 27 | + Titles = [new EdgeTitle(P("Scene 3"), Alignment.Right), new EdgeTitle(P("21:04"), Alignment.Right)], |
| 28 | + }; |
| 29 | + |
| 30 | + [Test] |
| 31 | + public async Task OneLeft_OneInTheMiddle_OneRight() |
| 32 | + => await Assert.That(Line(LeftMiddleRight(), 30)).IsEqualTo("=< A >=======< B >======< C >="); |
| 33 | + |
| 34 | + [Test] |
| 35 | + public async Task TwoOnTheRight_SitInOrder_ACellApart() |
| 36 | + => await Assert.That(Line(PoseHeader(), 40)).IsEqualTo("=< Wren >=========< Scene 3 >=< 21:04 >="); |
| 37 | + |
| 38 | + [Test] |
| 39 | + public async Task TooNarrow_DropsTheRightTitleFarthestFromTheEnd() |
| 40 | + => await Assert.That(Line(PoseHeader(), 31)).IsEqualTo("=< Wren >============< 21:04 >="); |
| 41 | + |
| 42 | + [Test] |
| 43 | + public async Task TooNarrow_DropsTheMiddleFirst() |
| 44 | + => await Assert.That(Line(LeftMiddleRight(), 18)).IsEqualTo("=< A >======< C >="); |
| 45 | + |
| 46 | + [Test] |
| 47 | + public async Task TheMiddleTitle_MovesOver_ToKeepACellClear() |
| 48 | + { |
| 49 | + var rule = new Rule(P("Long left title")) |
| 50 | + { |
| 51 | + Border = BorderStyle.Mush, |
| 52 | + TitleAlignment = Alignment.Left, |
| 53 | + Titles = [new EdgeTitle(P("M"))], |
| 54 | + }; |
| 55 | + |
| 56 | + await Assert.That(Line(rule, 30)).IsEqualTo("=< Long left title >=< M >===="); |
| 57 | + } |
| 58 | + |
| 59 | + [Test] |
| 60 | + public async Task OneTitleLeft_IsDrawnAsASingleTitleAlwaysWas() |
| 61 | + { |
| 62 | + var rule = new Rule { Border = BorderStyle.Mush, Titles = [new EdgeTitle(P("T"), Alignment.Right)] }; |
| 63 | + |
| 64 | + await Assert.That(Line(rule, 14)).IsEqualTo("========< T >="); |
| 65 | + } |
| 66 | + |
| 67 | + [Test] |
| 68 | + public async Task ABox_TakesTitlesInItsBottomEdge() |
| 69 | + { |
| 70 | + var box = new Frame(new TextBlock(P("x"))) |
| 71 | + { |
| 72 | + Border = BorderStyle.Mush, |
| 73 | + BottomTitles = [new EdgeTitle(P("1/3"), Alignment.Right)], |
| 74 | + }; |
| 75 | + |
| 76 | + await Assert.That(Line(box, 12).Split('\n')[^1]).IsEqualTo("+==< 1/3 >=+"); |
| 77 | + } |
| 78 | + |
| 79 | + [Test] |
| 80 | + public async Task ABox_TakesSeveralTitlesInItsTopEdge() |
| 81 | + { |
| 82 | + var box = new Frame(new TextBlock(P("x"))) |
| 83 | + { |
| 84 | + Border = BorderStyle.Mush, |
| 85 | + Title = P("Finger"), |
| 86 | + TitleAlignment = Alignment.Left, |
| 87 | + Titles = [new EdgeTitle(P("On"), Alignment.Right)], |
| 88 | + }; |
| 89 | + |
| 90 | + await Assert.That(Line(box, 24).Split('\n')[0]).IsEqualTo("+=< Finger >====< On >=+"); |
| 91 | + } |
| 92 | + |
| 93 | + [Test] |
| 94 | + public async Task AScreenReader_HearsTheTitlesLeftToRight() |
| 95 | + { |
| 96 | + var rule = new Rule(P("C")) { TitleAlignment = Alignment.Right, Titles = [new EdgeTitle(P("A"), Alignment.Left), new EdgeTitle(P("B"))] }; |
| 97 | + |
| 98 | + var lines = BlockLayout.Lines(rule, 40, new LayoutContext { Linear = true }); |
| 99 | + |
| 100 | + await Assert.That(lines.Select(line => line.ToPlainText())).IsEquivalentTo(new[] { "A, B, C" }); |
| 101 | + } |
| 102 | + |
| 103 | + [Test] |
| 104 | + public async Task TheSerializer_KeepsEveryTitle() |
| 105 | + { |
| 106 | + var text = BlockLayout.Build(LeftMiddleRight(), 30, fluid: true); |
| 107 | + |
| 108 | + var json = MarkupTextSerializer.Serialize(text, Registry); |
| 109 | + var read = MarkupTextSerializer.Deserialize(json, Registry); |
| 110 | + |
| 111 | + await Assert.That(json).Contains("\"tt\""); |
| 112 | + await Assert.That(MarkupTextSerializer.Serialize(read, Registry)).IsEqualTo(json); |
| 113 | + await Assert.That(BlockLayout.Relayout(read, 18, LayoutContext.Default).ToPlainText()).IsEqualTo("=< A >======< C >="); |
| 114 | + } |
| 115 | + |
| 116 | + [Test] |
| 117 | + public async Task TheSerializer_KeepsABoxsBottomTitles() |
| 118 | + { |
| 119 | + var box = new Frame(new TextBlock(P("x"))) { Border = BorderStyle.Mush, BottomTitles = [new EdgeTitle(P("1/3"), Alignment.Right)] }; |
| 120 | + |
| 121 | + var read = MarkupTextSerializer.Deserialize(MarkupTextSerializer.Serialize(BlockLayout.Build(box, 12), Registry), Registry); |
| 122 | + |
| 123 | + await Assert.That(BlockLayout.Relayout(read, 12, LayoutContext.Default).ToPlainText().Split('\n')[^1]).IsEqualTo("+==< 1/3 >=+"); |
| 124 | + } |
| 125 | + |
| 126 | + [Test] |
| 127 | + public async Task InHtml_TheLineRunsBetweenTheTitles() |
| 128 | + => await Assert.That(BlockLayout.Build(LeftMiddleRight(), 30).Render(MarkupFormat.Html, Registry)).Contains( |
| 129 | + "<div class=\"ms-rule ms-titles ms-border-mush\" role=\"separator\"><span class=\"ms-line ms-end\"></span><span class=\"ms-rule-title\">A</span>" + |
| 130 | + "<span class=\"ms-line\"></span><span class=\"ms-rule-title\">B</span><span class=\"ms-line\"></span><span class=\"ms-rule-title\">C</span>" + |
| 131 | + "<span class=\"ms-line ms-end\"></span></div>"); |
| 132 | + |
| 133 | + [Test] |
| 134 | + public async Task InHtml_ABoxsBottomTitlesDrawItsBottomEdge() |
| 135 | + { |
| 136 | + var box = new Frame(new TextBlock(P("x"))) { Border = BorderStyle.Mush, BottomTitles = [new EdgeTitle(P("1/3"), Alignment.Right)] }; |
| 137 | + |
| 138 | + await Assert.That(BlockLayout.Build(box, 12).Render(MarkupFormat.Html, Registry)).Contains( |
| 139 | + "<div class=\"ms-box-bottom ms-titles ms-border-mush\"><span class=\"ms-line\"></span><span class=\"ms-rule-title\">1/3</span><span class=\"ms-line ms-end\"></span></div></fieldset>"); |
| 140 | + } |
| 141 | + |
| 142 | + [Test] |
| 143 | + public async Task APriority_KeepsATitleTheSideWouldDrop() |
| 144 | + { |
| 145 | + var rule = new Rule |
| 146 | + { |
| 147 | + Border = BorderStyle.Mush, |
| 148 | + Titles = |
| 149 | + [ |
| 150 | + new EdgeTitle(P("Wren"), Alignment.Left) { Priority = 2 }, |
| 151 | + new EdgeTitle(P("Pose 17")) { Priority = 1 }, |
| 152 | + new EdgeTitle(P("Scene 3"), Alignment.Right), |
| 153 | + ], |
| 154 | + }; |
| 155 | + |
| 156 | + await Assert.That(Line(rule, 40)).IsEqualTo("=< Wren >======< Pose 17 >==< Scene 3 >="); |
| 157 | + await Assert.That(Line(rule, 26)).IsEqualTo("=< Wren >=< Pose 17 >=====").Because("the right title is 2 by its side, and among equals the right goes before the left"); |
| 158 | + await Assert.That(Line(rule, 16)).IsEqualTo("===< Pose 17 >=="); |
| 159 | + } |
| 160 | + |
| 161 | + [Test] |
| 162 | + public async Task TheSerializer_KeepsAPriority() |
| 163 | + { |
| 164 | + var rule = new Rule { Border = BorderStyle.Mush, Titles = [new EdgeTitle(P("A"), Alignment.Left) { Priority = 2 }, new EdgeTitle(P("B")) { Priority = 1 }] }; |
| 165 | + |
| 166 | + var json = MarkupTextSerializer.Serialize(BlockLayout.Build(rule, 20, fluid: true), Registry); |
| 167 | + var read = MarkupTextSerializer.Deserialize(json, Registry); |
| 168 | + |
| 169 | + await Assert.That(json).Contains("\"p\":2"); |
| 170 | + await Assert.That(BlockLayout.Relayout(read, 6, LayoutContext.Default).ToPlainText()).IsEqualTo("=< B >"); |
| 171 | + } |
| 172 | +} |
0 commit comments