1
use super::*;
2

            
3
13
fn console() -> ConsoleState {
4
13
    ConsoleState::new()
5
13
}
6

            
7
1020
fn type_line(state: &mut ConsoleState, text: &str) {
8
5984
    for c in text.chars() {
9
5984
        state.input.insert_char(c);
10
5984
    }
11
1020
}
12

            
13
#[test]
14
1
fn incomplete_form_buffers_and_yields_nothing() {
15
1
    let mut state = console();
16
1
    type_line(&mut state, "(list");
17
1
    assert_eq!(state.take_complete_form(), None);
18
1
    assert_eq!(state.pending, "(list");
19
1
    assert!(state.input.buffer().is_empty());
20
1
    assert!(state.history.is_empty());
21
1
}
22

            
23
#[test]
24
1
fn balanced_form_yields_and_clears_buffer() {
25
1
    let mut state = console();
26
1
    type_line(&mut state, "(+ 1 2)");
27
1
    let form = state.take_complete_form();
28
1
    assert_eq!(form.as_deref(), Some("(+ 1 2)"));
29
1
    assert!(state.pending.is_empty());
30
1
    assert!(state.input.buffer().is_empty());
31
1
}
32

            
33
#[test]
34
1
fn multiline_form_assembles_then_completes() {
35
1
    let mut state = console();
36
1
    type_line(&mut state, "(list");
37
1
    assert_eq!(state.take_complete_form(), None);
38
1
    type_line(&mut state, " 1 2)");
39
1
    let form = state.take_complete_form();
40
1
    assert_eq!(form.as_deref(), Some("(list\n 1 2)"));
41
1
    assert!(state.pending.is_empty());
42
1
}
43

            
44
#[test]
45
1
fn submitted_form_is_pushed_to_history() {
46
1
    let mut state = console();
47
1
    type_line(&mut state, "(foo)");
48
1
    let _ = state.take_complete_form();
49
1
    assert_eq!(state.history, vec!["(foo)".to_string()]);
50
1
    assert_eq!(state.history_cursor, None);
51
1
}
52

            
53
#[test]
54
1
fn incomplete_form_not_pushed_to_history() {
55
1
    let mut state = console();
56
1
    type_line(&mut state, "(open");
57
1
    let _ = state.take_complete_form();
58
1
    assert!(state.history.is_empty());
59
1
}
60

            
61
#[test]
62
1
fn history_prev_loads_latest_then_older_entries() {
63
1
    let mut state = console();
64
3
    for form in ["(a)", "(b)", "(c)"] {
65
3
        type_line(&mut state, form);
66
3
        let _ = state.take_complete_form();
67
3
    }
68
1
    state.history_prev();
69
1
    assert_eq!(state.input.buffer(), "(c)");
70
1
    state.history_prev();
71
1
    assert_eq!(state.input.buffer(), "(b)");
72
1
    state.history_prev();
73
1
    assert_eq!(state.input.buffer(), "(a)");
74
1
    state.history_prev();
75
1
    assert_eq!(state.input.buffer(), "(a)");
76
1
}
77

            
78
#[test]
79
1
fn history_next_walks_forward_then_clears_to_fresh_line() {
80
1
    let mut state = console();
81
2
    for form in ["(a)", "(b)"] {
82
2
        type_line(&mut state, form);
83
2
        let _ = state.take_complete_form();
84
2
    }
85
1
    state.history_prev();
86
1
    state.history_prev();
87
1
    assert_eq!(state.input.buffer(), "(a)");
88
1
    state.history_next();
89
1
    assert_eq!(state.input.buffer(), "(b)");
90
1
    state.history_next();
91
1
    assert!(state.input.buffer().is_empty());
92
1
    assert_eq!(state.history_cursor, None);
93
1
}
94

            
95
#[test]
96
1
fn history_navigation_is_noop_without_history() {
97
1
    let mut state = console();
98
1
    state.history_prev();
99
1
    assert!(state.input.buffer().is_empty());
100
1
    state.history_next();
101
1
    assert!(state.input.buffer().is_empty());
102
1
    assert_eq!(state.history_cursor, None);
103
1
}
104

            
105
#[test]
106
1
fn blank_enter_yields_nothing_and_records_no_history() {
107
1
    let mut state = console();
108
1
    assert_eq!(state.take_complete_form(), None);
109
1
    assert!(state.history.is_empty());
110
1
    assert!(state.pending.is_empty());
111
1
    type_line(&mut state, "   ");
112
1
    assert_eq!(state.take_complete_form(), None);
113
1
    assert!(state.history.is_empty());
114
1
}
115

            
116
#[test]
117
1
fn duplicate_consecutive_submissions_both_recorded() {
118
1
    let mut state = console();
119
1
    for _ in 0..2 {
120
2
        type_line(&mut state, "(a)");
121
2
        assert_eq!(state.take_complete_form().as_deref(), Some("(a)"));
122
    }
123
1
    assert_eq!(state.history, vec!["(a)".to_string(), "(a)".to_string()]);
124
1
}
125

            
126
#[test]
127
1
fn history_next_at_bottom_is_noop() {
128
1
    let mut state = console();
129
1
    type_line(&mut state, "(a)");
130
1
    let _ = state.take_complete_form();
131
1
    assert_eq!(state.history_cursor, None);
132
1
    state.history_next();
133
1
    assert_eq!(state.history_cursor, None);
134
1
    assert!(state.input.buffer().is_empty());
135
1
}
136

            
137
#[test]
138
1
fn history_caps_at_max_dropping_oldest() {
139
1
    let mut state = console();
140
1005
    for i in 0..(MAX_HISTORY_ENTRIES + 5) {
141
1005
        type_line(&mut state, &format!("(f{i})"));
142
1005
        let _ = state.take_complete_form();
143
1005
    }
144
1
    assert_eq!(state.history.len(), MAX_HISTORY_ENTRIES);
145
1
    assert_eq!(state.history.first().unwrap(), "(f5)");
146
1
    assert_eq!(
147
1
        state.history.last().unwrap(),
148
1
        &format!("(f{})", MAX_HISTORY_ENTRIES + 4)
149
    );
150
1
    state.history_prev();
151
1
    assert_eq!(
152
1
        state.input.buffer(),
153
1
        format!("(f{})", MAX_HISTORY_ENTRIES + 4)
154
    );
155
1
}
156

            
157
#[test]
158
1
fn format_result_splits_lines_verbatim() {
159
1
    assert_eq!(
160
1
        format_result("(:id 1 :value 2)"),
161
1
        vec!["(:id 1 :value 2)".to_string()]
162
    );
163
1
    assert_eq!(
164
1
        format_result("line one\nline two"),
165
1
        vec!["line one".to_string(), "line two".to_string()]
166
    );
167
1
}
168

            
169
#[test]
170
1
fn push_scrollback_caps_at_max_dropping_oldest() {
171
1
    let mut state = console();
172
1005
    for i in 0..(MAX_SCROLLBACK_LINES + 5) {
173
1005
        state.push_scrollback(format!("line {i}"));
174
1005
    }
175
1
    assert_eq!(state.scrollback.len(), MAX_SCROLLBACK_LINES);
176
1
    assert_eq!(state.scrollback.first().unwrap(), "line 5");
177
1
    assert_eq!(
178
1
        state.scrollback.last().unwrap(),
179
1
        &format!("line {}", MAX_SCROLLBACK_LINES + 4)
180
    );
181
1
}