Line data Source code
1 : /**
2 : * @file tests/unit/test_tui_status_row.c
3 : * @brief Unit tests for the status row (US-11 v2).
4 : */
5 :
6 : #include "test_helpers.h"
7 : #include "tui/status_row.h"
8 :
9 : #include <string.h>
10 :
11 2 : static void row_text(const Screen *s, int row, char *out, size_t cap) {
12 2 : size_t oi = 0;
13 162 : for (int c = 0; c < s->cols && oi + 1 < cap; c++) {
14 160 : ScreenCell cell = s->back[row * s->cols + c];
15 160 : out[oi++] = (cell.cp && cell.cp < 128) ? (char)cell.cp : ' ';
16 : }
17 2 : out[oi] = '\0';
18 2 : }
19 :
20 1 : static void test_init_is_dialogs_mode(void) {
21 1 : StatusRow sr; status_row_init(&sr);
22 1 : ASSERT(sr.mode == STATUS_MODE_DIALOGS, "default mode is dialogs");
23 1 : ASSERT(sr.message[0] == '\0', "empty message");
24 : }
25 :
26 1 : static void test_set_message_truncates(void) {
27 1 : StatusRow sr; status_row_init(&sr);
28 : char big[STATUS_ROW_MSG_MAX + 50];
29 1 : memset(big, 'x', sizeof(big));
30 1 : big[sizeof(big) - 1] = '\0';
31 1 : status_row_set_message(&sr, big);
32 1 : ASSERT(strlen(sr.message) == STATUS_ROW_MSG_MAX - 1, "truncated");
33 1 : status_row_set_message(&sr, NULL);
34 1 : ASSERT(sr.message[0] == '\0', "null clears");
35 : }
36 :
37 1 : static void test_render_dialogs_mode_shows_hint(void) {
38 1 : Screen s; ASSERT(screen_init(&s, 1, 80) == 0, "init");
39 1 : StatusRow sr; status_row_init(&sr);
40 1 : Pane p = { .row = 0, .col = 0, .rows = 1, .cols = 80 };
41 1 : status_row_render(&sr, &p, &s);
42 1 : char buf[128]; row_text(&s, 0, buf, sizeof(buf));
43 1 : ASSERT(strstr(buf, "[dialogs]") != NULL, "dialogs prefix");
44 1 : ASSERT(strstr(buf, "Enter") != NULL, "enter hint");
45 : /* Every cell on the row must have SCREEN_ATTR_REVERSE set. */
46 81 : for (int c = 0; c < 80; c++) {
47 80 : ASSERT(s.back[c].attrs & SCREEN_ATTR_REVERSE, "full-row reverse");
48 : }
49 1 : screen_free(&s);
50 : }
51 :
52 1 : static void test_render_history_mode_shows_different_hint(void) {
53 1 : Screen s; ASSERT(screen_init(&s, 1, 80) == 0, "init");
54 1 : StatusRow sr; status_row_init(&sr);
55 1 : sr.mode = STATUS_MODE_HISTORY;
56 1 : Pane p = { .row = 0, .col = 0, .rows = 1, .cols = 80 };
57 1 : status_row_render(&sr, &p, &s);
58 1 : char buf[128]; row_text(&s, 0, buf, sizeof(buf));
59 1 : ASSERT(strstr(buf, "[history]") != NULL, "history prefix");
60 1 : ASSERT(strstr(buf, "Tab") != NULL, "tab hint");
61 1 : screen_free(&s);
62 : }
63 :
64 1 : static void test_render_message_right_aligned(void) {
65 1 : Screen s; ASSERT(screen_init(&s, 1, 80) == 0, "init");
66 1 : StatusRow sr; status_row_init(&sr);
67 1 : status_row_set_message(&sr, "loading");
68 1 : Pane p = { .row = 0, .col = 0, .rows = 1, .cols = 80 };
69 1 : status_row_render(&sr, &p, &s);
70 : /* "loading" is 7 chars; col = 80 - 7 - 1 = 72 */
71 1 : ASSERT(s.back[72].cp == 'l', "message starts at right-aligned col");
72 1 : ASSERT(s.back[78].cp == 'g', "message ends near right edge");
73 1 : screen_free(&s);
74 : }
75 :
76 1 : static void test_render_null_args_noop(void) {
77 1 : Screen s; ASSERT(screen_init(&s, 1, 20) == 0, "init");
78 1 : Pane p = { .row = 0, .col = 0, .rows = 1, .cols = 20 };
79 1 : StatusRow sr; status_row_init(&sr);
80 1 : status_row_render(NULL, &p, &s);
81 1 : status_row_render(&sr, NULL, &s);
82 1 : status_row_render(&sr, &p, NULL);
83 1 : ASSERT(s.back[0].cp == ' ', "back untouched");
84 1 : screen_free(&s);
85 : }
86 :
87 1 : void test_tui_status_row_run(void) {
88 1 : RUN_TEST(test_init_is_dialogs_mode);
89 1 : RUN_TEST(test_set_message_truncates);
90 1 : RUN_TEST(test_render_dialogs_mode_shows_hint);
91 1 : RUN_TEST(test_render_history_mode_shows_different_hint);
92 1 : RUN_TEST(test_render_message_right_aligned);
93 1 : RUN_TEST(test_render_null_args_noop);
94 1 : }
|