summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-23 10:58:17 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-23 10:58:17 +0200
commit71a702f375750829c634b552217c9925d549828b (patch)
tree2b963da1d0110ed43920722ba4193ee9c79f2521 /tests
parent8ccb6d58d8e2f1c65dfd7ab5f0eb7d93f1f19def (diff)
downloadbokf-71a702f375750829c634b552217c9925d549828b.tar.gz
bokf-71a702f375750829c634b552217c9925d549828b.zip
tui: context menu on → / ^O; no F-keys, ^N or ^Enter
→ (where no caret uses it) and ^O (everywhere, also in table cells) open "Åtgärder": a box at the right edge with every action of the view and its key. Screens declare their actions with tui_set_actions(); choosing one feeds its key to the widget, so the menu and accelerators share one path. Function keys, Ctrl+N (now n), Ctrl+Enter and Ctrl+F are gone and no extended keyboard protocol is enabled, so the TUI works in a browser terminal; save/post/validate/preview/template/attach are menu actions. make check rejects F-keys, ^N and ^Enter in clients/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/test_tui.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/tests/test_tui.c b/tests/test_tui.c
index d01a546..c0c5f0d 100644
--- a/tests/test_tui.c
+++ b/tests/test_tui.c
@@ -329,9 +329,13 @@ static void test_nav(void)
nav_init(&v, 0);
CHECK(tui_nav_key(&v, KEY_DOWN, 0, 0, 0, 0) == TUI_NAV_NONE);
- CHECK(tui_nav_key(&v, KEY_F(5), 0, 0, 0, 0) == -2);
- CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 1, 0, 0, 0) == -4);
- CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(tui_nav_key(&v, 'r', 0, 0, 0, 0) == -2);
+ CHECK(tui_nav_key(&v, TUI_KEY_REFRESH, 0, 0, 0, 0) == -2);
+ CHECK(tui_nav_key(&v, 'n', 1, 0, 0, 0) == -4);
+ CHECK(tui_nav_key(&v, 'n', 0, 0, 0, 0) == TUI_NAV_NONE);
+ /* no F-keys and no ^N: browsers own them */
+ CHECK(tui_nav_key(&v, KEY_F(5), 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 1, 0, 0, 0) == TUI_NAV_NONE);
CHECK(tui_nav_key(&v, 'q', 0, 0, 0, 0) == -1);
CHECK(tui_nav_key(&v, 27, 0, 0, 0, 0) == -1);
@@ -350,9 +354,13 @@ static void test_nav(void)
CHECK(tui_nav_key(&v, '9', 0, 0, 0, 0) == TUI_NAV_NONE); /* out of range */
CHECK(tui_nav_key(&v, '\n', 0, 0, 0, 0) == v.sel);
- CHECK(tui_nav_key(&v, KEY_F(5), 0, 0, 0, 0) == -2);
- CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 1, 0, 0, 0) == -4);
- CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(tui_nav_key(&v, 'r', 0, 0, 0, 0) == -2);
+ CHECK(tui_nav_key(&v, TUI_KEY_REFRESH, 0, 0, 0, 0) == -2);
+ CHECK(tui_nav_key(&v, 'n', 1, 0, 0, 0) == -4);
+ CHECK(tui_nav_key(&v, 'n', 0, 0, 0, 0) == TUI_NAV_NONE);
+ /* no F-keys and no ^N: browsers own them */
+ CHECK(tui_nav_key(&v, KEY_F(5), 0, 0, 0, 0) == TUI_NAV_NONE);
+ CHECK(tui_nav_key(&v, TUI_KEY_CTRL_N, 1, 0, 0, 0) == TUI_NAV_NONE);
CHECK(tui_nav_key(&v, 'd', 0, 1, 0, 0) == -6);
CHECK(tui_nav_key(&v, 'd', 0, 0, 0, 0) == TUI_NAV_NONE);
CHECK(tui_nav_key(&v, 1, 0, 0, 1, 0) == -7); /* ^A */
@@ -590,9 +598,11 @@ static void test_form_nav(void)
CHECK(tui_form_next(0, 3, KEY_UP) == TUI_NAV_NONE);
CHECK(tui_form_next(0, 3, KEY_DOWN) == 1);
CHECK(tui_form_next(2, 3, KEY_DOWN) == TUI_NAV_NONE);
- CHECK(tui_form_next(1, 3, KEY_F(5)) == TUI_FORM_REFRESH);
- CHECK(tui_form_next(1, 3, TUI_KEY_CTRL_ENTER) == TUI_FORM_SUBMIT);
- CHECK(tui_form_next(1, 3, KEY_F(9)) == TUI_FORM_SUBMIT);
+ CHECK(tui_form_next(1, 3, TUI_KEY_REFRESH) == TUI_FORM_REFRESH);
+ CHECK(tui_form_next(1, 3, TUI_KEY_SUBMIT) == TUI_FORM_SUBMIT);
+ CHECK(tui_form_next(1, 3, KEY_F(5)) == TUI_NAV_NONE);
+ CHECK(tui_form_next(1, 3, KEY_F(9)) == TUI_NAV_NONE);
+ CHECK(tui_form_next(1, 3, TUI_KEY_CTRL_ENTER) == TUI_NAV_NONE);
CHECK(tui_form_next(1, 3, 27) == TUI_FORM_BACK);
CHECK(tui_form_next(1, 3, 'q') == TUI_FORM_BACK);
CHECK(tui_form_next(1, 3, 'x') == TUI_NAV_NONE);
@@ -662,8 +672,9 @@ static void test_form_actions(void)
CHECK(tui_form_act_page(4, nf, ACTS, 6, 1) == 8);
CHECK(tui_form_act_page(4, nf, ACTS, 6, -1) == 0);
CHECK(tui_form_act_page(0, 0, NULL, 0, 1) == -1);
- CHECK(tui_form_act_key(0, nf, ACTS, 6, KEY_F(5)) == TUI_FORM_REFRESH);
- CHECK(tui_form_act_key(5, nf, ACTS, 6, TUI_KEY_CTRL_ENTER) ==
+ CHECK(tui_form_act_key(0, nf, ACTS, 6, TUI_KEY_REFRESH) ==
+ TUI_FORM_REFRESH);
+ CHECK(tui_form_act_key(5, nf, ACTS, 6, TUI_KEY_SUBMIT) ==
TUI_FORM_SUBMIT);
CHECK(tui_form_act_key(5, nf, ACTS, 6, 27) == TUI_FORM_BACK);
CHECK(tui_form_act_key(5, nf, ACTS, 6, 'x') == TUI_NAV_NONE);
@@ -936,10 +947,11 @@ static void test_actions(void)
{
char buf[256];
struct tui_action acts[] = {
- { "save", "Spara", KEY_F(9), 1, NULL },
+ { "save", "Spara", TUI_KEY_SUBMIT, 1, NULL },
{ "del", "Radera utkast", 0, 0, "inget utkast" },
{ "sec", "Sektion", 0, -1, NULL },
- { "arch", "Arkivera", KEY_F(2), 1, NULL },
+ { "arch", "Arkivera", 'd', 1, NULL },
+ { "att", "Bifoga fil", 'a', 1, NULL },
};
tui_action_label(&acts[0], buf, sizeof buf);
@@ -947,18 +959,57 @@ static void test_actions(void)
tui_action_label(&acts[1], buf, sizeof buf);
CHECK(strcmp(buf, "Radera utkast (inget utkast)") == 0);
- tui_action_hint(acts, 4, 1, buf, sizeof buf);
- CHECK(strstr(buf, "F9 = Spara") != NULL);
- CHECK(strstr(buf, "F2 = fler") != NULL);
- CHECK(strstr(buf, "Arkivera") == NULL);
+ /* virtual keys are menu-only: not in the footer */
+ tui_action_hint(acts, 5, 1, buf, sizeof buf);
+ CHECK(strcmp(buf, "d = Arkivera → = åtgärder") == 0);
+ tui_action_hint(acts, 5, 0, buf, sizeof buf);
+ CHECK(strcmp(buf, "d = Arkivera a = Bifoga fil → = åtgärder") == 0);
+ tui_action_hint(NULL, 0, 1, buf, sizeof buf);
+ CHECK(strcmp(buf, "→ = åtgärder") == 0);
- tui_action_hint(acts, 4, 0, buf, sizeof buf);
- CHECK(strstr(buf, "F9 = Spara") != NULL);
- CHECK(strstr(buf, "F2 = Arkivera F2 = fler") != NULL);
- CHECK(strstr(buf, "Radera utkast") == NULL);
+ /* key names: web-safe keys only, virtual keys have none */
+ tui_key_name('\n', buf, sizeof buf);
+ CHECK(strcmp(buf, "Enter") == 0);
+ tui_key_name(27, buf, sizeof buf);
+ CHECK(strcmp(buf, "Esc") == 0);
+ tui_key_name(TUI_KEY_CTRL_X, buf, sizeof buf);
+ CHECK(strcmp(buf, "^X") == 0);
+ tui_key_name('n', buf, sizeof buf);
+ CHECK(strcmp(buf, "n") == 0);
+ tui_key_name(KEY_UP, buf, sizeof buf);
+ CHECK(strcmp(buf, "↑") == 0);
+ tui_key_name(TUI_KEY_SUBMIT, buf, sizeof buf);
+ CHECK(buf[0] == '\0');
+ tui_key_name(TUI_KEY_ACTION(3), buf, sizeof buf);
+ CHECK(buf[0] == '\0');
- tui_action_hint(NULL, 0, 1, buf, sizeof buf);
- CHECK(strcmp(buf, "F2 = fler") == 0);
+ /* the context menu: screen actions, a separator, then the widget's own
+ actions whose key the screen did not take */
+ struct tui_action scr[] = {
+ { "v.post", "Bokför", TUI_KEY_SUBMIT, 1, NULL },
+ { "v.tpl", "Hämta mall…", TUI_KEY_ACTION(0), 1, NULL },
+ };
+ struct tui_action own[] = {
+ { "rt.refresh", "Validera", TUI_KEY_REFRESH, 1, NULL },
+ { "rt.submit", "Spara", TUI_KEY_SUBMIT, 1, NULL },
+ { "rt.back", "Avbryt", 27, 1, NULL },
+ };
+ struct tui_action out[8];
+ int n = tui_ctx_merge(scr, 2, own, 3, out, 8);
+ CHECK(n == 5);
+ CHECK(strcmp(out[0].label, "Bokför") == 0);
+ CHECK(strcmp(out[1].label, "Hämta mall…") == 0);
+ CHECK(out[2].enabled == -1 && out[2].label[0] == '\0');
+ CHECK(strcmp(out[3].label, "Validera") == 0);
+ CHECK(strcmp(out[4].label, "Avbryt") == 0); /* Spara: key taken */
+ /* no screen actions: no separator */
+ n = tui_ctx_merge(NULL, 0, own, 3, out, 8);
+ CHECK(n == 3 && strcmp(out[0].label, "Validera") == 0);
+ /* capacity is respected */
+ n = tui_ctx_merge(scr, 2, own, 3, out, 3); /* no room: no separator */
+ CHECK(n == 3 && strcmp(out[2].label, "Validera") == 0);
+ n = tui_ctx_merge(scr, 2, own, 3, out, 4);
+ CHECK(n == 4 && strcmp(out[3].label, "Validera") == 0);
}
static void test_drafts(void)