1
//! Tests for command-line Tab completion.
2

            
3
use super::make_app;
4
use crate::event::{Intent, apply};
5

            
6
#[test]
7
1
fn tab_in_cmdline_completes_single_candidate() {
8
1
    let mut app = make_app();
9
1
    apply(&mut app, Intent::OpenCommandLine);
10
3
    for c in "acc".chars() {
11
3
        apply(&mut app, Intent::InsertChar(c));
12
3
    }
13
1
    apply(&mut app, Intent::CompleteCommandLine);
14
1
    assert_eq!(
15
1
        app.cmdline.editor.buffer(),
16
        "account ",
17
        "single match should complete and append space"
18
    );
19
1
    assert!(app.cmdline.completions.contains(&"account".to_string()));
20
1
}
21

            
22
#[test]
23
1
fn tab_in_cmdline_shows_multiple_candidates() {
24
1
    let mut app = make_app();
25
1
    apply(&mut app, Intent::OpenCommandLine);
26
8
    for c in "account ".chars() {
27
8
        apply(&mut app, Intent::InsertChar(c));
28
8
    }
29
1
    apply(&mut app, Intent::CompleteCommandLine);
30
1
    assert!(
31
1
        app.cmdline.completions.len() > 1,
32
        "after 'account ' multiple children should be candidates"
33
    );
34
1
    assert!(app.cmdline.completions.contains(&"create".to_string()));
35
1
    assert!(app.cmdline.completions.contains(&"list".to_string()));
36
1
}
37

            
38
#[test]
39
1
fn tab_in_cmdline_applies_lcp_for_ambiguous() {
40
1
    let mut app = make_app();
41
1
    apply(&mut app, Intent::OpenCommandLine);
42
    // "co" matches "commodity" and "config"
43
2
    for c in "co".chars() {
44
2
        apply(&mut app, Intent::InsertChar(c));
45
2
    }
46
1
    apply(&mut app, Intent::CompleteCommandLine);
47
1
    let buf = app.cmdline.editor.buffer();
48
1
    assert!(
49
1
        buf.starts_with("co"),
50
        "buffer must retain common prefix: got {buf:?}"
51
    );
52
1
    assert!(
53
1
        app.cmdline.completions.contains(&"commodity".to_string()),
54
        "commodity must be a candidate"
55
    );
56
1
    assert!(
57
1
        app.cmdline.completions.contains(&"config".to_string()),
58
        "config must be a candidate"
59
    );
60
1
    assert!(
61
1
        !buf.ends_with(' '),
62
        "ambiguous completion must not append a space"
63
    );
64
1
}
65

            
66
#[test]
67
1
fn tab_in_cmdline_does_nothing_on_no_match() {
68
1
    let mut app = make_app();
69
1
    apply(&mut app, Intent::OpenCommandLine);
70
10
    for c in "zzznomatch".chars() {
71
10
        apply(&mut app, Intent::InsertChar(c));
72
10
    }
73
1
    apply(&mut app, Intent::CompleteCommandLine);
74
1
    assert_eq!(app.cmdline.editor.buffer(), "zzznomatch");
75
1
    assert!(app.cmdline.completions.is_empty());
76
1
}
77

            
78
#[test]
79
1
fn editing_after_completion_clears_stale_candidates() {
80
1
    let mut app = make_app();
81
1
    apply(&mut app, Intent::OpenCommandLine);
82
8
    for c in "account ".chars() {
83
8
        apply(&mut app, Intent::InsertChar(c));
84
8
    }
85
1
    apply(&mut app, Intent::CompleteCommandLine);
86
1
    assert!(
87
1
        !app.cmdline.completions.is_empty(),
88
        "candidates should be shown right after Tab"
89
    );
90
1
    apply(&mut app, Intent::InsertChar('c'));
91
1
    assert!(
92
1
        app.cmdline.completions.is_empty(),
93
        "a normal edit must clear stale candidates"
94
    );
95
1
}