From b0e8299ff42eb17d6709f0d92c5ace47a6e3869d Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Sat, 3 Feb 2024 02:31:08 -0500 Subject: [PATCH] Unit test for tab::Message::Location * Implement a working unit test for `tab::Message::Location` * Add more helper test functions and improve existing logic --- src/app.rs | 57 ++++++++++++++++++++++++++++++++++++ src/tab.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 138 insertions(+), 4 deletions(-) diff --git a/src/app.rs b/src/app.rs index 9893f7e..bb962ed 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1187,6 +1187,17 @@ pub(crate) mod test_utils { } } + /// Read directory entries from `path` and sort. + pub fn read_dir_sorted(path: &Path) -> io::Result> { + let mut entries: Vec<_> = path + .read_dir()? + .map(|maybe_entry| maybe_entry.map(|entry| entry.path())) + .collect::>()?; + entries.sort_by(|a, b| sort_files(a, b)); + + Ok(entries) + } + /// Equality for [Path] and [Item]. pub fn eq_path_item(path: &Path, item: &Item) -> bool { let name = path @@ -1214,4 +1225,50 @@ pub(crate) mod test_utils { && path == item.path && is_hidden == item.hidden } + + /// Asserts `tab`'s location changed to `path` + pub fn assert_eq_tab_path(tab: &Tab, path: &Path) { + // Paths should be the same + let Location::Path(ref tab_path) = tab.location else { + panic!("Expected tab's location to be a path"); + }; + + assert_eq!( + path, + tab_path, + "Tab's path is {} instead of being updated to {}", + tab_path.display(), + path.display() + ); + } + + /// Assert that tab's items are equal to a path's entries. + pub fn assert_eq_tab_path_contents(tab: &Tab, path: &Path) { + let Location::Path(ref tab_path) = tab.location else { + panic!("Expected tab's location to be a path"); + }; + + // Tab items are sorted so paths from read_dir must be too + let entries = read_dir_sorted(path).expect("should be able to read paths from temp dir"); + + // Check lengths. + // `items_opt` is optional and the directory at `path` may have zero entries + // Therefore, this doesn't panic if `items_opt` is None + let items_len = tab + .items_opt + .as_ref() + .map(|items| items.len()) + .unwrap_or_default(); + assert_eq!(entries.len(), items_len); + + assert!( + entries + .into_iter() + .zip(tab.items_opt.clone().unwrap_or_default()) + .all(|(a, b)| eq_path_item(&a, &b)), + "Path ({}) and Tab path ({}) don't have equal contents", + path.display(), + tab_path.display() + ); + } } diff --git a/src/tab.rs b/src/tab.rs index 31fb312..749f001 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -1038,13 +1038,14 @@ impl Tab { mod tests { use std::io; + use cosmic::iced_runtime::keyboard::Modifiers; use log::debug; use test_log::test; - use super::scan_path; + use super::{scan_path, Item, Location, Message, Tab}; use crate::app::test_utils::{ - empty_fs, eq_path_item, simple_fs, sort_files, NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, - NUM_NESTED, + assert_eq_tab_path, assert_eq_tab_path_contents, empty_fs, eq_path_item, simple_fs, + sort_files, NAME_LEN, NUM_DIRS, NUM_FILES, NUM_HIDDEN, NUM_NESTED, }; #[test] @@ -1099,8 +1100,84 @@ mod tests { let actual = scan_path(&path.to_owned()); assert_eq!(0, path.read_dir()?.count()); - assert_eq!(0, actual.len()); + assert!(actual.is_empty()); Ok(()) } + + #[test] + fn tab_location_changes_location() -> io::Result<()> { + let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?; + let path = fs.path(); + + // Next directory in temp directory + let next_dir = path + .read_dir()? + .filter_map(|entry| { + entry.ok().and_then(|entry| { + let path = entry.path(); + if path.is_dir() { + Some(path) + } else { + None + } + }) + }) + .next() + .expect("temp directory should have at least one directory"); + + let mut tab = Tab::new(Location::Path(path.to_owned())); + debug!( + "Emitting Message::Location(Location::Path(\"{}\"))", + next_dir.display() + ); + tab.update( + Message::Location(Location::Path(next_dir.clone())), + Modifiers::empty(), + ); + + // Validate that the tab's path updated + // NOTE: `items_opt` is set to None with Message::Location so this ONLY checks for equal paths + // If item contents are NOT None then this needs to be reevaluated for correctness + assert_eq_tab_path(&tab, &next_dir); + assert!( + tab.items_opt.is_none(), + "Tab's `items` is not None which means this test needs to be updated" + ); + + Ok(()) + } + + #[test] + fn tab_click_single_selects_item() -> io::Result<()> { + let fs = simple_fs(NUM_FILES, NUM_NESTED, NUM_DIRS, NUM_NESTED, NAME_LEN)?; + let path = fs.path(); + + todo!() + } + + #[test] + fn tab_click_double_opens_folder() -> io::Result<()> { + unimplemented!() + } + + #[test] + fn tab_click_ctrl_selects_multiple() -> io::Result<()> { + unimplemented!() + } + + #[test] + fn tab_gonext_moves_forward_in_history() -> io::Result<()> { + unimplemented!() + } + + #[test] + fn tab_goprev_moves_backward_in_history() -> io::Result<()> { + unimplemented!() + } + + #[test] + fn tab_empty_history_does_nothing_on_prev_next() -> io::Result<()> { + unimplemented!() + } }