2
0

ResponderTests.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Alias Console to MockConsole so we don't accidentally use Console
  2. namespace Terminal.Gui.InputTests;
  3. public class ResponderTests
  4. {
  5. // Generic lifetime (IDisposable) tests
  6. [Fact]
  7. [TestRespondersDisposed]
  8. public void Dispose_Works ()
  9. {
  10. var r = new Responder ();
  11. #if DEBUG_IDISPOSABLE
  12. Assert.Single (Responder.Instances);
  13. #endif
  14. r.Dispose ();
  15. #if DEBUG_IDISPOSABLE
  16. Assert.Empty (Responder.Instances);
  17. #endif
  18. }
  19. [Fact]
  20. public void Disposing_Event_Notify_All_Subscribers_On_The_First_Container ()
  21. {
  22. #if DEBUG_IDISPOSABLE
  23. // Only clear before because need to test after assert
  24. Responder.Instances.Clear ();
  25. #endif
  26. var container1 = new View { Id = "Container1" };
  27. var count = 0;
  28. var view = new View { Id = "View" };
  29. view.Disposing += View_Disposing;
  30. container1.Add (view);
  31. Assert.Equal (container1, view.SuperView);
  32. void View_Disposing (object sender, EventArgs e)
  33. {
  34. count++;
  35. Assert.Equal (view, sender);
  36. container1.Remove ((View)sender);
  37. }
  38. Assert.Single (container1.Subviews);
  39. var container2 = new View { Id = "Container2" };
  40. container2.Add (view);
  41. Assert.Equal (container2, view.SuperView);
  42. Assert.Equal (container1.Subviews.Count, container2.Subviews.Count);
  43. container2.Dispose ();
  44. Assert.Empty (container1.Subviews);
  45. Assert.Empty (container2.Subviews);
  46. Assert.Equal (1, count);
  47. Assert.Null (view.SuperView);
  48. container1.Dispose ();
  49. #if DEBUG_IDISPOSABLE
  50. Assert.Empty (Responder.Instances);
  51. #endif
  52. }
  53. [Fact]
  54. public void Disposing_Event_Notify_All_Subscribers_On_The_Second_Container ()
  55. {
  56. #if DEBUG_IDISPOSABLE
  57. // Only clear before because need to test after assert
  58. Responder.Instances.Clear ();
  59. #endif
  60. var container1 = new View { Id = "Container1" };
  61. var view = new View { Id = "View" };
  62. container1.Add (view);
  63. Assert.Equal (container1, view.SuperView);
  64. Assert.Single (container1.Subviews);
  65. var container2 = new View { Id = "Container2" };
  66. var count = 0;
  67. view.Disposing += View_Disposing;
  68. container2.Add (view);
  69. Assert.Equal (container2, view.SuperView);
  70. void View_Disposing (object sender, EventArgs e)
  71. {
  72. count++;
  73. Assert.Equal (view, sender);
  74. container2.Remove ((View)sender);
  75. }
  76. Assert.Equal (container1.Subviews.Count, container2.Subviews.Count);
  77. container1.Dispose ();
  78. Assert.Empty (container1.Subviews);
  79. Assert.Empty (container2.Subviews);
  80. Assert.Equal (1, count);
  81. Assert.Null (view.SuperView);
  82. container2.Dispose ();
  83. #if DEBUG_IDISPOSABLE
  84. Assert.Empty (Responder.Instances);
  85. #endif
  86. }
  87. [Fact]
  88. [TestRespondersDisposed]
  89. public void IsOverridden_False_IfNotOverridden ()
  90. {
  91. // MouseEvent IS defined on Responder but NOT overridden
  92. Assert.False (Responder.IsOverridden (new Responder (), "OnMouseEvent"));
  93. // MouseEvent is defined on Responder and NOT overrident on View
  94. Assert.False (
  95. Responder.IsOverridden (
  96. new View { Text = "View does not override OnMouseEvent" },
  97. "OnMouseEvent"
  98. )
  99. );
  100. Assert.False (
  101. Responder.IsOverridden (
  102. new DerivedView { Text = "DerivedView does not override OnMouseEvent" },
  103. "OnMouseEvent"
  104. )
  105. );
  106. // MouseEvent is NOT defined on DerivedView
  107. Assert.False (
  108. Responder.IsOverridden (
  109. new DerivedView { Text = "DerivedView does not override OnMouseEvent" },
  110. "OnMouseEvent"
  111. )
  112. );
  113. // OnKeyDown is defined on View and NOT overrident on Button
  114. Assert.False (
  115. Responder.IsOverridden (
  116. new Button { Text = "Button does not override OnKeyDown" },
  117. "OnKeyDown"
  118. )
  119. );
  120. #if DEBUG_IDISPOSABLE
  121. // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above.
  122. Responder.Instances.Clear ();
  123. Assert.Empty (Responder.Instances);
  124. #endif
  125. }
  126. [Fact]
  127. [TestRespondersDisposed]
  128. public void IsOverridden_True_IfOverridden ()
  129. {
  130. // MouseEvent is defined on Responder IS overriden on ScrollBarView (but not View)
  131. Assert.True (
  132. Responder.IsOverridden (
  133. new ScrollBarView { Text = "ScrollBarView overrides OnMouseEvent" },
  134. "OnMouseEvent"
  135. )
  136. );
  137. // OnKeyDown is defined on View
  138. Assert.False (Responder.IsOverridden (new View { Text = "View overrides OnKeyDown" }, "OnKeyDown"));
  139. // OnKeyDown is defined on DerivedView
  140. Assert.True (
  141. Responder.IsOverridden (
  142. new DerivedView { Text = "DerivedView overrides OnKeyDown" },
  143. "OnKeyDown"
  144. )
  145. );
  146. // ScrollBarView overrides both MouseEvent (from Responder) and Redraw (from View)
  147. Assert.True (
  148. Responder.IsOverridden (
  149. new ScrollBarView { Text = "ScrollBarView overrides OnMouseEvent" },
  150. "OnMouseEvent"
  151. )
  152. );
  153. Assert.True (
  154. Responder.IsOverridden (
  155. new ScrollBarView { Text = "ScrollBarView overrides OnDrawContent" },
  156. "OnDrawContent"
  157. )
  158. );
  159. #if DEBUG_IDISPOSABLE
  160. // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above.
  161. Responder.Instances.Clear ();
  162. Assert.Empty (Responder.Instances);
  163. #endif
  164. }
  165. [Fact]
  166. public void KeyPressed_Handled_True_Cancels_KeyPress ()
  167. {
  168. var r = new View ();
  169. var args = new Key { KeyCode = KeyCode.Null };
  170. Assert.False (r.OnKeyDown (args));
  171. Assert.False (args.Handled);
  172. r.KeyDown += (s, a) => a.Handled = true;
  173. Assert.True (r.OnKeyDown (args));
  174. Assert.True (args.Handled);
  175. r.Dispose ();
  176. }
  177. [Fact]
  178. [TestRespondersDisposed]
  179. public void New_Initializes ()
  180. {
  181. var r = new Responder ();
  182. Assert.NotNull (r);
  183. Assert.Equal ("Terminal.Gui.Responder", r.ToString ());
  184. r.Dispose ();
  185. }
  186. [Fact]
  187. [TestRespondersDisposed]
  188. public void New_Methods_Return_False ()
  189. {
  190. var r = new View ();
  191. //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
  192. Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null }));
  193. Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null }));
  194. Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
  195. Assert.False (r.NewMouseEnterEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
  196. Assert.False (r.NewMouseLeaveEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
  197. var v = new View ();
  198. //Assert.False (r.OnEnter (v));
  199. v.Dispose ();
  200. v = new View ();
  201. //Assert.False (r.OnLeave (v));
  202. v.Dispose ();
  203. r.Dispose ();
  204. }
  205. [Fact]
  206. public void Responder_Not_Notifying_Dispose ()
  207. {
  208. // Only clear before because need to test after assert
  209. #if DEBUG_IDISPOSABLE
  210. Responder.Instances.Clear ();
  211. #endif
  212. var container1 = new View { Id = "Container1" };
  213. var view = new View { Id = "View" };
  214. container1.Add (view);
  215. Assert.Equal (container1, view.SuperView);
  216. Assert.Single (container1.Subviews);
  217. var container2 = new View { Id = "Container2" };
  218. container2.Add (view);
  219. Assert.Equal (container2, view.SuperView);
  220. Assert.Equal (container1.Subviews.Count, container2.Subviews.Count);
  221. container1.Dispose ();
  222. Assert.Empty (container1.Subviews);
  223. Assert.NotEmpty (container2.Subviews);
  224. Assert.Single (container2.Subviews);
  225. Assert.Null (view.SuperView);
  226. // Trying access disposed properties
  227. #if DEBUG_IDISPOSABLE
  228. Assert.True (container2.Subviews [0].WasDisposed);
  229. #endif
  230. Assert.False (container2.Subviews [0].CanFocus);
  231. Assert.Null (container2.Subviews [0].Margin);
  232. Assert.Null (container2.Subviews [0].Border);
  233. Assert.Null (container2.Subviews [0].Padding);
  234. Assert.Null (view.SuperView);
  235. container2.Dispose ();
  236. #if DEBUG_IDISPOSABLE
  237. Assert.Empty (Responder.Instances);
  238. #endif
  239. }
  240. public class DerivedView : View
  241. {
  242. public override bool OnKeyDown (Key keyEvent) { return true; }
  243. }
  244. }