Unit test for tab::Message::Location

* Implement a working unit test for `tab::Message::Location`
* Add more helper test functions and improve existing logic
This commit is contained in:
Josh Megnauth 2024-02-03 02:31:08 -05:00 committed by Jeremy Soller
parent 5d51190169
commit b0e8299ff4
2 changed files with 138 additions and 4 deletions

View file

@ -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<Vec<PathBuf>> {
let mut entries: Vec<_> = path
.read_dir()?
.map(|maybe_entry| maybe_entry.map(|entry| entry.path()))
.collect::<io::Result<_>>()?;
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()
);
}
}

View file

@ -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!()
}
}