summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_tui.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/tests/test_tui.c b/tests/test_tui.c
index 7ab969b..d01a546 100644
--- a/tests/test_tui.c
+++ b/tests/test_tui.c
@@ -453,6 +453,98 @@ static void test_sticky(void)
static const unsigned char SECTION_FLAGS[5] = { 0, 1, 1, 0, 1 };
+static void test_goto_search(void)
+{
+ const char *rows[] = {
+ " x A1 2026-01-01 Golden verifikat",
+ " A2 2026-01-05 Hyra kontor",
+ " A10 2026-02-01 Företagsförsäkring",
+ " F1 2026-02-03 Faktura 1 Testkund AB",
+ " A11 2026-03-01 Hyra kontor mars",
+ };
+ struct tui_list_nav v;
+ nav_init(&v, 5);
+ v.items = rows;
+
+ /* case-insensitive, also for åäö */
+ CHECK(tui_text_match("Företagsförsäkring", "FÖRSÄK"));
+ CHECK(tui_text_match("ÅRSREDOVISNING", "årsred"));
+ CHECK(tui_text_match("abc", ""));
+ CHECK(!tui_text_match("abc", "abd"));
+ CHECK(!tui_text_match(NULL, "a"));
+
+ /* a letter first makes the prompt a search from the top */
+ CHECK(tui_nav_key(&v, 'g', 0, 0, 0, 0) == TUI_NAV_NONE && v.goto_active);
+ CHECK(tui_nav_key(&v, 'h', 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(v.goto_search && v.sel == 1);
+ tui_nav_key(&v, 'y', 0, 0, 0, 0);
+ tui_nav_key(&v, 'r', 0, 0, 0, 0);
+ CHECK(v.sel == 1 && !v.goto_miss);
+ /* down/up step through the matches and wrap */
+ tui_nav_key(&v, KEY_DOWN, 0, 0, 0, 0);
+ CHECK(v.sel == 4);
+ tui_nav_key(&v, KEY_DOWN, 0, 0, 0, 0);
+ CHECK(v.sel == 1);
+ tui_nav_key(&v, KEY_UP, 0, 0, 0, 0);
+ CHECK(v.sel == 4);
+ /* digits, 'g' and 'q' are text once searching */
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ CHECK(!v.goto_search && v.goto_active && v.gotobuf[0] == '\0');
+ tui_nav_key(&v, 'a', 0, 0, 0, 0);
+ tui_nav_key(&v, '1', 0, 0, 0, 0);
+ tui_nav_key(&v, '0', 0, 0, 0, 0);
+ CHECK(v.goto_search && v.sel == 2 && strcmp(v.gotobuf, "a10") == 0);
+ /* no match keeps the selection and flags the miss */
+ tui_nav_key(&v, 'q', 0, 0, 0, 0);
+ CHECK(v.goto_active && v.goto_miss && v.sel == 2);
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ CHECK(!v.goto_miss);
+ /* multi-byte input searches once the character is complete */
+ tui_nav_key(&v, 21, 0, 0, 0, 0); /* ^U is ignored in the prompt */
+ while (v.gotobuf[0])
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ tui_nav_key(&v, 0xC3, 0, 0, 0, 0); /* "ö" */
+ tui_nav_key(&v, 0xB6, 0, 0, 0, 0);
+ CHECK(v.goto_search && v.sel == 2 && strcmp(v.gotobuf, "ö") == 0);
+ tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0);
+ CHECK(v.gotobuf[0] == '\0' && !v.goto_search);
+ /* Enter closes without opening; the selection stays */
+ tui_nav_key(&v, 'f', 0, 0, 0, 0);
+ tui_nav_key(&v, '1', 0, 0, 0, 0);
+ CHECK(v.sel == 3);
+ CHECK(tui_nav_key(&v, '\n', 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(!v.goto_active && !v.goto_search && v.gotobuf[0] == '\0' &&
+ v.sel == 3);
+
+ /* digits first still jump to a row number */
+ tui_nav_key(&v, 'g', 0, 0, 0, 0);
+ tui_nav_key(&v, '2', 0, 0, 0, 0);
+ CHECK(!v.goto_search && v.sel == 1);
+ tui_nav_key(&v, 'g', 0, 0, 0, 0); /* 'g' closes a number prompt */
+ CHECK(!v.goto_active);
+
+ /* without row texts a letter does not search */
+ v.items = NULL;
+ tui_nav_key(&v, 'g', 0, 0, 0, 0);
+ tui_nav_key(&v, 'h', 0, 0, 0, 0);
+ CHECK(v.goto_active && !v.goto_search && v.sel == 1);
+ tui_nav_key(&v, 27, 0, 0, 0, 0);
+ CHECK(!v.goto_active);
+
+ /* menu section headers are never a match */
+ const char *menu[] = { "\001Hyra", "Hyra kontor", "Övrigt" };
+ const unsigned char sel[] = { 0, 1, 1 };
+ nav_init(&v, 3);
+ v.items = menu;
+ v.selectable = sel;
+ v.sel = 2;
+ tui_nav_key(&v, 'g', 0, 0, 0, 0);
+ tui_nav_key(&v, 'h', 0, 0, 0, 0);
+ CHECK(v.sel == 1);
+}
+
static void test_nav_sections(void)
{
struct tui_list_nav v;
@@ -1001,6 +1093,7 @@ int main(void)
test_sticky();
test_nav();
test_nav_sections();
+ test_goto_search();
test_form_nav();
test_form_actions();
test_form_focus();