ClearViewportTests.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #nullable enable
  2. using Moq;
  3. using UnitTests;
  4. using Xunit.Abstractions;
  5. namespace UnitTests.ViewTests;
  6. [Trait ("Category", "Output")]
  7. public class ClearViewportTests (ITestOutputHelper output)
  8. {
  9. public class TestableView : View
  10. {
  11. public bool TestOnClearingViewport () { return OnClearingViewport (); }
  12. public int OnClearingViewportCalled { get; set; }
  13. public bool CancelOnClearingViewport { get; set; }
  14. protected override bool OnClearingViewport ()
  15. {
  16. OnClearingViewportCalled++;
  17. return CancelOnClearingViewport;
  18. }
  19. public int OnClearedViewportCalled { get; set; }
  20. protected override void OnClearedViewport () { OnClearedViewportCalled++; }
  21. }
  22. [Fact]
  23. public void DoClearViewport_ViewportIsTransparent_DoesNotClear ()
  24. {
  25. // Arrange
  26. Mock<TestableView> view = new () { CallBase = true };
  27. view.Object.ViewportSettings = ViewportSettingsFlags.Transparent;
  28. // Act
  29. view.Object.DoClearViewport ();
  30. // Assert
  31. Assert.Equal (0, view.Object.OnClearingViewportCalled);
  32. Assert.Equal (0, view.Object.OnClearedViewportCalled);
  33. }
  34. [Fact]
  35. public void DoClearViewport_OnClearingViewportReturnsTrue_DoesNotClear ()
  36. {
  37. // Arrange
  38. Mock<TestableView> view = new () { CallBase = true };
  39. view.Object.CancelOnClearingViewport = true;
  40. // Act
  41. view.Object.DoClearViewport ();
  42. // Assert
  43. Assert.Equal (0, view.Object.OnClearedViewportCalled);
  44. }
  45. [Fact]
  46. public void DoClearViewport_ClearingViewportEventCancelled_DoesNotClear ()
  47. {
  48. // Arrange
  49. Mock<TestableView> view = new () { CallBase = true };
  50. view.Object.ClearingViewport += (sender, e) => e.Cancel = true;
  51. // Act
  52. view.Object.DoClearViewport ();
  53. // Assert
  54. Assert.Equal (0, view.Object.OnClearedViewportCalled);
  55. }
  56. [Fact]
  57. public void DoClearViewport_ClearsViewport ()
  58. {
  59. // Arrange
  60. Mock<TestableView> view = new () { CallBase = true };
  61. // Act
  62. view.Object.DoClearViewport ();
  63. // Assert
  64. Assert.Equal (1, view.Object.OnClearedViewportCalled);
  65. }
  66. [Fact]
  67. public void DoClearViewport_RaisesClearingViewportEvent ()
  68. {
  69. // Arrange
  70. Mock<TestableView> view = new () { CallBase = true };
  71. var eventRaised = false;
  72. view.Object.ClearingViewport += (sender, e) => eventRaised = true;
  73. // Act
  74. view.Object.DoClearViewport ();
  75. // Assert
  76. Assert.True (eventRaised);
  77. }
  78. [Fact]
  79. [SetupFakeApplication]
  80. public void Clear_ClearsEntireViewport ()
  81. {
  82. var superView = new View
  83. {
  84. App = ApplicationImpl.Instance,
  85. Width = Dim.Fill (), Height = Dim.Fill ()
  86. };
  87. var view = new View
  88. {
  89. Text = "X",
  90. X = 1, Y = 1,
  91. Width = 3, Height = 3,
  92. BorderStyle = LineStyle.Single
  93. };
  94. superView.Add (view);
  95. superView.BeginInit ();
  96. superView.EndInit ();
  97. superView.LayoutSubViews ();
  98. superView.Draw ();
  99. DriverAssert.AssertDriverContentsWithFrameAre (
  100. @"
  101. ┌─┐
  102. │X│
  103. └─┘",
  104. output);
  105. // On Draw exit the view is excluded from the clip, so this will do nothing.
  106. view.ClearViewport ();
  107. DriverAssert.AssertDriverContentsWithFrameAre (
  108. @"
  109. ┌─┐
  110. │X│
  111. └─┘",
  112. output);
  113. view.SetClipToScreen ();
  114. view.ClearViewport ();
  115. DriverAssert.AssertDriverContentsWithFrameAre (
  116. @"
  117. ┌─┐
  118. │ │
  119. └─┘",
  120. output);
  121. }
  122. [Fact]
  123. [SetupFakeApplication]
  124. public void Clear_WithClearVisibleContentOnly_ClearsVisibleContentOnly ()
  125. {
  126. var superView = new View
  127. {
  128. App = ApplicationImpl.Instance,
  129. Width = Dim.Fill (), Height = Dim.Fill ()
  130. };
  131. var view = new View
  132. {
  133. Text = "X",
  134. X = 1, Y = 1,
  135. Width = 3, Height = 3,
  136. BorderStyle = LineStyle.Single,
  137. ViewportSettings = ViewportSettingsFlags.ClearContentOnly
  138. };
  139. superView.Add (view);
  140. superView.BeginInit ();
  141. superView.EndInit ();
  142. superView.LayoutSubViews ();
  143. superView.Draw ();
  144. DriverAssert.AssertDriverContentsWithFrameAre (
  145. @"
  146. ┌─┐
  147. │X│
  148. └─┘",
  149. output);
  150. view.SetClipToScreen ();
  151. view.ClearViewport ();
  152. DriverAssert.AssertDriverContentsWithFrameAre (
  153. @"
  154. ┌─┐
  155. │ │
  156. └─┘",
  157. output);
  158. }
  159. [Fact]
  160. [AutoInitShutdown]
  161. public void Clear_Viewport_Can_Use_Driver_AddRune_Or_AddStr_Methods ()
  162. {
  163. var view = new FrameView { Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Single };
  164. view.DrawingContent += (s, e) =>
  165. {
  166. Region? savedClip = view.AddViewportToClip ();
  167. for (var row = 0; row < view.Viewport.Height; row++)
  168. {
  169. Application.Driver?.Move (1, row + 1);
  170. for (var col = 0; col < view.Viewport.Width; col++)
  171. {
  172. Application.Driver?.AddStr ($"{col}");
  173. }
  174. }
  175. view.SetClip (savedClip);
  176. e.Cancel = true;
  177. };
  178. var top = new Toplevel ();
  179. top.Add (view);
  180. Application.Begin (top);
  181. Application.Driver!.SetScreenSize (20, 10);
  182. var expected = @"
  183. ┌──────────────────┐
  184. │012345678910111213│
  185. │012345678910111213│
  186. │012345678910111213│
  187. │012345678910111213│
  188. │012345678910111213│
  189. │012345678910111213│
  190. │012345678910111213│
  191. │012345678910111213│
  192. └──────────────────┘
  193. "
  194. ;
  195. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  196. Assert.Equal (new (0, 0, 20, 10), pos);
  197. view.FillRect (view.Viewport);
  198. expected = @"
  199. ┌──────────────────┐
  200. │ │
  201. │ │
  202. │ │
  203. │ │
  204. │ │
  205. │ │
  206. │ │
  207. │ │
  208. └──────────────────┘
  209. "
  210. ;
  211. pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  212. top.Dispose ();
  213. }
  214. [Fact]
  215. [AutoInitShutdown]
  216. public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods ()
  217. {
  218. var view = new FrameView { Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Single };
  219. view.DrawingContent += (s, e) =>
  220. {
  221. Region? savedClip = view.AddViewportToClip ();
  222. for (var row = 0; row < view.Viewport.Height; row++)
  223. {
  224. Application.Driver?.Move (1, row + 1);
  225. for (var col = 0; col < view.Viewport.Width; col++)
  226. {
  227. Application.Driver?.AddStr ($"{col}");
  228. }
  229. }
  230. view.SetClip (savedClip);
  231. e.Cancel = true;
  232. };
  233. var top = new Toplevel ();
  234. top.Add (view);
  235. Application.Begin (top);
  236. Application.Driver!.SetScreenSize (20, 10);
  237. var expected = @"
  238. ┌──────────────────┐
  239. │012345678910111213│
  240. │012345678910111213│
  241. │012345678910111213│
  242. │012345678910111213│
  243. │012345678910111213│
  244. │012345678910111213│
  245. │012345678910111213│
  246. │012345678910111213│
  247. └──────────────────┘
  248. "
  249. ;
  250. Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  251. Assert.Equal (new (0, 0, 20, 10), pos);
  252. view.FillRect (view.Viewport);
  253. expected = @"
  254. ┌──────────────────┐
  255. │ │
  256. │ │
  257. │ │
  258. │ │
  259. │ │
  260. │ │
  261. │ │
  262. │ │
  263. └──────────────────┘
  264. ";
  265. pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
  266. top.Dispose ();
  267. }
  268. [Theory (Skip = "This test is too fragile; depends on Library Resoruces/Themes which can easily change.")]
  269. [AutoInitShutdown]
  270. [InlineData (true)]
  271. [InlineData (false)]
  272. public void Clear_Does_Not_Spillover_Its_Parent (bool label)
  273. {
  274. ConfigurationManager.Enable (ConfigLocations.LibraryResources);
  275. View root = new () { Width = 20, Height = 10 };
  276. string text = new ('c', 100);
  277. View v = label
  278. // Label has Width/Height == AutoSize, so Frame.Size will be (100, 1)
  279. ? new Label { Text = text }
  280. // TextView has Width/Height == (Dim.Fill, 1), so Frame.Size will be 20 (width of root), 1
  281. : new TextView { Width = Dim.Fill (), Height = 1, Text = text };
  282. root.Add (v);
  283. Toplevel top = new ();
  284. top.Add (root);
  285. SessionToken sessionToken = Application.Begin (top);
  286. AutoInitShutdownAttribute.RunIteration ();
  287. if (label)
  288. {
  289. Assert.False (v.CanFocus);
  290. Assert.Equal (new (0, 0, text.Length, 1), v.Frame);
  291. }
  292. else
  293. {
  294. Assert.True (v.CanFocus);
  295. Assert.Equal (new (0, 0, 20, 1), v.Frame);
  296. }
  297. DriverAssert.AssertDriverContentsWithFrameAre (
  298. @"
  299. cccccccccccccccccccc",
  300. output
  301. );
  302. Attribute [] attributes =
  303. {
  304. SchemeManager.GetSchemes () ["TopLevel"]!.Normal,
  305. SchemeManager.GetSchemes () ["Base"]!.Normal,
  306. SchemeManager.GetSchemes () ["Base"]!.Focus
  307. };
  308. if (label)
  309. {
  310. DriverAssert.AssertDriverAttributesAre (
  311. @"
  312. 111111111111111111110
  313. 111111111111111111110",
  314. output,
  315. Application.Driver,
  316. attributes
  317. );
  318. }
  319. else
  320. {
  321. DriverAssert.AssertDriverAttributesAre (
  322. @"
  323. 222222222222222222220
  324. 111111111111111111110",
  325. output,
  326. Application.Driver,
  327. attributes
  328. );
  329. }
  330. if (label)
  331. {
  332. root.CanFocus = true;
  333. v.CanFocus = true;
  334. Assert.True (v.HasFocus);
  335. v.SetFocus ();
  336. Assert.True (v.HasFocus);
  337. Application.LayoutAndDraw ();
  338. DriverAssert.AssertDriverAttributesAre (
  339. @"
  340. 222222222222222222220
  341. 111111111111111111110",
  342. output,
  343. Application.Driver,
  344. attributes
  345. );
  346. }
  347. Application.End (sessionToken);
  348. top.Dispose ();
  349. CM.Disable (resetToHardCodedDefaults: true);
  350. }
  351. }