test: the TUI cursor stays drawn beside a side panel and on the tile bar (improvise-gtn7.1)
Both fail on gh/main: the grid at column 4 with any side panel open, the tile bar at width 42. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
+78
@@ -1120,3 +1120,81 @@ mod title_bar_tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod content_tests {
|
||||
use super::{draw, press};
|
||||
use crate::command::key::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use crate::model::cell::{CellKey, CellValue};
|
||||
use crate::ui::app::App;
|
||||
use crate::view::Axis;
|
||||
use crate::workbook::Workbook;
|
||||
use ratatui::{Terminal, backend::TestBackend, style::Color};
|
||||
|
||||
const COLS: usize = 12;
|
||||
|
||||
/// One row, twelve columns, and a value per column that names it.
|
||||
fn wide_grid() -> Workbook {
|
||||
let mut wb = Workbook::new("T");
|
||||
wb.add_category("Row").unwrap();
|
||||
wb.add_category("Col").unwrap();
|
||||
wb.add_item("Row", "R1").unwrap();
|
||||
for i in 0..COLS {
|
||||
let col = format!("Column_{i:02}");
|
||||
wb.add_item("Col", &col).unwrap();
|
||||
let key = CellKey::new(vec![("Row".into(), "R1".into()), ("Col".into(), col)]);
|
||||
wb.model.set_cell(key, CellValue::Number((101 + i) as f64));
|
||||
}
|
||||
wb.active_view_mut().set_axis("Row", Axis::Row);
|
||||
wb.active_view_mut().set_axis("Col", Axis::Column);
|
||||
wb
|
||||
}
|
||||
|
||||
/// The text the whole frame draws in the selected cell's style.
|
||||
fn selected_text(app: &App) -> String {
|
||||
let (w, h) = (app.term_width, app.term_height);
|
||||
let mut terminal = Terminal::new(TestBackend::new(w, h)).expect("test backend");
|
||||
terminal.draw(|f| draw(f, app)).expect("draw");
|
||||
terminal
|
||||
.backend()
|
||||
.buffer()
|
||||
.content()
|
||||
.iter()
|
||||
.filter(|c| c.bg == Color::Cyan && c.fg == Color::Black)
|
||||
.map(|c| c.symbol())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// improvise-gtn7.1: the cursor went behind a side panel —
|
||||
/// `context/test-evidence/tui.md`.
|
||||
#[test]
|
||||
fn moving_right_keeps_the_selected_cell_drawn_beside_any_side_panel() {
|
||||
let panels: [(&str, fn(&mut App)); 4] = [
|
||||
("no", |_| {}),
|
||||
("formula", |a| a.view_state.formula_panel_open = true),
|
||||
("category", |a| a.view_state.category_panel_open = true),
|
||||
("view", |a| a.view_state.view_panel_open = true),
|
||||
];
|
||||
for (panel, open) in panels {
|
||||
let mut app = App::new(wide_grid(), None);
|
||||
(app.term_width, app.term_height) = (80, 24);
|
||||
// The category panel is open at launch; close all three first.
|
||||
let vs = &mut app.view_state;
|
||||
(vs.formula_panel_open, vs.category_panel_open, vs.view_panel_open) =
|
||||
(false, false, false);
|
||||
open(&mut app);
|
||||
for step in 1..COLS {
|
||||
press(&mut app, KeyEvent::new(KeyCode::Right, KeyModifiers::NONE)).unwrap();
|
||||
let col = app.cursor().selected.1;
|
||||
assert_eq!(col, step, "setup: {panel} panel, the cursor moved");
|
||||
let drawn = selected_text(&app);
|
||||
assert!(
|
||||
drawn.contains(&(101 + col).to_string()),
|
||||
"{panel} panel: column {col} is selected (offset {}) but not \
|
||||
drawn; the selection drew {drawn:?}",
|
||||
app.cursor().col_offset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,38 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// improvise-gtn7.1: the tile cursor could scroll off the bar —
|
||||
/// `context/test-evidence/tui.md`.
|
||||
#[test]
|
||||
fn the_selected_tile_is_drawn_at_every_width_it_fits_in() {
|
||||
let mut wb = Workbook::new("Test");
|
||||
for i in 0..8 {
|
||||
wb.add_category(&format!("Category_{i}")).unwrap();
|
||||
}
|
||||
let app = App::new(wb, None);
|
||||
let cache = project::tile_bar_of(&app);
|
||||
let names: Vec<&str> = cache.tiles.iter().map(|t| t.category.as_str()).collect();
|
||||
assert!(names.len() > 8, "setup: more tiles than any tested width holds");
|
||||
for width in 40u16..=200 {
|
||||
for (sel, name) in names.iter().enumerate() {
|
||||
let area = Rect::new(0, 0, width, 1);
|
||||
let mut buf = Buffer::empty(area);
|
||||
TileBar::new(&cache, &AppMode::TileSelect, sel).render(area, &mut buf);
|
||||
let highlighted: String = buf
|
||||
.content()
|
||||
.iter()
|
||||
.filter(|c| c.bg == Color::Cyan)
|
||||
.map(|c| c.symbol())
|
||||
.collect();
|
||||
assert!(
|
||||
highlighted.contains(&format!("[{name} ")),
|
||||
"width {width}: tile {sel} ({name}) is selected but not drawn: {:?}",
|
||||
buf_text(&buf)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The tiles themselves are what the bar is for, and deleting the hint must
|
||||
/// not delete them. improvise-rr8n.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user