Dim.Tests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. using System.Globalization;
  2. using System.Text;
  3. using Xunit.Abstractions;
  4. using static Terminal.Gui.Dim;
  5. namespace Terminal.Gui.LayoutTests;
  6. public class DimTests
  7. {
  8. private readonly ITestOutputHelper _output;
  9. public DimTests (ITestOutputHelper output)
  10. {
  11. _output = output;
  12. Console.OutputEncoding = Encoding.Default;
  13. // Change current culture
  14. var culture = CultureInfo.CreateSpecificCulture ("en-US");
  15. Thread.CurrentThread.CurrentCulture = culture;
  16. Thread.CurrentThread.CurrentUICulture = culture;
  17. }
  18. [Fact]
  19. public void DimAbsolute_Calculate_ReturnsCorrectValue ()
  20. {
  21. var dim = new DimAbsolute (10);
  22. int result = dim.Calculate (0, 100, null, Dimension.None);
  23. Assert.Equal (10, result);
  24. }
  25. // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
  26. // TODO: A new test that calls SetRelativeLayout directly is needed.
  27. [Fact]
  28. [TestRespondersDisposed]
  29. public void Dim_Validation_Do_Not_Throws_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Null ()
  30. {
  31. var t = new View { Width = 80, Height = 25, Text = "top" };
  32. var w = new Window
  33. {
  34. X = 1,
  35. Y = 2,
  36. Width = 4,
  37. Height = 5,
  38. Title = "w"
  39. };
  40. t.Add (w);
  41. t.LayoutSubviews ();
  42. Assert.Equal (3, w.Width = 3);
  43. Assert.Equal (4, w.Height = 4);
  44. t.Dispose ();
  45. }
  46. [Fact]
  47. public void DimHeight_Set_To_Null_Throws ()
  48. {
  49. Dim dim = Height (null);
  50. Assert.Throws<NullReferenceException> (() => dim.ToString ());
  51. }
  52. [Fact]
  53. [TestRespondersDisposed]
  54. public void DimHeight_SetsValue ()
  55. {
  56. var testVal = Rectangle.Empty;
  57. var testValview = new View { Frame = testVal };
  58. Dim dim = Height (testValview);
  59. Assert.Equal ($"View(Height,View(){testVal})", dim.ToString ());
  60. testValview.Dispose ();
  61. testVal = new (1, 2, 3, 4);
  62. testValview = new () { Frame = testVal };
  63. dim = Height (testValview);
  64. Assert.Equal ($"View(Height,View(){testVal})", dim.ToString ());
  65. testValview.Dispose ();
  66. }
  67. [Fact]
  68. [TestRespondersDisposed]
  69. public void Internal_Tests ()
  70. {
  71. var dimFactor = new DimPercent (10);
  72. Assert.Equal (10, dimFactor.GetAnchor (100));
  73. var dimAbsolute = new DimAbsolute (10);
  74. Assert.Equal (10, dimAbsolute.GetAnchor (0));
  75. var dimFill = new DimFill (1);
  76. Assert.Equal (99, dimFill.GetAnchor (100));
  77. var dimCombine = new DimCombine (AddOrSubtract.Add, dimFactor, dimAbsolute);
  78. Assert.Equal (dimCombine.Left, dimFactor);
  79. Assert.Equal (dimCombine.Right, dimAbsolute);
  80. Assert.Equal (20, dimCombine.GetAnchor (100));
  81. var view = new View { Frame = new (20, 10, 20, 1) };
  82. var dimViewHeight = new DimView (view, Dimension.Height);
  83. Assert.Equal (1, dimViewHeight.GetAnchor (0));
  84. var dimViewWidth = new DimView (view, Dimension.Width);
  85. Assert.Equal (20, dimViewWidth.GetAnchor (0));
  86. view.Dispose ();
  87. }
  88. // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
  89. // TODO: A new test that calls SetRelativeLayout directly is needed.
  90. [Fact]
  91. [AutoInitShutdown]
  92. public void Only_DimAbsolute_And_DimFactor_As_A_Different_Procedure_For_Assigning_Value_To_Width_Or_Height ()
  93. {
  94. // Override CM
  95. Button.DefaultShadow = ShadowStyle.None;
  96. // Testing with the Button because it properly handles the Dim class.
  97. Toplevel t = new ();
  98. var w = new Window { Width = 100, Height = 100 };
  99. var f1 = new FrameView
  100. {
  101. X = 0,
  102. Y = 0,
  103. Width = Percent (50),
  104. Height = 5,
  105. Title = "f1"
  106. };
  107. var f2 = new FrameView
  108. {
  109. X = Pos.Right (f1),
  110. Y = 0,
  111. Width = Fill (),
  112. Height = 5,
  113. Title = "f2"
  114. };
  115. var v1 = new Button
  116. {
  117. X = Pos.X (f1) + 2,
  118. Y = Pos.Bottom (f1) + 2,
  119. Width = Width (f1) - 2,
  120. Height = Fill () - 2,
  121. ValidatePosDim = true,
  122. Text = "v1"
  123. };
  124. var v2 = new Button
  125. {
  126. X = Pos.X (f2) + 2,
  127. Y = Pos.Bottom (f2) + 2,
  128. Width = Width (f2) - 2,
  129. Height = Fill () - 2,
  130. ValidatePosDim = true,
  131. Text = "v2"
  132. };
  133. var v3 = new Button
  134. {
  135. Width = Percent (10),
  136. Height = Percent (10),
  137. ValidatePosDim = true,
  138. Text = "v3"
  139. };
  140. var v4 = new Button
  141. {
  142. Width = Absolute (50),
  143. Height = Absolute (50),
  144. ValidatePosDim = true,
  145. Text = "v4"
  146. };
  147. var v5 = new Button
  148. {
  149. Width = Width (v1) - Width (v3),
  150. Height = Height (v1) - Height (v3),
  151. ValidatePosDim = true,
  152. Text = "v5"
  153. };
  154. var v6 = new Button
  155. {
  156. X = Pos.X (f2),
  157. Y = Pos.Bottom (f2) + 2,
  158. Width = Percent (20, DimPercentMode.Position),
  159. Height = Percent (20, DimPercentMode.Position),
  160. ValidatePosDim = true,
  161. Text = "v6"
  162. };
  163. w.Add (f1, f2, v1, v2, v3, v4, v5, v6);
  164. t.Add (w);
  165. t.Ready += (s, e) =>
  166. {
  167. Assert.Equal ("Absolute(100)", w.Width.ToString ());
  168. Assert.Equal ("Absolute(100)", w.Height.ToString ());
  169. Assert.Equal (100, w.Frame.Width);
  170. Assert.Equal (100, w.Frame.Height);
  171. Assert.Equal ("Absolute(5)", f1.Height.ToString ());
  172. Assert.Equal (49, f1.Frame.Width); // 50-1=49
  173. Assert.Equal (5, f1.Frame.Height);
  174. Assert.Equal ("Fill(Absolute(0))", f2.Width.ToString ());
  175. Assert.Equal ("Absolute(5)", f2.Height.ToString ());
  176. Assert.Equal (49, f2.Frame.Width); // 50-1=49
  177. Assert.Equal (5, f2.Frame.Height);
  178. #if DEBUG
  179. Assert.Equal ($"Combine(View(Width,FrameView(f1){f1.Border.Frame})-Absolute(2))", v1.Width.ToString ());
  180. #else
  181. Assert.Equal ($"Combine(View(Width,FrameView(){f1.Border.Frame})-Absolute(2))", v1.Width.ToString ());
  182. #endif
  183. Assert.Equal ("Combine(Fill(Absolute(0))-Absolute(2))", v1.Height.ToString ());
  184. Assert.Equal (47, v1.Frame.Width); // 49-2=47
  185. Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89
  186. #if DEBUG
  187. Assert.Equal (
  188. $"Combine(View(Width,FrameView(f2){f2.Frame})-Absolute(2))",
  189. v2.Width.ToString ()
  190. #else
  191. Assert.Equal (
  192. $"Combine(View(Width,FrameView(){f2.Frame})-Absolute(2))",
  193. v2.Width.ToString ()
  194. #endif
  195. );
  196. #if DEBUG
  197. Assert.Equal ("Combine(Fill(Absolute(0))-Absolute(2))", v2.Height.ToString ());
  198. #else
  199. Assert.Equal ("Combine(Fill(Absolute(0))-Absolute(2))", v2.Height.ToString ());
  200. #endif
  201. Assert.Equal (47, v2.Frame.Width); // 49-2=47
  202. Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89
  203. Assert.Equal (9, v3.Frame.Width); // 98*10%=9
  204. Assert.Equal (9, v3.Frame.Height); // 98*10%=9
  205. Assert.Equal ("Absolute(50)", v4.Width.ToString ());
  206. Assert.Equal ("Absolute(50)", v4.Height.ToString ());
  207. Assert.Equal (50, v4.Frame.Width);
  208. Assert.Equal (50, v4.Frame.Height);
  209. #if DEBUG
  210. Assert.Equal ($"Combine(View(Width,Button(v1){v1.Frame})-View(Width,Button(v3){v3.Viewport}))", v5.Width.ToString ());
  211. #else
  212. Assert.Equal ($"Combine(View(Height,Button(){v1.Frame})-View(Height,Button(){v3.Viewport}))", v5.Height.ToString ( ));
  213. #endif
  214. Assert.Equal (38, v5.Frame.Width); // 47-9=38
  215. Assert.Equal (80, v5.Frame.Height); // 89-9=80
  216. Assert.Equal (9, v6.Frame.Width); // 47*20%=9
  217. Assert.Equal (18, v6.Frame.Height); // 89*20%=18
  218. w.Width = 200;
  219. Assert.True (t.NeedsLayout);
  220. w.Height = 200;
  221. t.LayoutSubviews ();
  222. Assert.Equal ("Absolute(200)", w.Width.ToString ());
  223. Assert.Equal ("Absolute(200)", w.Height.ToString ());
  224. Assert.Equal (200, w.Frame.Width);
  225. Assert.Equal (200, w.Frame.Height);
  226. f1.Text = "Frame1";
  227. Assert.Equal (99, f1.Frame.Width); // 100-1=99
  228. Assert.Equal (5, f1.Frame.Height);
  229. f2.Text = "Frame2";
  230. Assert.Equal ("Fill(Absolute(0))", f2.Width.ToString ());
  231. Assert.Equal ("Absolute(5)", f2.Height.ToString ());
  232. Assert.Equal (99, f2.Frame.Width); // 100-1=99
  233. Assert.Equal (5, f2.Frame.Height);
  234. v1.Text = "Button1";
  235. #if DEBUG
  236. Assert.Equal ($"Combine(View(Width,FrameView(f1){f1.Frame})-Absolute(2))", v1.Width.ToString ());
  237. #else
  238. Assert.Equal ($"Combine(View(Width,FrameView(){f1.Frame})-Absolute(2))", v1.Width.ToString ());
  239. #endif
  240. Assert.Equal ("Combine(Fill(Absolute(0))-Absolute(2))", v1.Height.ToString ());
  241. Assert.Equal (97, v1.Frame.Width); // 99-2=97
  242. Assert.Equal (189, v1.Frame.Height); // 198-2-7=189
  243. v2.Text = "Button2";
  244. #if DEBUG
  245. Assert.Equal ($"Combine(View(Width,FrameView(f2){f2.Frame})-Absolute(2))", v2.Width.ToString ());
  246. #else
  247. Assert.Equal ($"Combine(View(Width,FrameView(){f2.Frame})-Absolute(2))", v2.Width.ToString ());
  248. #endif
  249. Assert.Equal ("Combine(Fill(Absolute(0))-Absolute(2))", v2.Height.ToString ());
  250. Assert.Equal (97, v2.Frame.Width); // 99-2=97
  251. Assert.Equal (189, v2.Frame.Height); // 198-2-7=189
  252. v3.Text = "Button3";
  253. // 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width
  254. Assert.Equal (19, v3.Frame.Width);
  255. // 199*10%=19
  256. Assert.Equal (19, v3.Frame.Height);
  257. v4.Text = "Button4";
  258. v4.Width = Auto (DimAutoStyle.Text);
  259. v4.Height = Auto (DimAutoStyle.Text);
  260. v4.Layout ();
  261. Assert.Equal (Auto (DimAutoStyle.Text), v4.Width);
  262. Assert.Equal (Auto (DimAutoStyle.Text), v4.Height);
  263. Assert.Equal (11, v4.Frame.Width); // 11 is the text length and because is DimAbsolute
  264. Assert.Equal (1, v4.Frame.Height); // 1 because is DimAbsolute
  265. v5.Text = "Button5";
  266. #if DEBUG
  267. Assert.Equal ($"Combine(View(Width,Button(v1){v1.Frame})-View(Width,Button(v3){v3.Frame}))", v5.Width.ToString ());
  268. Assert.Equal ($"Combine(View(Height,Button(v1){v1.Frame})-View(Height,Button(v3){v3.Frame}))", v5.Height.ToString ());
  269. #else
  270. Assert.Equal ($"Combine(View(Width,Button(){v1.Frame})-View(Width,Button(){v3.Frame}))", v5.Width.ToString ());
  271. Assert.Equal ($"Combine(View(Height,Button(){v1.Frame})-View(Height,Button(){v3.Frame}))", v5.Height.ToString ());
  272. #endif
  273. Assert.Equal (78, v5.Frame.Width); // 97-9=78
  274. Assert.Equal (170, v5.Frame.Height); // 189-19=170
  275. v6.Text = "Button6";
  276. Assert.Equal (19, v6.Frame.Width); // 99*20%=19
  277. Assert.Equal (38, v6.Frame.Height); // 198-7*20=18
  278. };
  279. Application.Iteration += (s, a) => Application.RequestStop ();
  280. Application.Run (t);
  281. t.Dispose ();
  282. }
  283. // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
  284. // TODO: A new test that calls SetRelativeLayout directly is needed.
  285. [Fact]
  286. [TestRespondersDisposed]
  287. public void Referencing_SuperView_Does_Not_Throw ()
  288. {
  289. var super = new View { Width = 10, Height = 10, Text = "super" };
  290. var view = new View
  291. {
  292. Width = Width (super), // this is allowed
  293. Height = Height (super), // this is allowed
  294. Text = "view"
  295. };
  296. super.Add (view);
  297. super.BeginInit ();
  298. super.EndInit ();
  299. Exception exception = Record.Exception (super.LayoutSubviews);
  300. Assert.Null (exception);
  301. super.Dispose ();
  302. }
  303. [Fact]
  304. public void DimSized_Equals ()
  305. {
  306. var n1 = 0;
  307. var n2 = 0;
  308. Dim dim1 = Absolute (n1);
  309. Dim dim2 = Absolute (n2);
  310. Assert.Equal (dim1, dim2);
  311. n1 = n2 = 1;
  312. dim1 = Absolute (n1);
  313. dim2 = Absolute (n2);
  314. Assert.Equal (dim1, dim2);
  315. n1 = n2 = -1;
  316. dim1 = Absolute (n1);
  317. dim2 = Absolute (n2);
  318. Assert.Equal (dim1, dim2);
  319. n1 = 0;
  320. n2 = 1;
  321. dim1 = Absolute (n1);
  322. dim2 = Absolute (n2);
  323. Assert.NotEqual (dim1, dim2);
  324. }
  325. [Fact]
  326. public void DimSized_SetsValue ()
  327. {
  328. Dim dim = Absolute (0);
  329. Assert.Equal ("Absolute(0)", dim.ToString ());
  330. var testVal = 5;
  331. dim = Absolute (testVal);
  332. Assert.Equal ($"Absolute({testVal})", dim.ToString ());
  333. testVal = -1;
  334. dim = Absolute (testVal);
  335. Assert.Equal ($"Absolute({testVal})", dim.ToString ());
  336. }
  337. // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
  338. // TODO: A new test that calls SetRelativeLayout directly is needed.
  339. [Fact]
  340. [TestRespondersDisposed]
  341. public void Validation_Does_Not_Throw_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Null ()
  342. {
  343. var t = new View { Width = 80, Height = 25, Text = "top" };
  344. var w = new Window
  345. {
  346. X = 1,
  347. Y = 2,
  348. Width = 4,
  349. Height = 5,
  350. Title = "w"
  351. };
  352. t.Add (w);
  353. t.LayoutSubviews ();
  354. Assert.Equal (3, w.Width = 3);
  355. Assert.Equal (4, w.Height = 4);
  356. t.Dispose ();
  357. }
  358. [Fact]
  359. [TestRespondersDisposed]
  360. public void DimWidth_Equals ()
  361. {
  362. var testRect1 = Rectangle.Empty;
  363. var view1 = new View { Frame = testRect1 };
  364. var testRect2 = Rectangle.Empty;
  365. var view2 = new View { Frame = testRect2 };
  366. Dim dim1 = Width (view1);
  367. Dim dim2 = Width (view1);
  368. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  369. Assert.Equal (dim1, dim2);
  370. dim2 = Width (view2);
  371. Assert.NotEqual (dim1, dim2);
  372. testRect1 = new (0, 1, 2, 3);
  373. view1 = new () { Frame = testRect1 };
  374. testRect2 = new (0, 1, 2, 3);
  375. dim1 = Width (view1);
  376. dim2 = Width (view1);
  377. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  378. Assert.Equal (dim1, dim2);
  379. testRect1 = new (0, -1, 2, 3);
  380. view1 = new () { Frame = testRect1 };
  381. testRect2 = new (0, -1, 2, 3);
  382. dim1 = Width (view1);
  383. dim2 = Width (view1);
  384. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  385. Assert.Equal (dim1, dim2);
  386. testRect1 = new (0, -1, 2, 3);
  387. view1 = new () { Frame = testRect1 };
  388. testRect2 = Rectangle.Empty;
  389. view2 = new () { Frame = testRect2 };
  390. dim1 = Width (view1);
  391. dim2 = Width (view2);
  392. Assert.NotEqual (dim1, dim2);
  393. #if DEBUG_IDISPOSABLE
  394. // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above.
  395. Responder.Instances.Clear ();
  396. Assert.Empty (Responder.Instances);
  397. #endif
  398. }
  399. [Fact]
  400. public void DimWidth_Set_To_Null_Throws ()
  401. {
  402. Dim dim = Width (null);
  403. Assert.Throws<NullReferenceException> (() => dim.ToString ());
  404. }
  405. [Fact]
  406. [TestRespondersDisposed]
  407. public void DimWidth_SetsValue ()
  408. {
  409. var testVal = Rectangle.Empty;
  410. var testValView = new View { Frame = testVal };
  411. Dim dim = Width (testValView);
  412. Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
  413. testValView.Dispose ();
  414. testVal = new (1, 2, 3, 4);
  415. testValView = new () { Frame = testVal };
  416. dim = Width (testValView);
  417. Assert.Equal ($"View(Width,View(){testVal})", dim.ToString ());
  418. testValView.Dispose ();
  419. }
  420. }