ApplicationPopoverTests.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #nullable enable
  2. namespace UnitTests.ApplicationTests;
  3. public class ApplicationPopoverTests
  4. {
  5. [Fact]
  6. public void Application_Init_Initializes_PopoverManager ()
  7. {
  8. try
  9. {
  10. // Arrange
  11. Application.Init ("fake");
  12. // Act
  13. Assert.NotNull (Application.Popover);
  14. }
  15. finally
  16. {
  17. Application.ResetState (true);
  18. }
  19. }
  20. [Fact]
  21. public void Application_Shutdown_Resets_PopoverManager ()
  22. {
  23. try
  24. {
  25. // Arrange
  26. Application.Init ("fake");
  27. // Act
  28. Assert.NotNull (Application.Popover);
  29. Application.Shutdown ();
  30. // Test
  31. }
  32. finally
  33. {
  34. Application.ResetState (true);
  35. }
  36. }
  37. [Fact]
  38. public void Application_End_Does_Not_Reset_PopoverManager ()
  39. {
  40. Toplevel? top = null;
  41. try
  42. {
  43. // Arrange
  44. Application.Init ("fake");
  45. Assert.NotNull (Application.Popover);
  46. Application.StopAfterFirstIteration = true;
  47. top = new ();
  48. SessionToken rs = Application.Begin (top);
  49. // Act
  50. Application.End (rs);
  51. // Test
  52. Assert.NotNull (Application.Popover);
  53. }
  54. finally
  55. {
  56. top?.Dispose ();
  57. Application.ResetState (true);
  58. }
  59. }
  60. [Fact]
  61. public void Application_End_Hides_Active ()
  62. {
  63. Toplevel? top = null;
  64. try
  65. {
  66. // Arrange
  67. Application.Init ("fake");
  68. Application.StopAfterFirstIteration = true;
  69. top = new ();
  70. SessionToken rs = Application.Begin (top);
  71. PopoverTestClass? popover = new ();
  72. Application.Popover?.Register (popover);
  73. Application.Popover?.Show (popover);
  74. Assert.True (popover.Visible);
  75. // Act
  76. Application.End (rs);
  77. // Test
  78. Assert.False (popover.Visible);
  79. Assert.NotNull (Application.Popover);
  80. popover.Dispose ();
  81. Assert.Equal (1, popover.DisposedCount);
  82. }
  83. finally
  84. {
  85. top?.Dispose ();
  86. Application.ResetState (true);
  87. }
  88. }
  89. [Fact]
  90. public void Application_Shutdown_Disposes_Registered_Popovers ()
  91. {
  92. try
  93. {
  94. // Arrange
  95. Application.Init ("fake");
  96. PopoverTestClass? popover = new ();
  97. // Act
  98. Application.Popover?.Register (popover);
  99. Application.Shutdown ();
  100. // Test
  101. Assert.Equal (1, popover.DisposedCount);
  102. }
  103. finally
  104. {
  105. Application.ResetState (true);
  106. }
  107. }
  108. [Fact]
  109. public void Application_Shutdown_Does_Not_Dispose_DeRegistered_Popovers ()
  110. {
  111. try
  112. {
  113. // Arrange
  114. Application.Init ("fake");
  115. PopoverTestClass? popover = new ();
  116. Application.Popover?.Register (popover);
  117. // Act
  118. Application.Popover?.DeRegister (popover);
  119. Application.Shutdown ();
  120. // Test
  121. Assert.Equal (0, popover.DisposedCount);
  122. popover.Dispose ();
  123. Assert.Equal (1, popover.DisposedCount);
  124. }
  125. finally
  126. {
  127. Application.ResetState (true);
  128. }
  129. }
  130. [Fact]
  131. public void Application_Shutdown_Does_Not_Dispose_ActiveNotRegistered_Popover ()
  132. {
  133. try
  134. {
  135. // Arrange
  136. Application.Init ("fake");
  137. PopoverTestClass? popover = new ();
  138. Application.Popover?.Register (popover);
  139. Application.Popover?.Show (popover);
  140. Application.Popover?.DeRegister (popover);
  141. // Act
  142. Application.Shutdown ();
  143. // Test
  144. Assert.Equal (0, popover.DisposedCount);
  145. popover.Dispose ();
  146. Assert.Equal (1, popover.DisposedCount);
  147. }
  148. finally
  149. {
  150. Application.ResetState (true);
  151. }
  152. }
  153. [Fact]
  154. public void Register_SetsTopLevel ()
  155. {
  156. try
  157. {
  158. // Arrange
  159. Application.Init ("fake");
  160. Application.Running = new ();
  161. PopoverTestClass? popover = new ();
  162. // Act
  163. Application.Popover?.Register (popover);
  164. // Assert
  165. Assert.Equal (Application.Running, popover.Toplevel);
  166. }
  167. finally
  168. {
  169. Application.ResetState (true);
  170. }
  171. }
  172. [Fact]
  173. public void Keyboard_Events_Go_Only_To_Popover_Associated_With_Toplevel ()
  174. {
  175. try
  176. {
  177. // Arrange
  178. Application.Init ("fake");
  179. Application.Running = new() { Id = "initialTop" };
  180. PopoverTestClass? popover = new () { };
  181. var keyDownEvents = 0;
  182. popover.KeyDown += (s, e) =>
  183. {
  184. keyDownEvents++;
  185. e.Handled = true;
  186. }; // Ensure it handles the key
  187. Application.Popover?.Register (popover);
  188. // Act
  189. Application.RaiseKeyDownEvent (Key.A); // Goes to initialTop
  190. Application.Running = new() { Id = "secondaryTop" };
  191. Application.RaiseKeyDownEvent (Key.A); // Goes to secondaryTop
  192. // Test
  193. Assert.Equal (1, keyDownEvents);
  194. popover.Dispose ();
  195. Assert.Equal (1, popover.DisposedCount);
  196. }
  197. finally
  198. {
  199. Application.ResetState (true);
  200. }
  201. }
  202. // See: https://github.com/gui-cs/Terminal.Gui/issues/4122
  203. [Theory]
  204. [InlineData (0, 0, new [] { "top" })]
  205. [InlineData (10, 10, new string [] { })]
  206. [InlineData (1, 1, new [] { "top", "view" })]
  207. [InlineData (5, 5, new [] { "top" })]
  208. [InlineData (6, 6, new [] { "popoverSubView" })]
  209. [InlineData (7, 7, new [] { "top" })]
  210. [InlineData (3, 3, new [] { "top" })]
  211. public void GetViewsUnderMouse_Supports_ActivePopover (int mouseX, int mouseY, string [] viewIdStrings)
  212. {
  213. PopoverTestClass? popover = null;
  214. try
  215. {
  216. // Arrange
  217. Application.Init ("fake");
  218. Application.Running = new ()
  219. {
  220. Frame = new (0, 0, 10, 10),
  221. Id = "top"
  222. };
  223. View? view = new ()
  224. {
  225. Id = "view",
  226. X = 1,
  227. Y = 1,
  228. Width = 2,
  229. Height = 2
  230. };
  231. Application.Running.Add (view);
  232. popover = new ()
  233. {
  234. Id = "popover",
  235. X = 5,
  236. Y = 5,
  237. Width = 3,
  238. Height = 3
  239. }; // at 5,5 to 8,8 (screen)
  240. View? popoverSubView = new ()
  241. {
  242. Id = "popoverSubView",
  243. X = 1,
  244. Y = 1,
  245. Width = 1,
  246. Height = 1
  247. };
  248. popover.Add (popoverSubView);
  249. Application.Popover?.Register (popover);
  250. Application.Popover?.Show (popover);
  251. List<View?> found = view.GetViewsUnderLocation (new (mouseX, mouseY), ViewportSettingsFlags.TransparentMouse);
  252. string [] foundIds = found.Select (v => v!.Id).ToArray ();
  253. Assert.Equal (viewIdStrings, foundIds);
  254. }
  255. finally
  256. {
  257. popover?.Dispose ();
  258. Application.Running?.Dispose ();
  259. Application.ResetState (true);
  260. }
  261. }
  262. public class PopoverTestClass : PopoverBaseImpl
  263. {
  264. public List<Key> HandledKeys { get; } = [];
  265. public int NewCommandInvokeCount { get; private set; }
  266. // NOTE: Hides the base DisposedCount property
  267. public new int DisposedCount { get; private set; }
  268. public PopoverTestClass ()
  269. {
  270. CanFocus = true;
  271. AddCommand (Command.New, NewCommandHandler!);
  272. HotKeyBindings.Add (Key.N.WithCtrl, Command.New);
  273. return;
  274. bool? NewCommandHandler (ICommandContext ctx)
  275. {
  276. NewCommandInvokeCount++;
  277. return false;
  278. }
  279. }
  280. protected override bool OnKeyDown (Key key)
  281. {
  282. HandledKeys.Add (key);
  283. return false;
  284. }
  285. /// <inheritdoc/>
  286. protected override void Dispose (bool disposing)
  287. {
  288. base.Dispose (disposing);
  289. DisposedCount++;
  290. }
  291. }
  292. }