RuneCellTests.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. using System.Text;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class RuneCellTests (ITestOutputHelper output)
  5. {
  6. [Fact]
  7. public void Constructor_Defaults ()
  8. {
  9. var rc = new RuneCell ();
  10. Assert.NotNull (rc);
  11. Assert.Equal (0, rc.Rune.Value);
  12. Assert.Null (rc.ColorScheme);
  13. }
  14. [Fact]
  15. public void Equals_False ()
  16. {
  17. var rc1 = new RuneCell ();
  18. var rc2 = new RuneCell
  19. {
  20. Rune = new ('a'), ColorScheme = new() { Normal = new (Color.Red) }
  21. };
  22. Assert.False (rc1.Equals (rc2));
  23. Assert.False (rc2.Equals (rc1));
  24. rc1.Rune = new ('a');
  25. rc1.ColorScheme = new ();
  26. Assert.Equal (rc1.Rune, rc2.Rune);
  27. Assert.False (rc1.Equals (rc2));
  28. Assert.False (rc2.Equals (rc1));
  29. }
  30. [Fact]
  31. public void Equals_True ()
  32. {
  33. var rc1 = new RuneCell ();
  34. var rc2 = new RuneCell ();
  35. Assert.True (rc1.Equals (rc2));
  36. Assert.True (rc2.Equals (rc1));
  37. rc1.Rune = new ('a');
  38. rc1.ColorScheme = new ();
  39. rc2.Rune = new ('a');
  40. rc2.ColorScheme = new ();
  41. Assert.True (rc1.Equals (rc2));
  42. Assert.True (rc2.Equals (rc1));
  43. }
  44. [Fact]
  45. [AutoInitShutdown]
  46. public void RuneCell_LoadRuneCells_InheritsPreviousColorScheme ()
  47. {
  48. List<RuneCell> runeCells = new ();
  49. foreach (KeyValuePair<string, ColorScheme> color in Colors.ColorSchemes)
  50. {
  51. string csName = color.Key;
  52. foreach (Rune rune in csName.EnumerateRunes ())
  53. {
  54. runeCells.Add (new() { Rune = rune, ColorScheme = color.Value });
  55. }
  56. runeCells.Add (new() { Rune = (Rune)'\n', ColorScheme = color.Value });
  57. }
  58. TextView tv = CreateTextView ();
  59. tv.Load (runeCells);
  60. var top = new Toplevel ();
  61. top.Add (tv);
  62. RunState rs = Application.Begin (top);
  63. Assert.True (tv.InheritsPreviousColorScheme);
  64. var expectedText = @"
  65. TopLevel
  66. Base
  67. Dialog
  68. Menu
  69. Error ";
  70. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, output);
  71. Attribute [] attributes =
  72. {
  73. // 0
  74. Colors.ColorSchemes ["TopLevel"].Focus,
  75. // 1
  76. Colors.ColorSchemes ["Base"].Focus,
  77. // 2
  78. Colors.ColorSchemes ["Dialog"].Focus,
  79. // 3
  80. Colors.ColorSchemes ["Menu"].Focus,
  81. // 4
  82. Colors.ColorSchemes ["Error"].Focus
  83. };
  84. var expectedColor = @"
  85. 0000000000
  86. 1111000000
  87. 2222220000
  88. 3333000000
  89. 4444400000";
  90. TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
  91. tv.WordWrap = true;
  92. Application.Refresh ();
  93. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, output);
  94. TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
  95. tv.CursorPosition = new (6, 2);
  96. tv.SelectionStartColumn = 0;
  97. tv.SelectionStartRow = 0;
  98. Assert.Equal ($"TopLevel{Environment.NewLine}Base{Environment.NewLine}Dialog", tv.SelectedText);
  99. tv.Copy ();
  100. tv.Selecting = false;
  101. tv.CursorPosition = new (2, 4);
  102. tv.Paste ();
  103. Application.Refresh ();
  104. expectedText = @"
  105. TopLevel
  106. Base
  107. Dialog
  108. Menu
  109. ErTopLevel
  110. Base
  111. Dialogror ";
  112. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, output);
  113. expectedColor = @"
  114. 0000000000
  115. 1111000000
  116. 2222220000
  117. 3333000000
  118. 4444444444
  119. 4444000000
  120. 4444444440";
  121. TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
  122. tv.Undo ();
  123. tv.CursorPosition = new (0, 3);
  124. tv.SelectionStartColumn = 0;
  125. tv.SelectionStartRow = 0;
  126. Assert.Equal (
  127. $"TopLevel{Environment.NewLine}Base{Environment.NewLine}Dialog{Environment.NewLine}",
  128. tv.SelectedText
  129. );
  130. tv.Copy ();
  131. tv.Selecting = false;
  132. tv.CursorPosition = new (2, 4);
  133. tv.Paste ();
  134. Application.Refresh ();
  135. expectedText = @"
  136. TopLevel
  137. Base
  138. Dialog
  139. Menu
  140. ErTopLevel
  141. Base
  142. Dialog
  143. ror ";
  144. TestHelpers.AssertDriverContentsWithFrameAre (expectedText, output);
  145. expectedColor = @"
  146. 0000000000
  147. 1111000000
  148. 2222220000
  149. 3333000000
  150. 4444444444
  151. 4444000000
  152. 4444440000
  153. 4440000000";
  154. TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
  155. Application.End (rs);
  156. top.Dispose ();
  157. }
  158. [Fact]
  159. public void RuneCell_LoadRuneCells_Without_ColorScheme_Is_Never_Null ()
  160. {
  161. List<RuneCell> cells = new ()
  162. {
  163. new() { Rune = new ('T') },
  164. new() { Rune = new ('e') },
  165. new() { Rune = new ('s') },
  166. new() { Rune = new ('t') }
  167. };
  168. TextView tv = CreateTextView ();
  169. var top = new Toplevel ();
  170. top.Add (tv);
  171. tv.Load (cells);
  172. for (var i = 0; i < tv.Lines; i++)
  173. {
  174. List<RuneCell> line = tv.GetLine (i);
  175. foreach (RuneCell rc in line)
  176. {
  177. Assert.NotNull (rc.ColorScheme);
  178. }
  179. }
  180. }
  181. [Fact]
  182. [AutoInitShutdown]
  183. public void RuneCellEventArgs_WordWrap_True ()
  184. {
  185. var eventCount = 0;
  186. List<List<RuneCell>> text = new ()
  187. {
  188. TextModel.ToRuneCells (
  189. "This is the first line.".ToRunes ()
  190. ),
  191. TextModel.ToRuneCells (
  192. "This is the second line.".ToRunes ()
  193. )
  194. };
  195. TextView tv = CreateTextView ();
  196. tv.DrawNormalColor += _textView_DrawColor;
  197. tv.DrawReadOnlyColor += _textView_DrawColor;
  198. tv.DrawSelectionColor += _textView_DrawColor;
  199. tv.DrawUsedColor += _textView_DrawColor;
  200. void _textView_DrawColor (object sender, RuneCellEventArgs e)
  201. {
  202. Assert.Equal (e.Line [e.Col], text [e.UnwrappedPosition.Row] [e.UnwrappedPosition.Col]);
  203. eventCount++;
  204. }
  205. tv.Text = $"{TextModel.ToString (text [0])}\n{TextModel.ToString (text [1])}\n";
  206. Assert.False (tv.WordWrap);
  207. var top = new Toplevel ();
  208. top.Add (tv);
  209. Application.Begin (top);
  210. TestHelpers.AssertDriverContentsWithFrameAre (
  211. @"
  212. This is the first line.
  213. This is the second line.",
  214. output
  215. );
  216. tv.Width = 10;
  217. tv.Height = 25;
  218. tv.WordWrap = true;
  219. Application.Refresh ();
  220. TestHelpers.AssertDriverContentsWithFrameAre (
  221. @"
  222. This is
  223. the
  224. first
  225. line.
  226. This is
  227. the
  228. second
  229. line. ",
  230. output
  231. );
  232. Assert.Equal (eventCount, (text [0].Count + text [1].Count) * 2);
  233. top.Dispose ();
  234. }
  235. [Fact]
  236. public void ToString_Override ()
  237. {
  238. var rc1 = new RuneCell ();
  239. var rc2 = new RuneCell
  240. {
  241. Rune = new ('a'), ColorScheme = new() { Normal = new (Color.Red) }
  242. };
  243. Assert.Equal ("U+0000 '\0'; null", rc1.ToString ());
  244. Assert.Equal (
  245. "U+0061 'a'; Normal: [Red,Red]; Focus: [White,Black]; HotNormal: [White,Black]; HotFocus: [White,Black]; Disabled: [White,Black]",
  246. rc2.ToString ()
  247. );
  248. }
  249. // TODO: Move the tests below to View or Color - they test ColorScheme, not RuneCell primitives.
  250. private TextView CreateTextView () { return new() { Width = 30, Height = 10 }; }
  251. }