From 4e9ecc11989f3dc50a59970266da764cbfdf9153 Mon Sep 17 00:00:00 2001 From: Guilherme Lazari Date: Wed, 12 Aug 2026 16:56:14 -0300 Subject: [PATCH 1/2] Add test for some movements --- src/events.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 40 ++++++++++++++----------- test_data/test.bin | 3 ++ 3 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 test_data/test.bin diff --git a/src/events.rs b/src/events.rs index c39845d..ae907b6 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,4 +1,4 @@ -use ratatui::crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind}; +use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; use std::io::Result; use crate::app::App; @@ -19,8 +19,7 @@ pub fn handle_dialog_error_events(app: &mut App, key: KeyEvent) -> Result Ok(false) } -pub fn handle_events(app: &mut App) -> Result { - let event = event::read()?; +pub fn handle_events(app: &mut App, event: Event) -> Result { match event { Event::Key(key) if key.kind == KeyEventKind::Press => { match app.state { @@ -63,3 +62,72 @@ pub fn handle_events(app: &mut App) -> Result { } Ok(false) } + +#[cfg(test)] +mod tests { + use crate::update_page_size; + + use super::*; + use ratatui::crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers}; + + fn test_app() -> App { + let mut app = App::new(); + app.load_file("test_data/test.bin", 0, false).unwrap(); + update_page_size(&mut app, 5); // set height to 2 so we can test page up/down behavior + app + } + + #[test] + fn test_normal_mode_movements() { + use KeyCode::*; + let mut app = test_app(); + let end = app.file_info.size - 1; + let line_end = app.config.hex_mode_bytes_per_line - 1; + let page_size = app.reader.page_current_size; + + // (name, initial offset, key code, (expected cursor x, expected cursor y), new_offset) + let cases = [ + // right + ("right", 0, Right, (1, 0), 1), + ("right at edge", line_end, Right, (0, 1), line_end + 1), + ("right at end", end, Right, (line_end, 1), end), + // left + ("left", 6, Left, (5, 0), 5), + ("left at zero", 0, Left, (0, 0), 0), + ("left at edge", line_end + 1, Left, (line_end, 0), line_end), + // down + ("down", 0, Down, (0, 1), line_end + 1), + ("down at edge", line_end + 1, Down, (0, 1), page_size), + ("down at end", end, Down, (15, 1), end), + // up + ("up", line_end + 3, Up, (2, 0), 2), + ("up at egde", page_size + 3, Up, (3, 0), line_end + 4), + ("up at start", 0, Up, (0, 0), 0), + // page up + ("page up", page_size + 7, PageUp, (7, 0), 7), + ( + "page up 2nd line", + page_size + line_end + 3, + PageUp, + (2, 0), // page up from 2nd line should go to first line + line_end + 3, + ), + ("page up at start", 0, PageUp, (0, 0), 0), + // page down + ("page down", 4, PageDown, (4, 1), page_size + 4), + ("page down end", end, PageDown, (15, 1), end), + ]; + + for case in cases { + let (name, initial_offset, key_code, expected_point, expected_offset) = case; + app.goto(initial_offset); // this goto is also being tested in a way + let event = Event::Key(KeyEvent::new(key_code, KeyModifiers::NONE)); + handle_events(&mut app, event).unwrap(); + + let cursor_pos = (app.hex_view.cursor.x, app.hex_view.cursor.y); + assert_eq!(cursor_pos, expected_point, "Test case '{name}' failed"); + let new_offset = app.hex_view.offset; + assert_eq!(new_offset, expected_offset, "Test case '{name}' failed"); + } + } +} diff --git a/src/main.rs b/src/main.rs index 160d322..b02368f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ mod widgets; use std::process; use clap::Parser; +use ratatui::crossterm::event; use app::App; @@ -54,39 +55,44 @@ fn main() { // read init file ignoring errors let _ = app.read_initfile(); + println!("p_start: {}, offset:", app.reader.page_start,); let mut terminal = ratatui::init(); while app.running { terminal .draw(|f| { - // Page size is dynamically calculated as: - // frame height - (command line + status line + header) * bytes per line - - // Prevent panic on underflow with small screen sizes - // Currently, we can't have them because of widgets such as Calculator, - // but we might add support for such small screen sizes in the future - let page_size = if f.area().height.checked_sub(3).is_some() { - (f.area().height - 3) as usize * app.config.hex_mode_bytes_per_line - } else { - app.config.hex_mode_bytes_per_line - }; - - if page_size != app.reader.page_current_size { - app.reader.page_current_size = page_size; - app.reader.page_end = app.reader.page_start + page_size.wrapping_sub(1); - } + update_page_size(&mut app, f.area().height); app.screen = f.area(); draw::draw(f, &mut app) }) .expect("failed to draw frame"); - events::handle_events(&mut app).expect("unable to read events"); + let event = event::read().expect("unable to read event"); + events::handle_events(&mut app, event).expect("unable to read events"); } ratatui::restore(); } +/// Page size is dynamically calculated as: +/// frame height - (command line + status line + header) * bytes per line +pub fn update_page_size(app: &mut App, height: u16) { + // Prevent panic on underflow with small screen sizes + // Currently, we can't have them because of widgets such as Calculator, + // but we might add support for such small screen sizes in the future + let page_size = if height.checked_sub(3).is_some() { + (height - 3) as usize * app.config.hex_mode_bytes_per_line + } else { + app.config.hex_mode_bytes_per_line + }; + + if page_size != app.reader.page_current_size { + app.reader.page_current_size = page_size; + app.reader.page_end = app.reader.page_start + page_size.wrapping_sub(1); + } +} + #[macro_export] macro_rules! beep { () => { diff --git a/test_data/test.bin b/test_data/test.bin new file mode 100644 index 0000000..e1b79ef --- /dev/null +++ b/test_data/test.bin @@ -0,0 +1,3 @@ +Not really a binary +just some dummy data +to write tests against From d9cf945d334d5e3566831d8f4f240b25345afe64 Mon Sep 17 00:00:00 2001 From: Guilherme Lazari Date: Thu, 13 Aug 2026 08:19:37 -0300 Subject: [PATCH 2/2] Remove stray println! --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index b02368f..fcf2872 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,6 @@ fn main() { // read init file ignoring errors let _ = app.read_initfile(); - println!("p_start: {}, offset:", app.reader.page_start,); let mut terminal = ratatui::init();