AdvanceFocusTests.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. using Xunit.Abstractions;
  2. namespace Terminal.Gui.ViewTests;
  3. public class AdvanceFocusTests ()
  4. {
  5. [Fact]
  6. public void AdvanceFocus_CanFocus_Mixed ()
  7. {
  8. var r = new View ();
  9. var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  10. var v2 = new View { CanFocus = false, TabStop = TabBehavior.TabStop };
  11. var v3 = new View { CanFocus = false, TabStop = TabBehavior.NoStop };
  12. r.Add (v1, v2, v3);
  13. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  14. Assert.False (v1.HasFocus);
  15. Assert.False (v2.HasFocus);
  16. Assert.False (v3.HasFocus);
  17. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  18. Assert.False (v1.HasFocus);
  19. Assert.False (v2.HasFocus);
  20. Assert.False (v3.HasFocus);
  21. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  22. Assert.False (v1.HasFocus);
  23. Assert.False (v2.HasFocus);
  24. Assert.False (v3.HasFocus);
  25. r.Dispose ();
  26. }
  27. [Theory]
  28. [CombinatorialData]
  29. public void AdvanceFocus_Change_CanFocus_Works ([CombinatorialValues (TabBehavior.NoStop, TabBehavior.TabStop, TabBehavior.TabGroup)] TabBehavior behavior)
  30. {
  31. var r = new View { CanFocus = true };
  32. var v1 = new View ();
  33. var v2 = new View ();
  34. var v3 = new View ();
  35. Assert.True (r.CanFocus);
  36. Assert.False (v1.CanFocus);
  37. Assert.False (v2.CanFocus);
  38. Assert.False (v3.CanFocus);
  39. r.Add (v1, v2, v3);
  40. r.AdvanceFocus (NavigationDirection.Forward, behavior);
  41. Assert.False (v1.HasFocus);
  42. Assert.False (v2.HasFocus);
  43. Assert.False (v3.HasFocus);
  44. v1.CanFocus = true;
  45. v1.TabStop = behavior;
  46. r.AdvanceFocus (NavigationDirection.Forward, behavior);
  47. Assert.True (v1.HasFocus);
  48. Assert.False (v2.HasFocus);
  49. Assert.False (v3.HasFocus);
  50. v2.CanFocus = true;
  51. v2.TabStop = behavior;
  52. r.AdvanceFocus (NavigationDirection.Forward, behavior);
  53. Assert.False (v1.HasFocus);
  54. Assert.True (v2.HasFocus);
  55. Assert.False (v3.HasFocus);
  56. v3.CanFocus = true;
  57. v3.TabStop = behavior;
  58. r.AdvanceFocus (NavigationDirection.Forward, behavior);
  59. Assert.False (v1.HasFocus);
  60. Assert.False (v2.HasFocus);
  61. Assert.True (v3.HasFocus);
  62. r.Dispose ();
  63. }
  64. [Fact]
  65. public void AdvanceFocus_Compound_Subview ()
  66. {
  67. var top = new View { Id = "top", CanFocus = true };
  68. var compoundSubview = new View
  69. {
  70. CanFocus = true,
  71. Id = "compoundSubview"
  72. };
  73. var v1 = new View { Id = "v1", CanFocus = true };
  74. var v2 = new View { Id = "v2", CanFocus = true };
  75. var v3 = new View { Id = "v3", CanFocus = false };
  76. compoundSubview.Add (v1, v2, v3);
  77. top.Add (compoundSubview);
  78. // Cycle through v1 & v2
  79. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  80. Assert.True (v1.HasFocus);
  81. Assert.False (v2.HasFocus);
  82. Assert.False (v3.HasFocus);
  83. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  84. Assert.False (v1.HasFocus);
  85. Assert.True (v2.HasFocus);
  86. Assert.False (v3.HasFocus);
  87. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  88. Assert.True (v1.HasFocus);
  89. Assert.False (v2.HasFocus);
  90. Assert.False (v3.HasFocus);
  91. // Add another subview
  92. View otherSubview = new ()
  93. {
  94. CanFocus = true,
  95. Id = "otherSubview"
  96. };
  97. top.Add (otherSubview);
  98. // Adding a focusable subview causes advancefocus
  99. Assert.True (otherSubview.HasFocus);
  100. Assert.False (v1.HasFocus);
  101. // Cycle through v1 & v2
  102. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  103. Assert.True (v1.HasFocus);
  104. Assert.False (v2.HasFocus);
  105. Assert.False (v3.HasFocus);
  106. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  107. Assert.False (v1.HasFocus);
  108. Assert.True (v2.HasFocus);
  109. Assert.False (v3.HasFocus);
  110. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  111. Assert.False (v1.HasFocus);
  112. Assert.False (v2.HasFocus);
  113. Assert.False (v3.HasFocus);
  114. Assert.True (otherSubview.HasFocus);
  115. // v2 was previously focused down the compoundSubView focus chain
  116. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  117. Assert.False (v1.HasFocus);
  118. Assert.True (v2.HasFocus);
  119. Assert.False (v3.HasFocus);
  120. top.Dispose ();
  121. }
  122. [Fact]
  123. public void AdvanceFocus_NoStop_And_CanFocus_True_No_Focus ()
  124. {
  125. var r = new View ();
  126. var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  127. var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  128. var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  129. r.Add (v1, v2, v3);
  130. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  131. Assert.False (v1.HasFocus);
  132. Assert.False (v2.HasFocus);
  133. Assert.False (v3.HasFocus);
  134. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  135. Assert.False (v1.HasFocus);
  136. Assert.False (v2.HasFocus);
  137. Assert.False (v3.HasFocus);
  138. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  139. Assert.False (v1.HasFocus);
  140. Assert.False (v2.HasFocus);
  141. Assert.False (v3.HasFocus);
  142. r.Dispose ();
  143. }
  144. [Fact]
  145. public void AdvanceFocus_NoStop_Change_Enables_Stop ()
  146. {
  147. var r = new View { CanFocus = true };
  148. var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  149. var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  150. var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  151. r.Add (v1, v2, v3);
  152. v1.TabStop = TabBehavior.TabStop;
  153. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  154. Assert.True (v1.HasFocus);
  155. Assert.False (v2.HasFocus);
  156. Assert.False (v3.HasFocus);
  157. v2.TabStop = TabBehavior.TabStop;
  158. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  159. Assert.False (v1.HasFocus);
  160. Assert.True (v2.HasFocus);
  161. Assert.False (v3.HasFocus);
  162. v3.TabStop = TabBehavior.TabStop;
  163. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  164. Assert.False (v1.HasFocus);
  165. Assert.False (v2.HasFocus);
  166. Assert.True (v3.HasFocus);
  167. r.Dispose ();
  168. }
  169. [Fact]
  170. public void AdvanceFocus_NoStop_Prevents_Stop ()
  171. {
  172. var r = new View ();
  173. var v1 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  174. var v2 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  175. var v3 = new View { CanFocus = true, TabStop = TabBehavior.NoStop };
  176. r.Add (v1, v2, v3);
  177. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  178. Assert.False (v1.HasFocus);
  179. Assert.False (v2.HasFocus);
  180. Assert.False (v3.HasFocus);
  181. }
  182. [Fact]
  183. public void AdvanceFocus_Null_And_CanFocus_False_No_Advance ()
  184. {
  185. var r = new View ();
  186. var v1 = new View ();
  187. var v2 = new View ();
  188. var v3 = new View ();
  189. Assert.False (v1.CanFocus);
  190. Assert.Null (v1.TabStop);
  191. r.Add (v1, v2, v3);
  192. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  193. Assert.False (v1.HasFocus);
  194. Assert.False (v2.HasFocus);
  195. Assert.False (v3.HasFocus);
  196. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  197. Assert.False (v1.HasFocus);
  198. Assert.False (v2.HasFocus);
  199. Assert.False (v3.HasFocus);
  200. r.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  201. Assert.False (v1.HasFocus);
  202. Assert.False (v2.HasFocus);
  203. Assert.False (v3.HasFocus);
  204. r.Dispose ();
  205. }
  206. [Fact]
  207. public void AdvanceFocus_Subviews_Raises_HasFocusChanged ()
  208. {
  209. var top = new View
  210. {
  211. Id = "top",
  212. CanFocus = true
  213. };
  214. var subView1 = new View
  215. {
  216. Id = "subView1",
  217. CanFocus = true
  218. };
  219. var subView2 = new View
  220. {
  221. Id = "subView2",
  222. CanFocus = true
  223. };
  224. top.Add (subView1, subView2);
  225. var subView1HasFocusChangedTrueCount = 0;
  226. var subView1HasFocusChangedFalseCount = 0;
  227. subView1.HasFocusChanged += (s, e) =>
  228. {
  229. if (e.NewValue)
  230. {
  231. subView1HasFocusChangedTrueCount++;
  232. }
  233. else
  234. {
  235. subView1HasFocusChangedFalseCount++;
  236. }
  237. };
  238. var subView2HasFocusChangedTrueCount = 0;
  239. var subView2HasFocusChangedFalseCount = 0;
  240. subView2.HasFocusChanged += (s, e) =>
  241. {
  242. if (e.NewValue)
  243. {
  244. subView2HasFocusChangedTrueCount++;
  245. }
  246. else
  247. {
  248. subView2HasFocusChangedFalseCount++;
  249. }
  250. };
  251. top.SetFocus ();
  252. Assert.True (top.HasFocus);
  253. Assert.True (subView1.HasFocus);
  254. Assert.False (subView2.HasFocus);
  255. Assert.Equal (1, subView1HasFocusChangedTrueCount);
  256. Assert.Equal (0, subView1HasFocusChangedFalseCount);
  257. Assert.Equal (0, subView2HasFocusChangedTrueCount);
  258. Assert.Equal (0, subView2HasFocusChangedFalseCount);
  259. top.AdvanceFocus (NavigationDirection.Forward, null);
  260. Assert.False (subView1.HasFocus);
  261. Assert.True (subView2.HasFocus);
  262. Assert.Equal (1, subView1HasFocusChangedTrueCount);
  263. Assert.Equal (1, subView1HasFocusChangedFalseCount);
  264. Assert.Equal (1, subView2HasFocusChangedTrueCount);
  265. Assert.Equal (0, subView2HasFocusChangedFalseCount);
  266. top.AdvanceFocus (NavigationDirection.Forward, null);
  267. Assert.True (subView1.HasFocus);
  268. Assert.False (subView2.HasFocus);
  269. Assert.Equal (2, subView1HasFocusChangedTrueCount);
  270. Assert.Equal (1, subView1HasFocusChangedFalseCount);
  271. Assert.Equal (1, subView2HasFocusChangedTrueCount);
  272. Assert.Equal (1, subView2HasFocusChangedFalseCount);
  273. }
  274. [Fact]
  275. public void AdvanceFocus_Subviews_Raises_HasFocusChanging ()
  276. {
  277. var top = new View
  278. {
  279. Id = "top",
  280. CanFocus = true
  281. };
  282. var subView1 = new View
  283. {
  284. Id = "subView1",
  285. CanFocus = true
  286. };
  287. var subView2 = new View
  288. {
  289. Id = "subView2",
  290. CanFocus = true
  291. };
  292. top.Add (subView1, subView2);
  293. var subView1HasFocusChangingTrueCount = 0;
  294. var subView1HasFocusChangingFalseCount = 0;
  295. subView1.HasFocusChanging += (s, e) =>
  296. {
  297. if (e.NewValue)
  298. {
  299. subView1HasFocusChangingTrueCount++;
  300. }
  301. else
  302. {
  303. subView1HasFocusChangingFalseCount++;
  304. }
  305. };
  306. var subView2HasFocusChangingTrueCount = 0;
  307. var subView2HasFocusChangingFalseCount = 0;
  308. subView2.HasFocusChanging += (s, e) =>
  309. {
  310. if (e.NewValue)
  311. {
  312. subView2HasFocusChangingTrueCount++;
  313. }
  314. else
  315. {
  316. subView2HasFocusChangingFalseCount++;
  317. }
  318. };
  319. top.SetFocus ();
  320. Assert.True (top.HasFocus);
  321. Assert.True (subView1.HasFocus);
  322. Assert.False (subView2.HasFocus);
  323. Assert.Equal (1, subView1HasFocusChangingTrueCount);
  324. Assert.Equal (0, subView1HasFocusChangingFalseCount);
  325. Assert.Equal (0, subView2HasFocusChangingTrueCount);
  326. Assert.Equal (0, subView2HasFocusChangingFalseCount);
  327. top.AdvanceFocus (NavigationDirection.Forward, null);
  328. Assert.False (subView1.HasFocus);
  329. Assert.True (subView2.HasFocus);
  330. Assert.Equal (1, subView1HasFocusChangingTrueCount);
  331. Assert.Equal (1, subView1HasFocusChangingFalseCount);
  332. Assert.Equal (1, subView2HasFocusChangingTrueCount);
  333. Assert.Equal (0, subView2HasFocusChangingFalseCount);
  334. top.AdvanceFocus (NavigationDirection.Forward, null);
  335. Assert.True (subView1.HasFocus);
  336. Assert.False (subView2.HasFocus);
  337. Assert.Equal (2, subView1HasFocusChangingTrueCount);
  338. Assert.Equal (1, subView1HasFocusChangingFalseCount);
  339. Assert.Equal (1, subView2HasFocusChangingTrueCount);
  340. Assert.Equal (1, subView2HasFocusChangingFalseCount);
  341. }
  342. [Fact]
  343. public void AdvanceFocus_With_CanFocus_Are_All_True ()
  344. {
  345. var top = new View { Id = "top", CanFocus = true };
  346. var v1 = new View { Id = "v1", CanFocus = true };
  347. var v2 = new View { Id = "v2", CanFocus = true };
  348. var v3 = new View { Id = "v3", CanFocus = true };
  349. top.Add (v1, v2, v3);
  350. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  351. Assert.True (v1.HasFocus);
  352. Assert.False (v2.HasFocus);
  353. Assert.False (v3.HasFocus);
  354. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  355. Assert.False (v1.HasFocus);
  356. Assert.True (v2.HasFocus);
  357. Assert.False (v3.HasFocus);
  358. top.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
  359. Assert.False (v1.HasFocus);
  360. Assert.False (v2.HasFocus);
  361. Assert.True (v3.HasFocus);
  362. top.Dispose ();
  363. }
  364. [Theory]
  365. [CombinatorialData]
  366. public void TabStop_And_CanFocus_Are_Decoupled (bool canFocus, TabBehavior tabStop)
  367. {
  368. var view = new View { CanFocus = canFocus, TabStop = tabStop };
  369. Assert.Equal (canFocus, view.CanFocus);
  370. Assert.Equal (tabStop, view.TabStop);
  371. }
  372. }