SubviewTests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. namespace Terminal.Gui.ViewTests;
  2. public class SubViewTests
  3. {
  4. [Fact]
  5. public void SuperViewChanged_Raised_On_Add ()
  6. {
  7. var super = new View { };
  8. var sub = new View ();
  9. int superRaisedCount = 0;
  10. int subRaisedCount = 0;
  11. super.SuperViewChanged += (s, e) =>
  12. {
  13. superRaisedCount++;
  14. };
  15. sub.SuperViewChanged += (s, e) =>
  16. {
  17. if (e.SuperView is {})
  18. {
  19. subRaisedCount++;
  20. }
  21. };
  22. super.Add (sub);
  23. Assert.True (super.SubViews.Count == 1);
  24. Assert.Equal (super, sub.SuperView);
  25. Assert.Equal (0, superRaisedCount);
  26. Assert.Equal (1, subRaisedCount);
  27. }
  28. [Fact]
  29. public void SuperViewChanged_Raised_On_Remove ()
  30. {
  31. var super = new View { };
  32. var sub = new View ();
  33. int superRaisedCount = 0;
  34. int subRaisedCount = 0;
  35. super.SuperViewChanged += (s, e) =>
  36. {
  37. superRaisedCount++;
  38. };
  39. sub.SuperViewChanged += (s, e) =>
  40. {
  41. if (e.SuperView is null)
  42. {
  43. subRaisedCount++;
  44. }
  45. };
  46. super.Add (sub);
  47. Assert.True (super.SubViews.Count == 1);
  48. Assert.Equal (super, sub.SuperView);
  49. Assert.Equal (0, superRaisedCount);
  50. Assert.Equal (0, subRaisedCount);
  51. super.Remove (sub);
  52. Assert.Empty (super.SubViews);
  53. Assert.NotEqual (super, sub.SuperView);
  54. Assert.Equal (0, superRaisedCount);
  55. Assert.Equal (1, subRaisedCount);
  56. }
  57. [Fact]
  58. public void SuperView_Set_On_Add_Remove ()
  59. {
  60. var superView = new View ();
  61. var view = new View ();
  62. Assert.Null (view.SuperView);
  63. superView.Add (view);
  64. Assert.Equal (superView, view.SuperView);
  65. superView.Remove (view);
  66. Assert.Null (view.SuperView);
  67. }
  68. // TODO: Consider a feature that will change the ContentSize to fit the subviews.
  69. [Fact]
  70. public void Add_Does_Not_Impact_ContentSize ()
  71. {
  72. var view = new View ();
  73. view.SetContentSize (new Size (1, 1));
  74. var subview = new View
  75. {
  76. X = 10,
  77. Y = 10
  78. };
  79. Assert.Equal (new (1, 1), view.GetContentSize ());
  80. view.Add (subview);
  81. Assert.Equal (new (1, 1), view.GetContentSize ());
  82. }
  83. [Fact]
  84. public void Remove_Does_Not_Impact_ContentSize ()
  85. {
  86. var view = new View ();
  87. view.SetContentSize (new Size (1, 1));
  88. var subview = new View
  89. {
  90. X = 10,
  91. Y = 10
  92. };
  93. Assert.Equal (new (1, 1), view.GetContentSize ());
  94. view.Add (subview);
  95. Assert.Equal (new (1, 1), view.GetContentSize ());
  96. view.SetContentSize (new Size (5, 5));
  97. Assert.Equal (new (5, 5), view.GetContentSize ());
  98. view.Remove (subview);
  99. Assert.Equal (new (5, 5), view.GetContentSize ());
  100. }
  101. [Fact]
  102. public void MoveSubViewToStart ()
  103. {
  104. View superView = new ();
  105. var subview1 = new View
  106. {
  107. Id = "subview1"
  108. };
  109. var subview2 = new View
  110. {
  111. Id = "subview2"
  112. };
  113. var subview3 = new View
  114. {
  115. Id = "subview3"
  116. };
  117. superView.Add (subview1, subview2, subview3);
  118. superView.MoveSubViewToStart (subview2);
  119. Assert.Equal (subview2, superView.SubViews.ElementAt (0));
  120. superView.MoveSubViewToStart (subview3);
  121. Assert.Equal (subview3, superView.SubViews.ElementAt (0));
  122. }
  123. [Fact]
  124. public void MoveSubViewTowardsFront ()
  125. {
  126. View superView = new ();
  127. var subview1 = new View
  128. {
  129. Id = "subview1"
  130. };
  131. var subview2 = new View
  132. {
  133. Id = "subview2"
  134. };
  135. var subview3 = new View
  136. {
  137. Id = "subview3"
  138. };
  139. superView.Add (subview1, subview2, subview3);
  140. superView.MoveSubViewTowardsStart (subview2);
  141. Assert.Equal (subview2, superView.SubViews.ElementAt (0));
  142. superView.MoveSubViewTowardsStart (subview3);
  143. Assert.Equal (subview3, superView.SubViews.ElementAt (1));
  144. // Already at front, what happens?
  145. superView.MoveSubViewTowardsStart (subview2);
  146. Assert.Equal (subview2, superView.SubViews.ElementAt (0));
  147. }
  148. [Fact]
  149. public void MoveSubViewToEnd ()
  150. {
  151. View superView = new ();
  152. var subview1 = new View
  153. {
  154. Id = "subview1"
  155. };
  156. var subview2 = new View
  157. {
  158. Id = "subview2"
  159. };
  160. var subview3 = new View
  161. {
  162. Id = "subview3"
  163. };
  164. superView.Add (subview1, subview2, subview3);
  165. superView.MoveSubViewToEnd (subview1);
  166. Assert.Equal (subview1, superView.SubViews.ToArray () [^1]);
  167. superView.MoveSubViewToEnd (subview2);
  168. Assert.Equal (subview2, superView.SubViews.ToArray () [^1]);
  169. }
  170. [Fact]
  171. public void MoveSubViewTowardsEnd ()
  172. {
  173. View superView = new ();
  174. var subview1 = new View
  175. {
  176. Id = "subview1"
  177. };
  178. var subview2 = new View
  179. {
  180. Id = "subview2"
  181. };
  182. var subview3 = new View
  183. {
  184. Id = "subview3"
  185. };
  186. superView.Add (subview1, subview2, subview3);
  187. superView.MoveSubViewTowardsEnd (subview2);
  188. Assert.Equal (subview2, superView.SubViews.ToArray() [^1]);
  189. superView.MoveSubViewTowardsEnd (subview1);
  190. Assert.Equal (subview1, superView.SubViews.ToArray() [1]);
  191. // Already at end, what happens?
  192. superView.MoveSubViewTowardsEnd (subview2);
  193. Assert.Equal (subview2, superView.SubViews.ToArray() [^1]);
  194. }
  195. [Fact]
  196. public void IsInHierarchy_ViewIsNull_ReturnsFalse ()
  197. {
  198. // Arrange
  199. var start = new View ();
  200. // Act
  201. bool result = View.IsInHierarchy (start, null);
  202. // Assert
  203. Assert.False (result);
  204. }
  205. [Fact]
  206. public void IsInHierarchy_StartIsNull_ReturnsFalse ()
  207. {
  208. // Arrange
  209. var view = new View ();
  210. // Act
  211. bool result = View.IsInHierarchy (null, view);
  212. // Assert
  213. Assert.False (result);
  214. }
  215. [Fact]
  216. public void IsInHierarchy_ViewIsStart_ReturnsTrue ()
  217. {
  218. // Arrange
  219. var start = new View ();
  220. // Act
  221. bool result = View.IsInHierarchy (start, start);
  222. // Assert
  223. Assert.True (result);
  224. }
  225. [Fact]
  226. public void IsInHierarchy_ViewIsDirectSubView_ReturnsTrue ()
  227. {
  228. // Arrange
  229. var start = new View ();
  230. var subview = new View ();
  231. start.Add (subview);
  232. // Act
  233. bool result = View.IsInHierarchy (start, subview);
  234. // Assert
  235. Assert.True (result);
  236. }
  237. [Fact]
  238. public void IsInHierarchy_ViewIsNestedSubView_ReturnsTrue ()
  239. {
  240. // Arrange
  241. var start = new View ();
  242. var subview = new View ();
  243. var nestedSubView = new View ();
  244. start.Add (subview);
  245. subview.Add (nestedSubView);
  246. // Act
  247. bool result = View.IsInHierarchy (start, nestedSubView);
  248. // Assert
  249. Assert.True (result);
  250. }
  251. [Fact]
  252. public void IsInHierarchy_ViewIsNotInHierarchy_ReturnsFalse ()
  253. {
  254. // Arrange
  255. var start = new View ();
  256. var subview = new View ();
  257. // Act
  258. bool result = View.IsInHierarchy (start, subview);
  259. // Assert
  260. Assert.False (result);
  261. }
  262. [Theory]
  263. [CombinatorialData]
  264. public void IsInHierarchy_ViewIsInAdornments_ReturnsTrue (bool includeAdornments)
  265. {
  266. // Arrange
  267. var start = new View
  268. {
  269. Id = "start"
  270. };
  271. var inPadding = new View
  272. {
  273. Id = "inPadding"
  274. };
  275. start.Padding!.Add (inPadding);
  276. // Act
  277. bool result = View.IsInHierarchy (start, inPadding, includeAdornments);
  278. // Assert
  279. Assert.Equal (includeAdornments, result);
  280. }
  281. [Fact]
  282. public void SuperView_Set_Raises_SuperViewChangedEvents ()
  283. {
  284. // Arrange
  285. var view = new View ();
  286. var superView = new View ();
  287. int superViewChangedCount = 0;
  288. //int superViewChangingCount = 0;
  289. view.SuperViewChanged += (s, e) =>
  290. {
  291. superViewChangedCount++;
  292. };
  293. //view.SuperViewChanging += (s, e) =>
  294. //{
  295. // superViewChangingCount++;
  296. //};
  297. // Act
  298. superView.Add (view);
  299. // Assert
  300. //Assert.Equal (1, superViewChangingCount);
  301. Assert.Equal (1, superViewChangedCount);
  302. }
  303. [Fact]
  304. public void GetTopSuperView_Test ()
  305. {
  306. var v1 = new View ();
  307. var fv1 = new FrameView ();
  308. fv1.Add (v1);
  309. var tf1 = new TextField ();
  310. var w1 = new Window ();
  311. w1.Add (fv1, tf1);
  312. var top1 = new Toplevel ();
  313. top1.Add (w1);
  314. var v2 = new View ();
  315. var fv2 = new FrameView ();
  316. fv2.Add (v2);
  317. var tf2 = new TextField ();
  318. var w2 = new Window ();
  319. w2.Add (fv2, tf2);
  320. var top2 = new Toplevel ();
  321. top2.Add (w2);
  322. Assert.Equal (top1, v1.GetTopSuperView ());
  323. Assert.Equal (top2, v2.GetTopSuperView ());
  324. v1.Dispose ();
  325. fv1.Dispose ();
  326. tf1.Dispose ();
  327. w1.Dispose ();
  328. top1.Dispose ();
  329. v2.Dispose ();
  330. fv2.Dispose ();
  331. tf2.Dispose ();
  332. w2.Dispose ();
  333. top2.Dispose ();
  334. }
  335. [Fact]
  336. public void Initialized_Event_Comparing_With_Added_Event ()
  337. {
  338. var top = new Toplevel { Id = "0" }; // Frame: 0, 0, 80, 25; Viewport: 0, 0, 80, 25
  339. var winAddedToTop = new Window
  340. {
  341. Id = "t", Width = Dim.Fill (), Height = Dim.Fill ()
  342. }; // Frame: 0, 0, 80, 25; Viewport: 0, 0, 78, 23
  343. var v1AddedToWin = new View
  344. {
  345. Id = "v1", Width = Dim.Fill (), Height = Dim.Fill ()
  346. }; // Frame: 1, 1, 78, 23 (because Windows has a border)
  347. var v2AddedToWin = new View
  348. {
  349. Id = "v2", Width = Dim.Fill (), Height = Dim.Fill ()
  350. }; // Frame: 1, 1, 78, 23 (because Windows has a border)
  351. var svAddedTov1 = new View
  352. {
  353. Id = "sv1", Width = Dim.Fill (), Height = Dim.Fill ()
  354. }; // Frame: 1, 1, 78, 23 (same as it's superview v1AddedToWin)
  355. int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0;
  356. winAddedToTop.SubViewAdded += (s, e) =>
  357. {
  358. Assert.Equal (e.SuperView.Frame.Width, winAddedToTop.Frame.Width);
  359. Assert.Equal (e.SuperView.Frame.Height, winAddedToTop.Frame.Height);
  360. };
  361. v1AddedToWin.SubViewAdded += (s, e) =>
  362. {
  363. Assert.Equal (e.SuperView.Frame.Width, v1AddedToWin.Frame.Width);
  364. Assert.Equal (e.SuperView.Frame.Height, v1AddedToWin.Frame.Height);
  365. };
  366. v2AddedToWin.SubViewAdded += (s, e) =>
  367. {
  368. Assert.Equal (e.SuperView.Frame.Width, v2AddedToWin.Frame.Width);
  369. Assert.Equal (e.SuperView.Frame.Height, v2AddedToWin.Frame.Height);
  370. };
  371. svAddedTov1.SubViewAdded += (s, e) =>
  372. {
  373. Assert.Equal (e.SuperView.Frame.Width, svAddedTov1.Frame.Width);
  374. Assert.Equal (e.SuperView.Frame.Height, svAddedTov1.Frame.Height);
  375. };
  376. top.Initialized += (s, e) =>
  377. {
  378. tc++;
  379. Assert.Equal (1, tc);
  380. Assert.Equal (1, wc);
  381. Assert.Equal (1, v1c);
  382. Assert.Equal (1, v2c);
  383. Assert.Equal (1, sv1c);
  384. Assert.True (top.CanFocus);
  385. Assert.True (winAddedToTop.CanFocus);
  386. Assert.False (v1AddedToWin.CanFocus);
  387. Assert.False (v2AddedToWin.CanFocus);
  388. Assert.False (svAddedTov1.CanFocus);
  389. Application.LayoutAndDraw ();
  390. };
  391. winAddedToTop.Initialized += (s, e) =>
  392. {
  393. wc++;
  394. Assert.Equal (top.Viewport.Width, winAddedToTop.Frame.Width);
  395. Assert.Equal (top.Viewport.Height, winAddedToTop.Frame.Height);
  396. };
  397. v1AddedToWin.Initialized += (s, e) =>
  398. {
  399. v1c++;
  400. // Top.Frame: 0, 0, 80, 25; Top.Viewport: 0, 0, 80, 25
  401. // BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
  402. // in no way should the v1AddedToWin.Frame be the same as the Top.Frame/Viewport
  403. // as it is a subview of winAddedToTop, which has a border!
  404. //Assert.Equal (top.Viewport.Width, v1AddedToWin.Frame.Width);
  405. //Assert.Equal (top.Viewport.Height, v1AddedToWin.Frame.Height);
  406. };
  407. v2AddedToWin.Initialized += (s, e) =>
  408. {
  409. v2c++;
  410. // Top.Frame: 0, 0, 80, 25; Top.Viewport: 0, 0, 80, 25
  411. // BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
  412. // in no way should the v2AddedToWin.Frame be the same as the Top.Frame/Viewport
  413. // as it is a subview of winAddedToTop, which has a border!
  414. //Assert.Equal (top.Viewport.Width, v2AddedToWin.Frame.Width);
  415. //Assert.Equal (top.Viewport.Height, v2AddedToWin.Frame.Height);
  416. };
  417. svAddedTov1.Initialized += (s, e) =>
  418. {
  419. sv1c++;
  420. // Top.Frame: 0, 0, 80, 25; Top.Viewport: 0, 0, 80, 25
  421. // BUGBUG: This is wrong, it should be 78, 23. This test has always been broken.
  422. // in no way should the svAddedTov1.Frame be the same as the Top.Frame/Viewport
  423. // because sv1AddedTov1 is a subview of v1AddedToWin, which is a subview of
  424. // winAddedToTop, which has a border!
  425. //Assert.Equal (top.Viewport.Width, svAddedTov1.Frame.Width);
  426. //Assert.Equal (top.Viewport.Height, svAddedTov1.Frame.Height);
  427. Assert.False (svAddedTov1.CanFocus);
  428. //Assert.Throws<InvalidOperationException> (() => svAddedTov1.CanFocus = true);
  429. Assert.False (svAddedTov1.CanFocus);
  430. };
  431. v1AddedToWin.Add (svAddedTov1);
  432. winAddedToTop.Add (v1AddedToWin, v2AddedToWin);
  433. top.Add (winAddedToTop);
  434. top.BeginInit ();
  435. top.EndInit ();
  436. Assert.Equal (1, tc);
  437. Assert.Equal (1, wc);
  438. Assert.Equal (1, v1c);
  439. Assert.Equal (1, v2c);
  440. Assert.Equal (1, sv1c);
  441. Assert.True (top.CanFocus);
  442. Assert.True (winAddedToTop.CanFocus);
  443. Assert.False (v1AddedToWin.CanFocus);
  444. Assert.False (v2AddedToWin.CanFocus);
  445. Assert.False (svAddedTov1.CanFocus);
  446. v1AddedToWin.CanFocus = true;
  447. Assert.False (svAddedTov1.CanFocus); // False because sv1 was disposed and it isn't a subview of v1.
  448. }
  449. [Fact]
  450. public void SuperViewChanged_Raised_On_SubViewAdded_SubViewRemoved ()
  451. {
  452. var isAdded = false;
  453. View superView = new () { Id = "superView" };
  454. View subView = new () { Id = "subView" };
  455. superView.SubViewAdded += (s, e) =>
  456. {
  457. Assert.True (isAdded);
  458. Assert.Equal (superView, subView.SuperView);
  459. Assert.Equal (subView, e.SubView);
  460. Assert.Equal (superView, e.SuperView);
  461. };
  462. superView.SubViewRemoved += (s, e) =>
  463. {
  464. Assert.False (isAdded);
  465. Assert.NotEqual (superView, subView.SuperView);
  466. Assert.Equal (subView, e.SubView);
  467. Assert.Equal (superView, e.SuperView);
  468. };
  469. subView.SuperViewChanged += (s, e) => { isAdded = subView.SuperView == superView; };
  470. superView.Add (subView);
  471. Assert.True (isAdded);
  472. Assert.Equal (superView, subView.SuperView);
  473. Assert.Single (superView.SubViews);
  474. superView.Remove (subView);
  475. Assert.False (isAdded);
  476. Assert.NotEqual (superView, subView.SuperView);
  477. Assert.Empty (superView.SubViews);
  478. }
  479. }