use sql_cli::app_state_container::AppStateContainer;
use sql_cli::buffer::{Buffer, BufferAPI};
use sql_cli::data::data_view::DataView;
use sql_cli::data::datatable::{DataColumn, DataRow, DataTable, DataValue};
use sql_cli::ui::state::state_coordinator::StateCoordinator;
use sql_cli::ui::viewport_manager::ViewportManager;
use std::cell::RefCell;
use std::sync::Arc;
fn make_table() -> DataTable {
let mut table = DataTable::new("versions");
table.add_column(DataColumn::new("project"));
table.add_column(DataColumn::new("version"));
for (p, v) in [("alpha", "1.0.0"), ("nucleus", "2.3.4"), ("beta", "9.9.9")] {
table
.add_row(DataRow::new(vec![
DataValue::String(p.to_string()),
DataValue::String(v.to_string()),
]))
.unwrap();
}
table
}
fn make_container() -> AppStateContainer {
let table = make_table();
let mut buffer = Buffer::new(1);
buffer.set_datatable(Some(Arc::new(table.clone())));
buffer.set_dataview(Some(DataView::new(Arc::new(table))));
let mut container = AppStateContainer::default();
container.buffers_mut().add_buffer(buffer);
container.buffers_mut().switch_to(0);
container.update_data_size(3, 2);
container
}
fn viewport_for(container: &AppStateContainer) -> RefCell<Option<ViewportManager>> {
RefCell::new(Some(ViewportManager::new(Arc::new(
container.get_buffer_dataview().unwrap().clone(),
))))
}
fn selected_row(container: &AppStateContainer) -> Option<usize> {
container.current_buffer().unwrap().get_selected_row()
}
#[test]
fn freshly_loaded_file_has_a_selected_row() {
let container = make_container();
assert_eq!(
selected_row(&container),
Some(0),
"yank must work immediately after loading a file, without pressing j/k first"
);
}
#[test]
fn empty_results_have_no_selected_row() {
let mut container = make_container();
let vm = viewport_for(&container);
container.set_fuzzy_filter_pattern("zzzznomatch".to_string());
let (count, _) = StateCoordinator::apply_fuzzy_filter_with_refs(&mut container, &vm);
assert_eq!(count, 0);
assert_eq!(
selected_row(&container),
None,
"with no visible rows there is genuinely nothing to yank"
);
}
#[test]
fn fuzzy_filter_to_single_row_keeps_a_selected_row() {
let mut container = make_container();
let vm = viewport_for(&container);
container.set_fuzzy_filter_pattern("nucleus".to_string());
let (count, _) = StateCoordinator::apply_fuzzy_filter_with_refs(&mut container, &vm);
assert_eq!(count, 1);
assert_eq!(selected_row(&container), Some(0));
}
#[test]
fn text_filter_to_single_row_keeps_a_selected_row() {
let mut container = make_container();
let vm = viewport_for(&container);
let count = StateCoordinator::apply_text_filter_with_refs(&mut container, &vm, "nucleus");
assert_eq!(count, 1, "text filter should narrow to the single match");
assert_eq!(
selected_row(&container),
Some(0),
"the 'f' filter must land on the first match like the fuzzy filter does"
);
}
#[test]
fn selection_is_clamped_to_the_filtered_view() {
let mut container = make_container();
let vm = viewport_for(&container);
container.set_selected_row(Some(2));
let count = StateCoordinator::apply_text_filter_with_refs(&mut container, &vm, "nucleus");
assert_eq!(count, 1);
let row = selected_row(&container).expect("one visible row means one selectable row");
let view = container.get_buffer_dataview().unwrap();
assert_eq!(view.row_count(), 1);
assert_eq!(
view.get_cell_value(row, 1),
Some("2.3.4".to_string()),
"yank must read the visible row, not a stale index"
);
}