Files
pikl/crates/pikl/tests/headless_dsl.rs

335 lines
8.7 KiB
Rust

#![cfg(unix)]
mod common;
use common::run_pikl;
use pikl_test_macros::pikl_tests;
pikl_tests! {
headless mod basic_selection {
items: ["alpha", "beta", "charlie"];
test confirm_first {
actions: [confirm]
stdout: "alpha"
exit: 0
}
test move_down_and_confirm {
actions: [move-down, confirm]
stdout: "beta"
exit: 0
}
test move_to_third {
actions: [move-down, move-down, confirm]
stdout: "charlie"
exit: 0
}
test cancel_exits_1 {
actions: [cancel]
stdout: ""
exit: 1
}
test empty_script_cancels {
actions: []
exit: 1
}
}
headless mod filtering {
items: ["alpha", "beta", "banana"];
test filter_then_confirm {
actions: [filter "ban", confirm]
stdout: "banana"
exit: 0
}
}
headless mod errors {
items: ["one", "two"];
test invalid_action {
actions: [raw "bogus"]
stderr contains: "unknown action"
exit: 2
}
test actions_after_show_ui {
actions: [raw "show-ui", raw "confirm"]
stderr contains: "actions after show-ui"
exit: 2
}
}
// ── Demo scenario tests ──────────────────────────────
// These cover the scenarios from examples/demo.sh so
// we catch regressions in the demo workflows.
headless mod demo_plain_text {
items: [
"apple", "banana", "cherry", "date",
"elderberry", "fig", "grape", "honeydew"
];
test confirm_first {
actions: [confirm]
stdout: "apple"
exit: 0
}
test navigate_to_last {
actions: [move-to-bottom, confirm]
stdout: "honeydew"
exit: 0
}
test filter_then_confirm {
actions: [filter "cher", confirm]
stdout: "cherry"
exit: 0
}
test filter_narrows_to_one {
actions: [filter "elder", confirm]
stdout: "elderberry"
exit: 0
}
test cancel {
actions: [cancel]
exit: 1
}
}
headless mod demo_big_list {
// Bare numbers parse as JSON numbers with empty labels,
// so we prefix with "item-" to keep them as plain text.
items: [
"item-1", "item-2", "item-3", "item-4", "item-5",
"item-6", "item-7", "item-8", "item-9", "item-10",
"item-11", "item-12", "item-13", "item-14", "item-15",
"item-16", "item-17", "item-18", "item-19", "item-20",
"item-50", "item-100", "item-200", "item-499", "item-500"
];
test confirm_first {
actions: [confirm]
stdout: "item-1"
exit: 0
}
test move_to_bottom {
actions: [move-to-bottom, confirm]
stdout: "item-500"
exit: 0
}
test filter_exact {
actions: [filter "item-499", confirm]
stdout: "item-499"
exit: 0
}
test page_down_then_confirm {
actions: [page-down, confirm]
exit: 0
}
}
headless mod demo_json_objects {
items: [
"{\"label\": \"Arch Linux\", \"category\": \"rolling\", \"init\": \"systemd\"}",
"{\"label\": \"NixOS\", \"category\": \"rolling\", \"init\": \"systemd\"}",
"{\"label\": \"Void Linux\", \"category\": \"rolling\", \"init\": \"runit\"}",
"{\"label\": \"Debian\", \"category\": \"stable\", \"init\": \"systemd\"}",
"{\"label\": \"Alpine\", \"category\": \"stable\", \"init\": \"openrc\"}",
"{\"label\": \"Fedora\", \"category\": \"semi-rolling\", \"init\": \"systemd\"}",
"{\"label\": \"Gentoo\", \"category\": \"rolling\", \"init\": \"openrc\"}"
];
test confirm_first {
actions: [confirm]
stdout: "Arch Linux"
exit: 0
}
test preserves_json_fields {
actions: [confirm]
stdout: "rolling"
exit: 0
}
test filter_by_label {
actions: [filter "Void", confirm]
stdout: "Void Linux"
exit: 0
}
test navigate_to_debian {
actions: [move-down, move-down, move-down, confirm]
stdout: "Debian"
exit: 0
}
test filter_and_navigate {
actions: [filter "Linux", move-down, confirm]
stdout: "Void Linux"
exit: 0
}
test cancel {
actions: [cancel]
exit: 1
}
}
headless mod demo_custom_label_key {
items: [
"{\"name\": \"Neovim\", \"type\": \"editor\", \"lang\": \"C/Lua\"}",
"{\"name\": \"Helix\", \"type\": \"editor\", \"lang\": \"Rust\"}",
"{\"name\": \"Kakoune\", \"type\": \"editor\", \"lang\": \"C++\"}",
"{\"name\": \"Emacs\", \"type\": \"editor\", \"lang\": \"Lisp\"}",
"{\"name\": \"Vim\", \"type\": \"editor\", \"lang\": \"C\"}"
];
label_key: "name";
test confirm_first {
actions: [confirm]
stdout: "Neovim"
exit: 0
}
test filter_by_name {
actions: [filter "Hel", confirm]
stdout: "Helix"
exit: 0
}
test preserves_lang_field {
actions: [move-down, confirm]
stdout: "Rust"
exit: 0
}
test navigate_to_last {
actions: [move-to-bottom, confirm]
stdout: "Vim"
exit: 0
}
}
headless mod demo_mixed_input {
items: [
"just a plain string",
"{\"label\": \"a json object\", \"extra\": 42}",
"another plain string",
"{\"label\": \"second object\", \"extra\": 99}"
];
test confirm_plain_text {
actions: [confirm]
stdout: "just a plain string"
exit: 0
}
test confirm_json_object {
actions: [move-down, confirm]
stdout: "a json object"
exit: 0
}
test json_preserves_extra {
actions: [move-down, confirm]
stdout: "42"
exit: 0
}
test navigate_to_second_plain {
actions: [move-down, move-down, confirm]
stdout: "another plain string"
exit: 0
}
test navigate_to_second_json {
actions: [move-down, move-down, move-down, confirm]
stdout: "second object"
exit: 0
}
test filter_across_types {
actions: [filter "plain", confirm]
stdout: "just a plain string"
exit: 0
}
}
headless mod new_actions {
items: ["a","b","c","d","e","f","g","h","i","j"];
test half_page_down_confirm {
actions: [raw "half-page-down", confirm]
// headless viewport=50, half=25, clamps to last (idx 9) -> "j"
stdout: "j"
exit: 0
}
test set_mode_round_trip {
actions: [raw "set-mode normal", raw "set-mode insert", confirm]
stdout: "a"
exit: 0
}
}
headless mod multi_select_headless {
items: ["alpha", "bravo", "charlie"];
multi: true;
test toggle_and_confirm {
actions: [toggle-select, confirm]
stdout: "alpha"
exit: 0
}
test toggle_two_and_confirm {
actions: [toggle-select, move-down, move-down, toggle-select, confirm]
stdout: "alpha"
exit: 0
}
test select_all_and_confirm {
actions: [select-all, confirm]
stdout: "alpha"
exit: 0
}
test deselect_all_clears {
actions: [toggle-select, deselect-all, confirm]
// Falls back to cursor item
stdout: "alpha"
exit: 0
}
test without_multi_toggle_is_noop {
// This test does NOT have multi: true (uses the shared fixture)
// but toggle-select still just selects cursor on confirm
actions: [toggle-select, confirm]
stdout: "alpha"
exit: 0
}
}
headless mod pipeline_headless {
items: ["error_log", "warning_temp", "info_log"];
test pipeline_filter {
actions: [filter "'log | !error", confirm]
stdout: "info_log"
exit: 0
}
}
}