LCOV - code coverage report
Current view: top level - tests/unit - test_tui_list_view.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 128 128
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 15 15

            Line data    Source code
       1              : /**
       2              :  * @file tests/unit/test_tui_list_view.c
       3              :  * @brief Unit tests for the scroll/selection helper (US-11 v2).
       4              :  */
       5              : 
       6              : #include "test_helpers.h"
       7              : #include "tui/list_view.h"
       8              : 
       9            1 : static void test_init_is_empty(void) {
      10              :     ListView lv;
      11            1 :     list_view_init(&lv);
      12            1 :     ASSERT(lv.count == 0, "count 0");
      13            1 :     ASSERT(lv.selected == -1, "selected -1");
      14            1 :     ASSERT(lv.scroll_top == 0, "scroll_top 0");
      15            1 :     ASSERT(lv.rows_visible == 0, "rows_visible 0");
      16              : }
      17              : 
      18            1 : static void test_set_count_selects_first_when_unset(void) {
      19            1 :     ListView lv; list_view_init(&lv);
      20            1 :     list_view_set_viewport(&lv, 5);
      21            1 :     list_view_set_count(&lv, 10);
      22            1 :     ASSERT(lv.selected == 0, "first item selected");
      23            1 :     ASSERT(lv.scroll_top == 0, "at top");
      24              : }
      25              : 
      26            1 : static void test_set_count_clamps_selected(void) {
      27            1 :     ListView lv; list_view_init(&lv);
      28            1 :     list_view_set_viewport(&lv, 5);
      29            1 :     list_view_set_count(&lv, 10);
      30            1 :     lv.selected = 7;
      31            1 :     lv.scroll_top = 5;
      32            1 :     list_view_set_count(&lv, 4);
      33            1 :     ASSERT(lv.selected == 3, "selection clamped to last valid");
      34            1 :     ASSERT(lv.scroll_top <= 3, "scroll clamped");
      35              : }
      36              : 
      37            1 : static void test_set_count_zero_resets_selection(void) {
      38            1 :     ListView lv; list_view_init(&lv);
      39            1 :     list_view_set_viewport(&lv, 5);
      40            1 :     list_view_set_count(&lv, 10);
      41            1 :     list_view_set_count(&lv, 0);
      42            1 :     ASSERT(lv.selected == -1, "empty list has no selection");
      43            1 :     ASSERT(lv.scroll_top == 0, "scroll reset");
      44              : }
      45              : 
      46            1 : static void test_move_down_advances_and_scrolls(void) {
      47            1 :     ListView lv; list_view_init(&lv);
      48            1 :     list_view_set_viewport(&lv, 3);
      49            1 :     list_view_set_count(&lv, 10);
      50            4 :     for (int i = 0; i < 3; i++) list_view_move_down(&lv);
      51            1 :     ASSERT(lv.selected == 3, "selected = 3");
      52            1 :     ASSERT(lv.scroll_top == 1, "scroll followed selection");
      53            1 :     ASSERT(list_view_is_visible(&lv, 3), "selection visible");
      54              : }
      55              : 
      56            1 : static void test_move_down_stops_at_last(void) {
      57            1 :     ListView lv; list_view_init(&lv);
      58            1 :     list_view_set_viewport(&lv, 5);
      59            1 :     list_view_set_count(&lv, 3);
      60           11 :     for (int i = 0; i < 10; i++) list_view_move_down(&lv);
      61            1 :     ASSERT(lv.selected == 2, "pinned at last");
      62              : }
      63              : 
      64            1 : static void test_move_up_stops_at_first(void) {
      65            1 :     ListView lv; list_view_init(&lv);
      66            1 :     list_view_set_viewport(&lv, 3);
      67            1 :     list_view_set_count(&lv, 10);
      68            6 :     for (int i = 0; i < 5; i++) list_view_move_down(&lv);
      69           11 :     for (int i = 0; i < 10; i++) list_view_move_up(&lv);
      70            1 :     ASSERT(lv.selected == 0, "pinned at first");
      71            1 :     ASSERT(lv.scroll_top == 0, "scroll back to top");
      72              : }
      73              : 
      74            1 : static void test_page_down_jumps_by_viewport(void) {
      75            1 :     ListView lv; list_view_init(&lv);
      76            1 :     list_view_set_viewport(&lv, 4);
      77            1 :     list_view_set_count(&lv, 20);
      78            1 :     list_view_page_down(&lv);
      79            1 :     ASSERT(lv.selected == 4, "selected jumped by 4");
      80            1 :     list_view_page_down(&lv);
      81            1 :     ASSERT(lv.selected == 8, "second page");
      82            1 :     ASSERT(list_view_is_visible(&lv, 8), "selection in viewport after page");
      83              : }
      84              : 
      85            1 : static void test_page_up_jumps_back(void) {
      86            1 :     ListView lv; list_view_init(&lv);
      87            1 :     list_view_set_viewport(&lv, 4);
      88            1 :     list_view_set_count(&lv, 20);
      89            1 :     lv.selected = 12;
      90            1 :     lv.scroll_top = 9;
      91            1 :     list_view_page_up(&lv);
      92            1 :     ASSERT(lv.selected == 8, "selected -= viewport");
      93              : }
      94              : 
      95            1 : static void test_home_end(void) {
      96            1 :     ListView lv; list_view_init(&lv);
      97            1 :     list_view_set_viewport(&lv, 5);
      98            1 :     list_view_set_count(&lv, 30);
      99            1 :     list_view_end(&lv);
     100            1 :     ASSERT(lv.selected == 29, "end selects last");
     101            1 :     ASSERT(list_view_is_visible(&lv, 29), "last visible");
     102            1 :     list_view_home(&lv);
     103            1 :     ASSERT(lv.selected == 0, "home selects first");
     104            1 :     ASSERT(lv.scroll_top == 0, "scroll to top");
     105              : }
     106              : 
     107            1 : static void test_reveal_keeps_selection_in_view(void) {
     108            1 :     ListView lv; list_view_init(&lv);
     109            1 :     list_view_set_viewport(&lv, 5);
     110            1 :     list_view_set_count(&lv, 30);
     111            1 :     lv.selected = 20;
     112            1 :     list_view_reveal_selected(&lv);
     113            1 :     ASSERT(list_view_is_visible(&lv, 20), "selection revealed");
     114            1 :     ASSERT(lv.scroll_top == 16, "minimum scroll for visibility");
     115              : }
     116              : 
     117            1 : static void test_set_viewport_reveals(void) {
     118            1 :     ListView lv; list_view_init(&lv);
     119            1 :     list_view_set_viewport(&lv, 10);
     120            1 :     list_view_set_count(&lv, 50);
     121            1 :     lv.selected = 40;
     122            1 :     list_view_reveal_selected(&lv);
     123            1 :     ASSERT(lv.scroll_top == 31, "scroll matches big viewport");
     124              :     /* Shrinking the viewport must keep selection visible. */
     125            1 :     list_view_set_viewport(&lv, 3);
     126            1 :     ASSERT(lv.rows_visible == 3, "viewport shrunk");
     127            1 :     ASSERT(list_view_is_visible(&lv, 40), "selection still visible");
     128              : }
     129              : 
     130            1 : static void test_move_on_empty_is_noop(void) {
     131            1 :     ListView lv; list_view_init(&lv);
     132            1 :     list_view_move_up(&lv);
     133            1 :     list_view_move_down(&lv);
     134            1 :     list_view_page_up(&lv);
     135            1 :     list_view_page_down(&lv);
     136            1 :     list_view_home(&lv);
     137            1 :     list_view_end(&lv);
     138            1 :     ASSERT(lv.selected == -1, "empty navigation left alone");
     139            1 :     ASSERT(lv.count == 0, "still empty");
     140              : }
     141              : 
     142            1 : static void test_is_visible_rejects_out_of_range(void) {
     143            1 :     ListView lv; list_view_init(&lv);
     144            1 :     list_view_set_viewport(&lv, 3);
     145            1 :     list_view_set_count(&lv, 5);
     146            1 :     ASSERT(list_view_is_visible(&lv, 0), "first visible");
     147            1 :     ASSERT(list_view_is_visible(&lv, 2), "last of viewport visible");
     148            1 :     ASSERT(!list_view_is_visible(&lv, 3), "row 3 not visible");
     149              : }
     150              : 
     151            1 : void test_tui_list_view_run(void) {
     152            1 :     RUN_TEST(test_init_is_empty);
     153            1 :     RUN_TEST(test_set_count_selects_first_when_unset);
     154            1 :     RUN_TEST(test_set_count_clamps_selected);
     155            1 :     RUN_TEST(test_set_count_zero_resets_selection);
     156            1 :     RUN_TEST(test_move_down_advances_and_scrolls);
     157            1 :     RUN_TEST(test_move_down_stops_at_last);
     158            1 :     RUN_TEST(test_move_up_stops_at_first);
     159            1 :     RUN_TEST(test_page_down_jumps_by_viewport);
     160            1 :     RUN_TEST(test_page_up_jumps_back);
     161            1 :     RUN_TEST(test_home_end);
     162            1 :     RUN_TEST(test_reveal_keeps_selection_in_view);
     163            1 :     RUN_TEST(test_set_viewport_reveals);
     164            1 :     RUN_TEST(test_move_on_empty_is_noop);
     165            1 :     RUN_TEST(test_is_visible_rejects_out_of_range);
     166            1 : }
        

Generated by: LCOV version 2.0-1