gioser

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 660Markdown 302TOML 157RON 312382 Sutichaykuna

⎇ dba855e446ca2bd4e7d146bdc168fb232cad15a4 modules/command-palette/tests/smoke.rs Rust · 125 siq'ikuna · 4.1 KB Ñawpa willay Pi imata llamkarqan ch'uya

feat: llimphi standalone — framework UI soberano extraído del monorepo e65e9cc62 · Sergio ·

1//! Smoke tests del fuzzy match y del flujo `Open → KeyInput → Apply`.
2//! No requieren backend gráfico — sólo el reducer puro y `refilter`.
3
4use llimphi_module_command_palette::{
5    self as palette, Command, PaletteAction, PaletteMsg, PaletteState,
6};
7use llimphi_ui::{Key, KeyEvent, KeyState, Modifiers};
8
9fn seed() -> Vec<Command> {
10    vec![
11        Command::new("editor.save", "Save File", "Editor").with_shortcut("Ctrl+S"),
12        Command::new("editor.open", "Open File", "Editor").with_shortcut("Ctrl+P"),
13        Command::new("editor.findInFiles", "Find in Files", "Editor")
14            .with_shortcut("Ctrl+Shift+F"),
15        Command::new("terminal.open", "Open Terminal", "Terminal")
16            .with_shortcut("Ctrl+`"),
17        Command::new("lsp.format", "Format Document", "LSP")
18            .with_shortcut("Ctrl+Alt+L"),
19        Command::new("lsp.goto", "Go to Definition", "LSP").with_shortcut("F12"),
20    ]
21}
22
23fn key_char(c: &str) -> KeyEvent {
24    KeyEvent {
25        key: Key::Character(c.into()),
26        state: KeyState::Pressed,
27        text: Some(c.into()),
28        modifiers: Modifiers::default(),
29        repeat: false,
30    }
31}
32
33#[test]
34fn estado_vacio_lista_todos_los_comandos() {
35    let cmds = seed();
36    let s = PaletteState::new(&cmds);
37    assert_eq!(s.results.len(), cmds.len());
38    assert_eq!(s.selected, 0);
39}
40
41#[test]
42fn fuzzy_match_acerca_el_comando_correcto_al_top() {
43    let cmds = seed();
44    let mut s = PaletteState::new(&cmds);
45
46    // Tipear "term" debería rankear "Open Terminal" o "Terminal" arriba.
47    for ch in ["t", "e", "r", "m"] {
48        let action = palette::apply(&mut s, PaletteMsg::KeyInput(key_char(ch)), &cmds);
49        assert_eq!(action, PaletteAction::None);
50    }
51    let top = s.results.first().expect("debe haber al menos un match");
52    assert_eq!(
53        cmds[*top].id, "terminal.open",
54        "esperaba terminal.open al top, vi {:?}",
55        cmds[*top].title
56    );
57}
58
59#[test]
60fn enter_emite_invoke_con_el_id_seleccionado() {
61    let cmds = seed();
62    let mut s = PaletteState::new(&cmds);
63
64    for ch in ["s", "a", "v"] {
65        palette::apply(&mut s, PaletteMsg::KeyInput(key_char(ch)), &cmds);
66    }
67    let action = palette::apply(&mut s, PaletteMsg::Apply, &cmds);
68    assert_eq!(action, PaletteAction::Invoke("editor.save".into()));
69}
70
71#[test]
72fn nav_circula_por_los_resultados() {
73    let cmds = seed();
74    let mut s = PaletteState::new(&cmds);
75    assert_eq!(s.selected, 0);
76
77    palette::apply(&mut s, PaletteMsg::Nav(1), &cmds);
78    assert_eq!(s.selected, 1);
79
80    // Saltar al final desde la cima con -1 (wrap-around).
81    let mut s = PaletteState::new(&cmds);
82    palette::apply(&mut s, PaletteMsg::Nav(-1), &cmds);
83    assert_eq!(s.selected, cmds.len() - 1);
84}
85
86#[test]
87fn escape_emite_close() {
88    let cmds = seed();
89    let mut s = PaletteState::new(&cmds);
90    let action = palette::apply(&mut s, PaletteMsg::Close, &cmds);
91    assert_eq!(action, PaletteAction::Close);
92}
93
94#[test]
95fn open_shortcut_es_ctrl_shift_p() {
96    use llimphi_ui::Modifiers;
97    let mk = |ctrl: bool, shift: bool, c: &str| KeyEvent {
98        key: Key::Character(c.into()),
99        state: KeyState::Pressed,
100        text: Some(c.into()),
101        modifiers: Modifiers { ctrl, shift, ..Modifiers::default() },
102        repeat: false,
103    };
104    assert!(palette::open_shortcut(&mk(true, true, "p")));
105    assert!(palette::open_shortcut(&mk(true, true, "P")));
106    // Sin shift no — ese es Ctrl+P del file-picker.
107    assert!(!palette::open_shortcut(&mk(true, false, "p")));
108    // Sin ctrl no.
109    assert!(!palette::open_shortcut(&mk(false, true, "p")));
110    // Otra letra no.
111    assert!(!palette::open_shortcut(&mk(true, true, "q")));
112}
113
114#[test]
115fn busqueda_por_grupo_funciona() {
116    let cmds = seed();
117    let mut s = PaletteState::new(&cmds);
118    // "lsp" debería traer Format y Goto Definition (ambos del grupo LSP).
119    for ch in ["l", "s", "p"] {
120        palette::apply(&mut s, PaletteMsg::KeyInput(key_char(ch)), &cmds);
121    }
122    let ids: Vec<&str> = s.results.iter().map(|&i| cmds[i].id.as_str()).collect();
123    assert!(ids.contains(&"lsp.format"), "esperaba lsp.format en {ids:?}");
124    assert!(ids.contains(&"lsp.goto"), "esperaba lsp.goto en {ids:?}");
125}