-
Notifications
You must be signed in to change notification settings - Fork 17
Add test for some movements #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<bool> | |
| Ok(false) | ||
| } | ||
|
|
||
| pub fn handle_events(app: &mut App) -> Result<bool> { | ||
| let event = event::read()?; | ||
| pub fn handle_events(app: &mut App, event: Event) -> Result<bool> { | ||
| 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<bool> { | |
| } | ||
| 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), | ||
|
Comment on lines
+88
to
+91
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eu costumo gostar de estruturar os testes assim: uma lista de casos e um for loop testando todos. Eu acho que ajuda a deixar mais facil de adicionar mais casos parecidos depois. Mas tem gente que prefere um teste separado por caso, nao sei o que voce prefere 🤷
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bem legal essa abordagem. Nunca tinha visto, mas gostei. Bem mais rápido para escrever novos testes! :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. muito bom mesmo, eu faço isso em python com pytest.mark.parametrize, fica bem legal para ampliar a cobertura no longo prazo. Apesar disso não ser suportado nativamente por Rust, também dá pra ter um cenário parecido usando isso |
||
| ("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"); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ mod widgets; | |
| use std::process; | ||
|
|
||
| use clap::Parser; | ||
| use ratatui::crossterm::event; | ||
|
|
||
| use app::App; | ||
|
|
||
|
|
@@ -60,33 +61,37 @@ fn main() { | |
| 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) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extrai como funcao, pq sem rodar isso o page_end e current_size ficam setados em zero e da problema no teste. Acho que o ideal seria o |
||
| // 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 { | ||
| () => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Not really a binary | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Um arquivo qualquer de teste. talvez de para nao ter ele e gerar um arquivo on the fly |
||
| just some dummy data | ||
| to write tests against | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Essa eh a principal mudanca que permite rodar esse teste sem um terminal