DimAutoTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. using System;
  2. using System.Globalization;
  3. using System.Threading;
  4. using Xunit;
  5. using Xunit.Abstractions;
  6. // Alias Console to MockConsole so we don't accidentally use Console
  7. using Console = Terminal.Gui.FakeConsole;
  8. namespace Terminal.Gui.ViewTests;
  9. public class DimAutoTests {
  10. readonly ITestOutputHelper _output;
  11. public DimAutoTests (ITestOutputHelper output)
  12. {
  13. _output = output;
  14. Console.OutputEncoding = System.Text.Encoding.Default;
  15. // Change current culture
  16. var culture = CultureInfo.CreateSpecificCulture ("en-US");
  17. Thread.CurrentThread.CurrentCulture = culture;
  18. Thread.CurrentThread.CurrentUICulture = culture;
  19. }
  20. [Fact]
  21. public void NoSubViews_Does_Nothing ()
  22. {
  23. var superView = new View () {
  24. X = 0,
  25. Y = 0,
  26. Width = Dim.Auto (),
  27. Height = Dim.Auto (),
  28. ValidatePosDim = true,
  29. };
  30. superView.BeginInit ();
  31. superView.EndInit ();
  32. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  33. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  34. superView.SetRelativeLayout (new Rect (0, 0, 10, 10));
  35. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  36. superView.SetRelativeLayout (new Rect (10, 10, 10, 10));
  37. Assert.Equal (new Rect (0, 0, 0, 0), superView.Frame);
  38. }
  39. [Theory]
  40. [InlineData (0, 0, 0, 0, 0, 0)]
  41. [InlineData (0, 0, 5, 0, 5, 0)]
  42. [InlineData (0, 0, 0, 5, 0, 5)]
  43. [InlineData (0, 0, 5, 5, 5, 5)]
  44. [InlineData (1, 0, 5, 0, 6, 0)]
  45. [InlineData (1, 0, 0, 5, 1, 5)]
  46. [InlineData (1, 0, 5, 5, 6, 5)]
  47. [InlineData (1, 1, 5, 5, 6, 6)]
  48. [InlineData (-1, 0, 5, 0, 4, 0)]
  49. [InlineData (-1, 0, 0, 5, 0, 5)]
  50. [InlineData (-1, 0, 5, 5, 4, 5)]
  51. [InlineData (-1, -1, 5, 5, 4, 4)]
  52. public void SubView_ChangesSuperViewSize (int subX, int subY, int subWidth, int subHeight, int expectedWidth, int expectedHeight)
  53. {
  54. var superView = new View () {
  55. X = 0,
  56. Y = 0,
  57. Width = Dim.Auto (),
  58. Height = Dim.Auto (),
  59. ValidatePosDim = true,
  60. };
  61. var subView = new View () {
  62. X = subX,
  63. Y = subY,
  64. Width = subWidth,
  65. Height = subHeight,
  66. ValidatePosDim = true,
  67. };
  68. superView.Add (subView);
  69. superView.BeginInit ();
  70. superView.EndInit ();
  71. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  72. Assert.Equal (new Rect (0, 0, expectedWidth, expectedHeight), superView.Frame);
  73. }
  74. [Theory]
  75. [InlineData (0, 0, 0, 0, 0)]
  76. [InlineData (0, 0, 5, 0, 5)]
  77. [InlineData (0, 0, 0, 5, 0)]
  78. [InlineData (0, 0, 5, 5, 5)]
  79. [InlineData (1, 0, 5, 0, 6)]
  80. [InlineData (1, 0, 0, 5, 1)]
  81. [InlineData (1, 0, 5, 5, 6)]
  82. [InlineData (1, 1, 5, 5, 6)]
  83. [InlineData (-1, 0, 5, 0, 4)]
  84. [InlineData (-1, 0, 0, 5, 0)]
  85. [InlineData (-1, 0, 5, 5, 4)]
  86. [InlineData (-1, -1, 5, 5, 4)]
  87. public void Width_Auto_Height_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedWidth)
  88. {
  89. var superView = new View () {
  90. X = 0,
  91. Y = 0,
  92. Width = Dim.Auto (),
  93. Height = 10,
  94. ValidatePosDim = true,
  95. };
  96. var subView = new View () {
  97. X = subX,
  98. Y = subY,
  99. Width = subWidth,
  100. Height = subHeight,
  101. ValidatePosDim = true,
  102. };
  103. superView.Add (subView);
  104. superView.BeginInit ();
  105. superView.EndInit ();
  106. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  107. Assert.Equal (new Rect (0, 0, expectedWidth, 10), superView.Frame);
  108. }
  109. [Theory]
  110. [InlineData (0, 0, 0, 0, 0)]
  111. [InlineData (0, 0, 5, 0, 0)]
  112. [InlineData (0, 0, 0, 5, 5)]
  113. [InlineData (0, 0, 5, 5, 5)]
  114. [InlineData (1, 0, 5, 0, 0)]
  115. [InlineData (1, 0, 0, 5, 5)]
  116. [InlineData (1, 0, 5, 5, 5)]
  117. [InlineData (1, 1, 5, 5, 6)]
  118. [InlineData (-1, 0, 5, 0, 0)]
  119. [InlineData (-1, 0, 0, 5, 5)]
  120. [InlineData (-1, 0, 5, 5, 5)]
  121. [InlineData (-1, -1, 5, 5, 4)]
  122. public void Height_Auto_Width_NotChanged (int subX, int subY, int subWidth, int subHeight, int expectedHeight)
  123. {
  124. var superView = new View () {
  125. X = 0,
  126. Y = 0,
  127. Width = 10,
  128. Height = Dim.Auto (),
  129. ValidatePosDim = true,
  130. };
  131. var subView = new View () {
  132. X = subX,
  133. Y = subY,
  134. Width = subWidth,
  135. Height = subHeight,
  136. ValidatePosDim = true,
  137. };
  138. superView.Add (subView);
  139. superView.BeginInit ();
  140. superView.EndInit ();
  141. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  142. Assert.Equal (new Rect (0, 0, 10, expectedHeight), superView.Frame);
  143. }
  144. // Test validation
  145. [Fact]
  146. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims ()
  147. {
  148. var superView = new View () {
  149. X = 0,
  150. Y = 0,
  151. Width = Dim.Auto (),
  152. Height = Dim.Auto (),
  153. ValidatePosDim = true,
  154. };
  155. var subView = new View () {
  156. X = 0,
  157. Y = 0,
  158. Width = Dim.Fill (),
  159. Height = 10
  160. };
  161. superView.BeginInit ();
  162. superView.EndInit ();
  163. Assert.Throws<InvalidOperationException> (() => superView.Add (subView));
  164. subView.Width = 10;
  165. superView.Add (subView);
  166. superView.BeginInit ();
  167. superView.EndInit ();
  168. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  169. superView.LayoutSubviews (); // no throw
  170. Assert.Throws<InvalidOperationException> (() => subView.Width = Dim.Fill ());
  171. subView.Width = 10;
  172. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Fill ());
  173. subView.Height = 10;
  174. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Percent (50));
  175. subView.Height = 10;
  176. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Center ());
  177. subView.X = 0;
  178. Assert.Throws<InvalidOperationException> (() => subView.Y = Pos.Center ());
  179. subView.Y = 0;
  180. subView.Width = 10;
  181. subView.Height = 10;
  182. subView.X = 0;
  183. subView.Y = 0;
  184. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  185. superView.LayoutSubviews ();
  186. }
  187. // Test validation
  188. [Fact]
  189. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Dims_Combine ()
  190. {
  191. var superView = new View () {
  192. X = 0,
  193. Y = 0,
  194. Width = Dim.Auto (),
  195. Height = Dim.Auto (),
  196. ValidatePosDim = true,
  197. };
  198. var subView = new View () {
  199. X = 0,
  200. Y = 0,
  201. Width = 10,
  202. Height = 10
  203. };
  204. var subView2 = new View () {
  205. X = 0,
  206. Y = 0,
  207. Width = 10,
  208. Height = 10
  209. };
  210. superView.Add (subView, subView2);
  211. superView.BeginInit ();
  212. superView.EndInit ();
  213. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  214. superView.LayoutSubviews (); // no throw
  215. Assert.Throws<InvalidOperationException> (() => subView.Height = Dim.Fill () + 3);
  216. subView.Height = 0;
  217. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + Dim.Fill ());
  218. subView.Height = 0;
  219. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + 5 + Dim.Fill ());
  220. subView.Height = 0;
  221. Assert.Throws<InvalidOperationException> (() => subView.Height = 3 + 5 + Dim.Percent (10));
  222. subView.Height = 0;
  223. // Tests nested Combine
  224. Assert.Throws<InvalidOperationException> (() => subView.Height = 5 + new Dim.DimCombine (true, 3, new Dim.DimCombine (true, Dim.Percent (10), 9)));
  225. }
  226. [Fact]
  227. public void ValidatePosDim_True_Throws_When_SubView_Uses_SuperView_Pos_Combine ()
  228. {
  229. var superView = new View () {
  230. X = 0,
  231. Y = 0,
  232. Width = Dim.Auto (),
  233. Height = Dim.Auto (),
  234. ValidatePosDim = true,
  235. };
  236. var subView = new View () {
  237. X = 0,
  238. Y = 0,
  239. Width = 10,
  240. Height = 10
  241. };
  242. var subView2 = new View () {
  243. X = 0,
  244. Y = 0,
  245. Width = 10,
  246. Height = 10
  247. };
  248. superView.Add (subView, subView2);
  249. superView.BeginInit ();
  250. superView.EndInit ();
  251. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  252. superView.LayoutSubviews (); // no throw
  253. subView.X = Pos.Right (subView2);
  254. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  255. superView.LayoutSubviews (); // no throw
  256. subView.X = Pos.Right (subView2) + 3;
  257. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  258. superView.LayoutSubviews (); // no throw
  259. subView.X = new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, 7, 9));
  260. superView.SetRelativeLayout (new Rect (0, 0, 0, 0)); // no throw
  261. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Center () + 3);
  262. subView.X = 0;
  263. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + Pos.Center ());
  264. subView.X = 0;
  265. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + 5 + Pos.Center ());
  266. subView.X = 0;
  267. Assert.Throws<InvalidOperationException> (() => subView.X = 3 + 5 + Pos.Percent (10));
  268. subView.X = 0;
  269. Assert.Throws<InvalidOperationException> (() => subView.X = Pos.Percent (10) + Pos.Center ());
  270. subView.X = 0;
  271. // Tests nested Combine
  272. Assert.Throws<InvalidOperationException> (() => subView.X = 5 + new Pos.PosCombine (true, Pos.Right (subView2), new Pos.PosCombine (true, Pos.Center (), 9)));
  273. subView.X = 0;
  274. }
  275. // Test min - ensure that if min is specified in the DimAuto constructor it is honored
  276. [Fact]
  277. public void DimAuto_Min ()
  278. {
  279. var superView = new View () {
  280. X = 0,
  281. Y = 0,
  282. Width = Dim.Auto (min: 10),
  283. Height = Dim.Auto (min: 10),
  284. ValidatePosDim = true,
  285. };
  286. var subView = new View () {
  287. X = 0,
  288. Y = 0,
  289. Width = 5,
  290. Height = 5
  291. };
  292. superView.Add (subView);
  293. superView.BeginInit ();
  294. superView.EndInit ();
  295. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  296. superView.LayoutSubviews (); // no throw
  297. Assert.Equal (10, superView.Frame.Width);
  298. Assert.Equal (10, superView.Frame.Height);
  299. }
  300. [Fact]
  301. public void DimAuto_Min_Resets_If_Subview_Shrinks ()
  302. {
  303. var superView = new View () {
  304. X = 0,
  305. Y = 0,
  306. Width = Dim.Auto (min: 10),
  307. Height = Dim.Auto (min: 10),
  308. ValidatePosDim = true,
  309. };
  310. var subView = new View () {
  311. X = 0,
  312. Y = 0,
  313. Width = 5,
  314. Height = 5
  315. };
  316. superView.Add (subView);
  317. superView.BeginInit ();
  318. superView.EndInit ();
  319. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  320. superView.LayoutSubviews (); // no throw
  321. Assert.Equal (10, superView.Frame.Width);
  322. Assert.Equal (10, superView.Frame.Height);
  323. subView.Width = 3;
  324. subView.Height = 3;
  325. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  326. superView.LayoutSubviews (); // no throw
  327. Assert.Equal (3, subView.Frame.Width);
  328. Assert.Equal (3, subView.Frame.Height);
  329. Assert.Equal (10, superView.Frame.Width);
  330. Assert.Equal (10, superView.Frame.Height);
  331. }
  332. // what happens if DimAuto (min: 10) and the subview moves to a negative coord?
  333. [Fact]
  334. public void DimAuto_Min_Resets_If_Subview_Moves_Negative ()
  335. {
  336. var superView = new View () {
  337. X = 0,
  338. Y = 0,
  339. Width = Dim.Auto (min: 10),
  340. Height = Dim.Auto (min: 10),
  341. ValidatePosDim = true,
  342. };
  343. var subView = new View () {
  344. X = 0,
  345. Y = 0,
  346. Width = 5,
  347. Height = 5
  348. };
  349. superView.Add (subView);
  350. superView.BeginInit ();
  351. superView.EndInit ();
  352. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  353. superView.LayoutSubviews (); // no throw
  354. Assert.Equal (10, superView.Frame.Width);
  355. Assert.Equal (10, superView.Frame.Height);
  356. subView.X = -1;
  357. subView.Y = -1;
  358. superView.SetRelativeLayout (new Rect (0, 0, 0, 0));
  359. superView.LayoutSubviews (); // no throw
  360. Assert.Equal (5, subView.Frame.Width);
  361. Assert.Equal (5, subView.Frame.Height);
  362. Assert.Equal (10, superView.Frame.Width);
  363. Assert.Equal (10, superView.Frame.Height);
  364. }
  365. // Test variations of Frame
  366. }