ScrollSliderTests.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. using Xunit.Abstractions;
  2. namespace Terminal.Gui.ViewsTests;
  3. public class ScrollSliderTests
  4. {
  5. [Fact]
  6. public void Constructor_Initializes_Correctly ()
  7. {
  8. var scrollSlider = new ScrollSlider ();
  9. Assert.False (scrollSlider.CanFocus);
  10. Assert.Equal (Orientation.Vertical, scrollSlider.Orientation);
  11. Assert.Equal (TextDirection.TopBottom_LeftRight, scrollSlider.TextDirection);
  12. Assert.Equal (Alignment.Center, scrollSlider.TextAlignment);
  13. Assert.Equal (Alignment.Center, scrollSlider.VerticalTextAlignment);
  14. scrollSlider.Layout ();
  15. Assert.Equal (0, scrollSlider.Frame.X);
  16. Assert.Equal (0, scrollSlider.Frame.Y);
  17. Assert.Equal (1, scrollSlider.Size);
  18. Assert.Equal (2048, scrollSlider.VisibleContentSize);
  19. }
  20. [Fact]
  21. public void Add_To_SuperView_Initializes_Correctly ()
  22. {
  23. var super = new View
  24. {
  25. Id = "super",
  26. Width = 10,
  27. Height = 10,
  28. CanFocus = true
  29. };
  30. var scrollSlider = new ScrollSlider ();
  31. super.Add (scrollSlider);
  32. Assert.False (scrollSlider.CanFocus);
  33. Assert.Equal (Orientation.Vertical, scrollSlider.Orientation);
  34. Assert.Equal (TextDirection.TopBottom_LeftRight, scrollSlider.TextDirection);
  35. Assert.Equal (Alignment.Center, scrollSlider.TextAlignment);
  36. Assert.Equal (Alignment.Center, scrollSlider.VerticalTextAlignment);
  37. scrollSlider.Layout ();
  38. Assert.Equal (0, scrollSlider.Frame.X);
  39. Assert.Equal (0, scrollSlider.Frame.Y);
  40. Assert.Equal (1, scrollSlider.Size);
  41. Assert.Equal (10, scrollSlider.VisibleContentSize);
  42. }
  43. //[Fact]
  44. //public void OnOrientationChanged_Sets_Size_To_1 ()
  45. //{
  46. // var scrollSlider = new ScrollSlider ();
  47. // scrollSlider.Orientation = Orientation.Horizontal;
  48. // Assert.Equal (1, scrollSlider.Size);
  49. //}
  50. [Fact]
  51. public void OnOrientationChanged_Sets_Position_To_0 ()
  52. {
  53. var super = new View
  54. {
  55. Id = "super",
  56. Width = 10,
  57. Height = 10
  58. };
  59. var scrollSlider = new ScrollSlider ();
  60. super.Add (scrollSlider);
  61. scrollSlider.Layout ();
  62. scrollSlider.Position = 1;
  63. scrollSlider.Orientation = Orientation.Horizontal;
  64. Assert.Equal (0, scrollSlider.Position);
  65. }
  66. [Fact]
  67. public void OnOrientationChanged_Updates_TextDirection_And_TextAlignment ()
  68. {
  69. var scrollSlider = new ScrollSlider ();
  70. scrollSlider.Orientation = Orientation.Horizontal;
  71. Assert.Equal (TextDirection.LeftRight_TopBottom, scrollSlider.TextDirection);
  72. Assert.Equal (Alignment.Center, scrollSlider.TextAlignment);
  73. Assert.Equal (Alignment.Center, scrollSlider.VerticalTextAlignment);
  74. }
  75. [Theory]
  76. [CombinatorialData]
  77. public void Size_Clamps_To_SuperView_Viewport ([CombinatorialRange (-1, 6, 1)] int sliderSize, Orientation orientation)
  78. {
  79. var super = new View
  80. {
  81. Id = "super",
  82. Width = 5,
  83. Height = 5
  84. };
  85. var scrollSlider = new ScrollSlider
  86. {
  87. Orientation = orientation
  88. };
  89. super.Add (scrollSlider);
  90. scrollSlider.Layout ();
  91. scrollSlider.Size = sliderSize;
  92. scrollSlider.Layout ();
  93. Assert.True (scrollSlider.Size > 0);
  94. Assert.True (scrollSlider.Size <= 5);
  95. }
  96. [Theory]
  97. [CombinatorialData]
  98. public void Size_Clamps_To_VisibleContentSizes (
  99. [CombinatorialRange (1, 6, 1)] int dimension,
  100. [CombinatorialRange (-1, 6, 1)] int sliderSize,
  101. Orientation orientation
  102. )
  103. {
  104. var scrollSlider = new ScrollSlider
  105. {
  106. Orientation = orientation,
  107. VisibleContentSize = dimension,
  108. Size = sliderSize
  109. };
  110. scrollSlider.Layout ();
  111. Assert.True (scrollSlider.Size > 0);
  112. Assert.True (scrollSlider.Size <= dimension);
  113. }
  114. [Theory]
  115. [CombinatorialData]
  116. public void CalculateSize_ScrollBounds_0_Returns_1 (
  117. [CombinatorialRange (-1, 5, 1)] int visibleContentSize,
  118. [CombinatorialRange (-1, 5, 1)] int scrollableContentSize
  119. )
  120. {
  121. // Arrange
  122. // Act
  123. int sliderSize = ScrollSlider.CalculateSize (scrollableContentSize, visibleContentSize, 0);
  124. // Assert
  125. Assert.Equal (1, sliderSize);
  126. }
  127. [Theory]
  128. [CombinatorialData]
  129. public void CalculateSize_ScrollableContentSize_0_Returns_1 (
  130. [CombinatorialRange (-1, 5, 1)] int visibleContentSize,
  131. [CombinatorialRange (-1, 5, 1)] int sliderBounds
  132. )
  133. {
  134. // Arrange
  135. // Act
  136. int sliderSize = ScrollSlider.CalculateSize (0, visibleContentSize, sliderBounds);
  137. // Assert
  138. Assert.Equal (1, sliderSize);
  139. }
  140. //[Theory]
  141. //[CombinatorialData]
  142. //public void CalculateSize_VisibleContentSize_0_Returns_0 ([CombinatorialRange (-1, 5, 1)] int scrollableContentSize, [CombinatorialRange (-1, 5, 1)] int sliderBounds)
  143. //{
  144. // // Arrange
  145. // // Act
  146. // var sliderSize = ScrollSlider.CalculateSize (scrollableContentSize, 0, sliderBounds);
  147. // // Assert
  148. // Assert.Equal (0, sliderSize);
  149. //}
  150. [Theory]
  151. [InlineData (0, 1, 1, 1)]
  152. [InlineData (1, 1, 1, 1)]
  153. [InlineData (1, 2, 1, 1)]
  154. [InlineData (0, 5, 5, 5)]
  155. [InlineData (1, 5, 5, 1)]
  156. [InlineData (2, 5, 5, 2)]
  157. [InlineData (3, 5, 5, 3)]
  158. [InlineData (4, 5, 5, 4)]
  159. [InlineData (5, 5, 5, 5)]
  160. [InlineData (6, 5, 5, 5)]
  161. public void CalculateSize_Calculates_Correctly (int visibleContentSize, int scrollableContentSize, int scrollBounds, int expectedSliderSize)
  162. {
  163. // Arrange
  164. // Act
  165. int sliderSize = ScrollSlider.CalculateSize (scrollableContentSize, visibleContentSize, scrollBounds);
  166. // Assert
  167. Assert.Equal (expectedSliderSize, sliderSize);
  168. }
  169. [Fact]
  170. public void VisibleContentSize_Not_Set_Uses_SuperView ()
  171. {
  172. View super = new ()
  173. {
  174. Id = "super",
  175. Height = 5,
  176. Width = 5
  177. };
  178. var scrollSlider = new ScrollSlider ();
  179. super.Add (scrollSlider);
  180. super.Layout ();
  181. Assert.Equal (5, scrollSlider.VisibleContentSize);
  182. }
  183. [Fact]
  184. public void VisibleContentSize_Set_Overrides_SuperView ()
  185. {
  186. View super = new ()
  187. {
  188. Id = "super",
  189. Height = 5,
  190. Width = 5
  191. };
  192. var scrollSlider = new ScrollSlider
  193. {
  194. VisibleContentSize = 10
  195. };
  196. super.Add (scrollSlider);
  197. super.Layout ();
  198. Assert.Equal (10, scrollSlider.VisibleContentSize);
  199. super.Height = 3;
  200. super.Layout ();
  201. Assert.Equal (10, scrollSlider.VisibleContentSize);
  202. super.Height = 7;
  203. super.Layout ();
  204. Assert.Equal (10, scrollSlider.VisibleContentSize);
  205. }
  206. [Theory]
  207. [CombinatorialData]
  208. public void VisibleContentSizes_Clamps_0_To_Dimension ([CombinatorialRange (0, 10, 1)] int dimension, Orientation orientation)
  209. {
  210. var scrollSlider = new ScrollSlider
  211. {
  212. Orientation = orientation,
  213. VisibleContentSize = dimension
  214. };
  215. Assert.InRange (scrollSlider.VisibleContentSize, 1, 10);
  216. View super = new ()
  217. {
  218. Id = "super",
  219. Height = dimension,
  220. Width = dimension
  221. };
  222. scrollSlider = new()
  223. {
  224. Orientation = orientation
  225. };
  226. super.Add (scrollSlider);
  227. super.Layout ();
  228. Assert.InRange (scrollSlider.VisibleContentSize, 1, 10);
  229. scrollSlider.VisibleContentSize = dimension;
  230. Assert.InRange (scrollSlider.VisibleContentSize, 1, 10);
  231. }
  232. [Theory]
  233. //// 0123456789
  234. //// ---------
  235. //// ◄█►
  236. //[InlineData (3, 3, 0, 1, 0)]
  237. //[InlineData (3, 3, 1, 1, 0)]
  238. //[InlineData (3, 3, 2, 1, 0)]
  239. //// 0123456789
  240. //// ---------
  241. //// ◄██►
  242. //[InlineData (4, 4, 0, 2, 0)]
  243. //[InlineData (4, 4, 1, 2, 0)]
  244. //[InlineData (4, 4, 2, 2, 0)]
  245. //[InlineData (4, 4, 3, 2, 0)]
  246. //[InlineData (4, 4, 4, 2, 0)]
  247. // 012345
  248. // ^----
  249. // █░
  250. [InlineData (2, 5, 0, 0)]
  251. // -^---
  252. // █░
  253. [InlineData (2, 5, 1, 0)]
  254. // --^--
  255. // ░█
  256. [InlineData (2, 5, 2, 1)]
  257. // ---^-
  258. // ░█
  259. [InlineData (2, 5, 3, 1)]
  260. // ----^
  261. // ░█
  262. [InlineData (2, 5, 4, 1)]
  263. // 012345
  264. // ^----
  265. // █░░
  266. [InlineData (3, 5, 0, 0)]
  267. // -^---
  268. // ░█░
  269. [InlineData (3, 5, 1, 1)]
  270. // --^--
  271. // ░░█
  272. [InlineData (3, 5, 2, 2)]
  273. // ---^-
  274. // ░░█
  275. [InlineData (3, 5, 3, 2)]
  276. // ----^
  277. // ░░█
  278. [InlineData (3, 5, 4, 2)]
  279. // 0123456789
  280. // ^-----
  281. // █░░
  282. [InlineData (3, 6, 0, 0)]
  283. // -^----
  284. // █░░
  285. [InlineData (3, 6, 1, 1)]
  286. // --^---
  287. // ░█░
  288. [InlineData (3, 6, 2, 1)]
  289. // ---^--
  290. // ░░█
  291. [InlineData (3, 6, 3, 2)]
  292. // ----^-
  293. // ░░█
  294. [InlineData (3, 6, 4, 2)]
  295. // -----^
  296. // ░░█
  297. [InlineData (3, 6, 5, 2)]
  298. // 012345
  299. // ^----
  300. // ███░
  301. [InlineData (4, 5, 0, 0)]
  302. // -^---
  303. // ░███
  304. [InlineData (4, 5, 1, 1)]
  305. // --^--
  306. // ░███
  307. [InlineData (4, 5, 2, 1)]
  308. // ---^-
  309. // ░███
  310. [InlineData (4, 5, 3, 1)]
  311. // ----^
  312. // ░███
  313. [InlineData (4, 5, 4, 1)]
  314. //// 01234
  315. //// ^---------
  316. //// ◄█░░►
  317. //[InlineData (5, 10, 0, 1, 0)]
  318. //// -^--------
  319. //// ◄█░░►
  320. //[InlineData (5, 10, 1, 1, 0)]
  321. //// --^-------
  322. //// ◄█░░►
  323. //[InlineData (5, 10, 2, 1, 0)]
  324. //// ---^------
  325. //// ◄█░░►
  326. //[InlineData (5, 10, 3, 1, 0)]
  327. //// ----^----
  328. //// ◄░█░►
  329. //[InlineData (5, 10, 4, 1, 1)]
  330. //// -----^---
  331. //// ◄░█░►
  332. //[InlineData (5, 10, 5, 1, 1)]
  333. //// ------^--
  334. //// ◄░░█►
  335. //[InlineData (5, 10, 6, 1, 2)]
  336. //// ------^--
  337. //// ◄░░█►
  338. //[InlineData (5, 10, 7, 1, 2)]
  339. //// -------^-
  340. //// ◄░░█►
  341. //[InlineData (5, 10, 8, 1, 2)]
  342. //// --------^
  343. //// ◄░░█►
  344. //[InlineData (5, 10, 9, 1, 2)]
  345. // 0123456789
  346. // ████░░░░
  347. // ^-----------------
  348. // 012345678901234567890123456789
  349. // ░████░░░
  350. // ----^-------------
  351. // 012345678901234567890123456789
  352. // ░░████░░
  353. // --------^---------
  354. // 012345678901234567890123456789
  355. // ░░░████░
  356. // ------------^-----
  357. // 012345678901234567890123456789
  358. // ░░░░████
  359. // ----------------^--
  360. // 0123456789
  361. // ███░░░░░
  362. // ^-----------------
  363. // 012345678901234567890123456789
  364. // ░░███░░░
  365. // --------^---------
  366. // 012345678901234567890123456789
  367. // ░░░███░░
  368. // ------------^-----
  369. // 012345678901234567890123456789
  370. // ░░░░███░
  371. // ----------------^--
  372. // 012345678901234567890123456789
  373. // ░░░░░███
  374. // ----------------^--
  375. [InlineData (8, 18, 0, 0)]
  376. [InlineData (8, 18, 1, 0)]
  377. // 012345678901234567890123456789
  378. // ░███░░░░
  379. // --^---------------
  380. [InlineData (8, 18, 2, 1)]
  381. [InlineData (8, 18, 3, 2)]
  382. [InlineData (8, 18, 4, 2)]
  383. [InlineData (8, 18, 5, 2)]
  384. [InlineData (8, 18, 6, 3)]
  385. [InlineData (8, 18, 7, 4)]
  386. [InlineData (8, 18, 8, 4)]
  387. [InlineData (8, 18, 9, 4)]
  388. // 012345678901234567890123456789
  389. // ░░░░░███
  390. // ----------^--------
  391. [InlineData (8, 18, 10, 5)]
  392. [InlineData (8, 18, 11, 5)]
  393. [InlineData (8, 18, 12, 5)]
  394. [InlineData (8, 18, 13, 5)]
  395. [InlineData (8, 18, 14, 5)]
  396. [InlineData (8, 18, 15, 5)]
  397. [InlineData (8, 18, 16, 5)]
  398. [InlineData (8, 18, 17, 5)]
  399. [InlineData (8, 18, 18, 5)]
  400. [InlineData (8, 18, 19, 5)]
  401. [InlineData (8, 18, 20, 5)]
  402. [InlineData (8, 18, 21, 5)]
  403. [InlineData (8, 18, 22, 5)]
  404. [InlineData (8, 18, 23, 5)]
  405. // ------------------ ^
  406. [InlineData (8, 18, 24, 5)]
  407. [InlineData (8, 18, 25, 5)]
  408. //// 0123456789
  409. //// ◄████░░░░►
  410. //// ^-----------------
  411. //[InlineData (10, 20, 0, 5, 0)]
  412. //[InlineData (10, 20, 1, 5, 0)]
  413. //[InlineData (10, 20, 2, 5, 0)]
  414. //[InlineData (10, 20, 3, 5, 0)]
  415. //[InlineData (10, 20, 4, 5, 1)]
  416. //[InlineData (10, 20, 5, 5, 1)]
  417. //[InlineData (10, 20, 6, 5, 1)]
  418. //[InlineData (10, 20, 7, 5, 2)]
  419. //[InlineData (10, 20, 8, 5, 2)]
  420. //[InlineData (10, 20, 9, 5, 2)]
  421. //[InlineData (10, 20, 10, 5, 3)]
  422. //[InlineData (10, 20, 11, 5, 3)]
  423. //[InlineData (10, 20, 12, 5, 3)]
  424. //[InlineData (10, 20, 13, 5, 3)]
  425. //[InlineData (10, 20, 14, 5, 4)]
  426. //[InlineData (10, 20, 15, 5, 4)]
  427. //[InlineData (10, 20, 16, 5, 4)]
  428. //[InlineData (10, 20, 17, 5, 5)]
  429. //[InlineData (10, 20, 18, 5, 5)]
  430. //[InlineData (10, 20, 19, 5, 5)]
  431. //[InlineData (10, 20, 20, 5, 6)]
  432. //[InlineData (10, 20, 21, 5, 6)]
  433. //[InlineData (10, 20, 22, 5, 6)]
  434. //[InlineData (10, 20, 23, 5, 6)]
  435. //[InlineData (10, 20, 24, 5, 6)]
  436. //[InlineData (10, 20, 25, 5, 6)]
  437. public void CalculatePosition_Calculates_Correctly (int visibleContentSize, int scrollableContentSize, int contentPosition, int expectedSliderPosition)
  438. {
  439. // Arrange
  440. // Act
  441. int sliderPosition = ScrollSlider.CalculatePosition (
  442. scrollableContentSize,
  443. visibleContentSize,
  444. contentPosition,
  445. visibleContentSize,
  446. NavigationDirection.Forward);
  447. // Assert
  448. Assert.Equal (expectedSliderPosition, sliderPosition);
  449. }
  450. [Theory]
  451. [InlineData (8, 18, 0, 0)]
  452. public void CalculateContentPosition_Calculates_Correctly (
  453. int visibleContentSize,
  454. int scrollableContentSize,
  455. int sliderPosition,
  456. int expectedContentPosition
  457. )
  458. {
  459. // Arrange
  460. // Act
  461. int contentPosition = ScrollSlider.CalculateContentPosition (
  462. scrollableContentSize,
  463. visibleContentSize,
  464. sliderPosition,
  465. visibleContentSize);
  466. // Assert
  467. Assert.Equal (expectedContentPosition, contentPosition);
  468. }
  469. [Theory]
  470. [CombinatorialData]
  471. public void ClampPosition_WithSuperView_Clamps_To_ViewPort_Minus_Size_If_VisibleContentSize_Not_Set (
  472. [CombinatorialRange (10, 10, 1)] int dimension,
  473. [CombinatorialRange (1, 5, 1)] int sliderSize,
  474. [CombinatorialRange (-1, 10, 2)] int sliderPosition,
  475. Orientation orientation
  476. )
  477. {
  478. View super = new ()
  479. {
  480. Id = "super",
  481. Height = dimension,
  482. Width = dimension
  483. };
  484. var scrollSlider = new ScrollSlider
  485. {
  486. Orientation = orientation,
  487. Size = sliderSize
  488. };
  489. super.Add (scrollSlider);
  490. super.Layout ();
  491. Assert.Equal (dimension, scrollSlider.VisibleContentSize);
  492. int clampedPosition = scrollSlider.ClampPosition (sliderPosition);
  493. Assert.InRange (clampedPosition, 0, dimension - sliderSize);
  494. }
  495. [Theory]
  496. [CombinatorialData]
  497. public void ClampPosition_WithSuperView_Clamps_To_VisibleContentSize_Minus_Size (
  498. [CombinatorialRange (10, 10, 1)] int dimension,
  499. [CombinatorialRange (1, 5, 1)] int sliderSize,
  500. [CombinatorialRange (-1, 10, 2)] int sliderPosition,
  501. Orientation orientation
  502. )
  503. {
  504. View super = new ()
  505. {
  506. Id = "super",
  507. Height = dimension + 2,
  508. Width = dimension + 2
  509. };
  510. var scrollSlider = new ScrollSlider
  511. {
  512. Orientation = orientation,
  513. VisibleContentSize = dimension,
  514. Size = sliderSize
  515. };
  516. super.Add (scrollSlider);
  517. super.Layout ();
  518. int clampedPosition = scrollSlider.ClampPosition (sliderPosition);
  519. Assert.InRange (clampedPosition, 0, dimension - sliderSize);
  520. }
  521. [Theory]
  522. [CombinatorialData]
  523. public void ClampPosition_NoSuperView_Clamps_To_VisibleContentSize_Minus_Size (
  524. [CombinatorialRange (10, 10, 1)] int dimension,
  525. [CombinatorialRange (1, 5, 1)] int sliderSize,
  526. [CombinatorialRange (-1, 10, 2)] int sliderPosition,
  527. Orientation orientation
  528. )
  529. {
  530. var scrollSlider = new ScrollSlider
  531. {
  532. Orientation = orientation,
  533. VisibleContentSize = dimension,
  534. Size = sliderSize
  535. };
  536. int clampedPosition = scrollSlider.ClampPosition (sliderPosition);
  537. Assert.InRange (clampedPosition, 0, dimension - sliderSize);
  538. }
  539. [Theory]
  540. [CombinatorialData]
  541. public void Position_Clamps_To_VisibleContentSize (
  542. [CombinatorialRange (0, 5, 1)] int dimension,
  543. [CombinatorialRange (1, 5, 1)] int sliderSize,
  544. [CombinatorialRange (-1, 10, 2)] int sliderPosition,
  545. Orientation orientation
  546. )
  547. {
  548. var scrollSlider = new ScrollSlider
  549. {
  550. Orientation = orientation,
  551. VisibleContentSize = dimension,
  552. Size = sliderSize,
  553. Position = sliderPosition
  554. };
  555. Assert.True (scrollSlider.Position <= 5);
  556. }
  557. [Theory]
  558. [CombinatorialData]
  559. public void Position_Clamps_To_SuperView_Viewport (
  560. [CombinatorialRange (0, 5, 1)] int sliderSize,
  561. [CombinatorialRange (-2, 10, 2)] int sliderPosition,
  562. Orientation orientation
  563. )
  564. {
  565. var super = new View
  566. {
  567. Id = "super",
  568. Width = 5,
  569. Height = 5
  570. };
  571. var scrollSlider = new ScrollSlider
  572. {
  573. Orientation = orientation
  574. };
  575. super.Add (scrollSlider);
  576. scrollSlider.Size = sliderSize;
  577. scrollSlider.Layout ();
  578. scrollSlider.Position = sliderPosition;
  579. Assert.True (scrollSlider.Position <= 5);
  580. }
  581. }