Selected item is always at the bottom of list #41

Merged
wojtek merged 7 commits from 40---selected-item-is-always-at-the-bottom-of-list into main 2023-04-27 19:05:37 +02:00
3 changed files with 563 additions and 634 deletions
Showing only changes of commit 9d73a37f1a - Show all commits

View File

@ -1,484 +0,0 @@
// #[cfg(test)]
// mod tests {
// use crate::tests::{MockCollectionManager, COLLECTION};
// use super::*;
// #[test]
// fn test_track_selection() {
// let tracks = &COLLECTION[0].albums[0].tracks;
// assert!(tracks.len() > 1);
// let empty = SelectedTrack::initialise(&vec![]);
// assert!(empty.is_none());
// let sel = SelectedTrack::initialise(tracks);
// assert!(sel.is_some());
// let mut sel = sel.unwrap();
// assert_eq!(sel.index, 0);
// sel.decrement(tracks);
// assert_eq!(sel.index, 0);
// sel.increment(tracks);
// assert_eq!(sel.index, 1);
// sel.decrement(tracks);
// assert_eq!(sel.index, 0);
// for _ in 0..(tracks.len() + 5) {
// sel.increment(tracks);
// }
// assert_eq!(sel.index, tracks.len() - 1);
// // Artifical test case to verify upper limit.
// let mut sel = SelectedTrack {
// index: std::usize::MAX,
// };
// assert_eq!(sel.index, std::usize::MAX);
// sel.increment(&vec![]);
// assert_eq!(sel.index, std::usize::MAX);
// }
// #[test]
// fn test_album_selection() {
// let albums = &COLLECTION[0].albums;
// assert!(albums.len() > 1);
// let empty = SelectedAlbum::initialise(&vec![]);
// assert!(empty.is_none());
// let sel = SelectedAlbum::initialise(albums);
// assert!(sel.is_some());
// let mut sel = sel.unwrap();
// assert_eq!(sel.index, 0);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 0);
// sel.track
// .as_mut()
// .unwrap()
// .increment(&albums[sel.index].tracks);
// assert_eq!(sel.index, 0);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// // Verify that decrement that doesn't change index does not reset track.
// sel.decrement(albums);
// assert_eq!(sel.index, 0);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// sel.increment(albums);
// assert_eq!(sel.index, 1);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 0);
// sel.decrement(albums);
// assert_eq!(sel.index, 0);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 0);
// for _ in 0..(albums.len() + 5) {
// sel.increment(albums);
// }
// assert_eq!(sel.index, albums.len() - 1);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 0);
// sel.track
// .as_mut()
// .unwrap()
// .increment(&albums[sel.index].tracks);
// assert_eq!(sel.index, albums.len() - 1);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// // Verify that increment that doesn't change index does not reset track.
// sel.increment(albums);
// assert_eq!(sel.index, albums.len() - 1);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// // Artifical test case to verify upper limit.
// let mut sel = SelectedAlbum {
// index: std::usize::MAX,
// track: Some(SelectedTrack { index: 1 }),
// };
// assert_eq!(sel.index, std::usize::MAX);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// sel.increment(&vec![]);
// assert_eq!(sel.index, std::usize::MAX);
// assert!(sel.track.is_some());
// assert_eq!(sel.track.as_ref().unwrap().index, 1);
// }
// #[test]
// fn test_artist_selection() {
// let artists = &COLLECTION;
// assert!(artists.len() > 1);
// let empty = SelectedArtist::initialise(&vec![]);
// assert!(empty.is_none());
// let sel = SelectedArtist::initialise(artists);
// assert!(sel.is_some());
// let mut sel = sel.unwrap();
// assert_eq!(sel.index, 0);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 0);
// sel.album
// .as_mut()
// .unwrap()
// .increment(&artists[sel.index].albums);
// assert_eq!(sel.index, 0);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// // Verify that decrement that doesn't change index does not reset album.
// sel.decrement(artists);
// assert_eq!(sel.index, 0);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// sel.increment(artists);
// assert_eq!(sel.index, 1);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 0);
// sel.decrement(artists);
// assert_eq!(sel.index, 0);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 0);
// for _ in 0..(artists.len() + 5) {
// sel.increment(artists);
// }
// assert_eq!(sel.index, artists.len() - 1);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 0);
// sel.album
// .as_mut()
// .unwrap()
// .increment(&artists[sel.index].albums);
// assert_eq!(sel.index, artists.len() - 1);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// // Verify that increment that doesn't change index does not reset album.
// sel.increment(artists);
// assert_eq!(sel.index, artists.len() - 1);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// // Artifical test case to verify upper limit.
// let mut sel = SelectedArtist {
// index: std::usize::MAX,
// album: Some(SelectedAlbum {
// index: 1,
// track: None,
// }),
// };
// assert_eq!(sel.index, std::usize::MAX);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// sel.increment(&vec![]);
// assert_eq!(sel.index, std::usize::MAX);
// assert!(sel.album.is_some());
// assert_eq!(sel.album.as_ref().unwrap().index, 1);
// }
// #[test]
// fn app_running() {
// let mut collection_manager = MockCollectionManager::new();
// collection_manager
// .expect_rescan_library()
// .times(1)
// .return_once(|| Ok(()));
// collection_manager
// .expect_get_collection()
// .return_const(COLLECTION.to_owned());
// let mut app = TuiApp::new(collection_manager).unwrap();
// assert!(app.is_running());
// app.quit();
// assert!(!app.is_running());
// }
// #[test]
// fn app_modifiers() {
// let mut collection_manager = MockCollectionManager::new();
// collection_manager
// .expect_rescan_library()
// .times(1)
// .return_once(|| Ok(()));
// collection_manager
// .expect_get_collection()
// .return_const(COLLECTION.to_owned());
// let mut app = TuiApp::new(collection_manager).unwrap();
// assert!(app.is_running());
// assert!(!app.get_artist_ids().is_empty());
// assert!(!app.get_album_ids().is_empty());
// assert!(!app.get_track_ids().is_empty());
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_category();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_category();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(1));
// app.increment_category();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(1));
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_selection();
// app.decrement_category();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(1));
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_selection();
// app.decrement_category();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(1));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(0));
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), Some(0));
// app.increment_category();
// app.increment_selection();
// app.decrement_category();
// app.decrement_selection();
// app.decrement_category();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(1));
// assert_eq!(app.selected_track(), Some(0));
// }
// #[test]
// fn app_no_tracks() {
// let mut collection_manager = MockCollectionManager::new();
// let mut collection = COLLECTION.to_owned();
// collection[0].albums[0].tracks = vec![];
// collection_manager
// .expect_rescan_library()
// .times(1)
// .return_once(|| Ok(()));
// collection_manager
// .expect_get_collection()
// .return_const(collection);
// let mut app = TuiApp::new(collection_manager).unwrap();
// assert!(app.is_running());
// assert!(!app.get_artist_ids().is_empty());
// assert!(!app.get_album_ids().is_empty());
// assert!(app.get_track_ids().is_empty());
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), None);
// app.increment_category();
// app.increment_category();
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), Some(0));
// assert_eq!(app.selected_track(), None);
// }
// #[test]
// fn app_no_albums() {
// let mut collection_manager = MockCollectionManager::new();
// let mut collection = COLLECTION.to_owned();
// collection[0].albums = vec![];
// collection_manager
// .expect_rescan_library()
// .times(1)
// .return_once(|| Ok(()));
// collection_manager
// .expect_get_collection()
// .return_const(collection);
// let mut app = TuiApp::new(collection_manager).unwrap();
// assert!(app.is_running());
// assert!(!app.get_artist_ids().is_empty());
// assert!(app.get_album_ids().is_empty());
// assert!(app.get_track_ids().is_empty());
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.increment_category();
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.increment_category();
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), Some(0));
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// }
// #[test]
// fn app_no_artists() {
// let mut collection_manager = MockCollectionManager::new();
// let collection = vec![];
// collection_manager
// .expect_rescan_library()
// .times(1)
// .return_once(|| Ok(()));
// collection_manager
// .expect_get_collection()
// .return_const(collection);
// let mut app = TuiApp::new(collection_manager).unwrap();
// assert!(app.is_running());
// assert!(app.get_artist_ids().is_empty());
// assert!(app.get_album_ids().is_empty());
// assert!(app.get_track_ids().is_empty());
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Artist);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.increment_category();
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Album);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.increment_category();
// app.increment_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// app.decrement_selection();
// assert_eq!(app.get_active_category(), Category::Track);
// assert_eq!(app.selected_artist(), None);
// assert_eq!(app.selected_album(), None);
// assert_eq!(app.selected_track(), None);
// }
// }

View File

@ -156,151 +156,150 @@ impl<B: Backend, UI: Ui> Tui<B, UI> {
// GRCOV_EXCL_STOP // GRCOV_EXCL_STOP
} }
// #[cfg(test)] #[cfg(test)]
// mod tests { mod tests {
// use std::{io, thread}; use std::{io, thread};
// use musichoard::collection::{self, Collection}; use musichoard::collection::{self, Collection};
// use ratatui::{backend::TestBackend, Terminal}; use ratatui::{backend::TestBackend, Terminal};
// use crate::tests::{MockCollectionManager, COLLECTION}; use crate::tests::{MockCollectionManager, COLLECTION};
// use super::{ use super::{
// app::TuiApp, event::EventError, handler::MockEventHandler, listener::MockEventListener, event::EventError,
// ui::Ui, Error, Tui, handler::MockEventHandler,
// }; listener::MockEventListener,
ui::{MhUi, Ui},
Error, Tui,
};
// pub fn terminal() -> Terminal<TestBackend> { pub fn terminal() -> Terminal<TestBackend> {
// let backend = TestBackend::new(150, 30); let backend = TestBackend::new(150, 30);
// Terminal::new(backend).unwrap() Terminal::new(backend).unwrap()
// } }
// pub fn app(collection: Collection) -> TuiApp<MockCollectionManager> { pub fn app(collection: Collection) -> MhUi<MockCollectionManager> {
// let mut collection_manager = MockCollectionManager::new(); let mut collection_manager = MockCollectionManager::new();
// collection_manager collection_manager
// .expect_rescan_library() .expect_rescan_library()
// .returning(|| Ok(())); .returning(|| Ok(()));
// collection_manager collection_manager
// .expect_get_collection() .expect_get_collection()
// .return_const(collection); .return_const(collection);
// TuiApp::new(collection_manager).unwrap() MhUi::new(collection_manager).unwrap()
// } }
// fn listener() -> MockEventListener { fn listener() -> MockEventListener {
// let mut listener = MockEventListener::new(); let mut listener = MockEventListener::new();
// listener.expect_spawn().return_once(|| { listener.expect_spawn().return_once(|| {
// thread::spawn(|| { thread::spawn(|| {
// thread::park(); thread::park();
// return EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "unparked")); return EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "unparked"));
// }) })
// }); });
// listener listener
// } }
// fn handler() -> MockEventHandler<TuiApp<MockCollectionManager>> { fn handler() -> MockEventHandler<MhUi<MockCollectionManager>> {
// let mut handler = MockEventHandler::new(); let mut handler = MockEventHandler::new();
// handler.expect_handle_next_event().return_once( handler
// |app: &mut TuiApp<MockCollectionManager>| { .expect_handle_next_event()
// app.quit(); .return_once(|app: &mut MhUi<MockCollectionManager>| {
// Ok(()) app.quit();
// }, Ok(())
// ); });
// handler handler
// } }
// #[test] #[test]
// fn run() { fn run() {
// let terminal = terminal(); let terminal = terminal();
// let app = app(COLLECTION.to_owned()); let app = app(COLLECTION.to_owned());
// let ui = Ui::new();
// let listener = listener(); let listener = listener();
// let handler = handler(); let handler = handler();
// let result = Tui::main(terminal, app, ui, handler, listener); let result = Tui::main(terminal, app, handler, listener);
// assert!(result.is_ok()); assert!(result.is_ok());
// } }
// #[test] #[test]
// fn event_error() { fn event_error() {
// let terminal = terminal(); let terminal = terminal();
// let app = app(COLLECTION.to_owned()); let app = app(COLLECTION.to_owned());
// let ui = Ui::new();
// let listener = listener(); let listener = listener();
// let mut handler = MockEventHandler::new(); let mut handler = MockEventHandler::new();
// handler handler
// .expect_handle_next_event() .expect_handle_next_event()
// .return_once(|_| Err(EventError::Recv)); .return_once(|_| Err(EventError::Recv));
// let result = Tui::main(terminal, app, ui, handler, listener); let result = Tui::main(terminal, app, handler, listener);
// assert!(result.is_err()); assert!(result.is_err());
// assert_eq!( assert_eq!(
// result.unwrap_err(), result.unwrap_err(),
// Error::Event(EventError::Recv.to_string()) Error::Event(EventError::Recv.to_string())
// ); );
// } }
// #[test] #[test]
// fn listener_error() { fn listener_error() {
// let terminal = terminal(); let terminal = terminal();
// let app = app(COLLECTION.to_owned()); let app = app(COLLECTION.to_owned());
// let ui = Ui::new();
// let error = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "error")); let error = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "error"));
// let listener_handle: thread::JoinHandle<EventError> = thread::spawn(|| error); let listener_handle: thread::JoinHandle<EventError> = thread::spawn(|| error);
// while !listener_handle.is_finished() {} while !listener_handle.is_finished() {}
// let mut listener = MockEventListener::new(); let mut listener = MockEventListener::new();
// listener.expect_spawn().return_once(|| listener_handle); listener.expect_spawn().return_once(|| listener_handle);
// let mut handler = MockEventHandler::new(); let mut handler = MockEventHandler::new();
// handler handler
// .expect_handle_next_event() .expect_handle_next_event()
// .return_once(|_| Err(EventError::Recv)); .return_once(|_| Err(EventError::Recv));
// let result = Tui::main(terminal, app, ui, handler, listener); let result = Tui::main(terminal, app, handler, listener);
// assert!(result.is_err()); assert!(result.is_err());
// let error = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "error")); let error = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "error"));
// assert_eq!(result.unwrap_err(), Error::Event(error.to_string())); assert_eq!(result.unwrap_err(), Error::Event(error.to_string()));
// } }
// #[test] #[test]
// fn listener_panic() { fn listener_panic() {
// let terminal = terminal(); let terminal = terminal();
// let app = app(COLLECTION.to_owned()); let app = app(COLLECTION.to_owned());
// let ui = Ui::new();
// let listener_handle: thread::JoinHandle<EventError> = thread::spawn(|| panic!()); let listener_handle: thread::JoinHandle<EventError> = thread::spawn(|| panic!());
// while !listener_handle.is_finished() {} while !listener_handle.is_finished() {}
// let mut listener = MockEventListener::new(); let mut listener = MockEventListener::new();
// listener.expect_spawn().return_once(|| listener_handle); listener.expect_spawn().return_once(|| listener_handle);
// let mut handler = MockEventHandler::new(); let mut handler = MockEventHandler::new();
// handler handler
// .expect_handle_next_event() .expect_handle_next_event()
// .return_once(|_| Err(EventError::Recv)); .return_once(|_| Err(EventError::Recv));
// let result = Tui::main(terminal, app, ui, handler, listener); let result = Tui::main(terminal, app, handler, listener);
// assert!(result.is_err()); assert!(result.is_err());
// assert_eq!(result.unwrap_err(), Error::ListenerPanic); assert_eq!(result.unwrap_err(), Error::ListenerPanic);
// } }
// #[test] #[test]
// fn errors() { fn errors() {
// let collection_err: Error = collection::Error::DatabaseError(String::from("")).into(); let collection_err: Error = collection::Error::DatabaseError(String::from("")).into();
// let io_err: Error = io::Error::new(io::ErrorKind::Interrupted, "error").into(); let io_err: Error = io::Error::new(io::ErrorKind::Interrupted, "error").into();
// let event_err: Error = EventError::Recv.into(); let event_err: Error = EventError::Recv.into();
// let listener_err = Error::ListenerPanic; let listener_err = Error::ListenerPanic;
// assert!(!format!("{:?}", collection_err).is_empty()); assert!(!format!("{:?}", collection_err).is_empty());
// assert!(!format!("{:?}", io_err).is_empty()); assert!(!format!("{:?}", io_err).is_empty());
// assert!(!format!("{:?}", event_err).is_empty()); assert!(!format!("{:?}", event_err).is_empty());
// assert!(!format!("{:?}", listener_err).is_empty()); assert!(!format!("{:?}", listener_err).is_empty());
// } }
// } }

View File

@ -598,42 +598,456 @@ impl<CM: CollectionManager> Ui for MhUi<CM> {
} }
} }
// #[cfg(test)] #[cfg(test)]
// mod tests { mod tests {
// // This is UI so the only sensible unit test is to run the code through various app states. use crate::tests::{MockCollectionManager, COLLECTION};
use crate::tui::tests::{app, terminal};
// use crate::{ use super::*;
// tests::COLLECTION,
// tui::{
// app::App,
// tests::{app, terminal},
// },
// };
// use super::Ui; #[test]
fn test_track_selection() {
let tracks = &COLLECTION[0].albums[0].tracks;
assert!(tracks.len() > 1);
// #[test] let empty = TrackSelection::initialise(None);
// fn empty() { assert_eq!(empty.state.selected(), None);
// let mut terminal = terminal();
// let app = app(vec![]);
// let ui = Ui::new();
// terminal.draw(|frame| ui.render(&app, frame)).unwrap(); let empty = TrackSelection::initialise(Some(&vec![]));
// } assert_eq!(empty.state.selected(), None);
// #[test] let mut sel = TrackSelection::initialise(Some(tracks));
// fn collection() { assert_eq!(sel.state.selected(), Some(0));
// let mut terminal = terminal();
// let mut app = app(COLLECTION.to_owned());
// let ui = Ui::new();
// terminal.draw(|frame| ui.render(&app, frame)).unwrap(); sel.decrement(tracks);
assert_eq!(sel.state.selected(), Some(0));
// // Change the track (which has a different track format). sel.increment(tracks);
// app.increment_category(); assert_eq!(sel.state.selected(), Some(1));
// app.increment_category();
// app.increment_selection();
// terminal.draw(|frame| ui.render(&app, frame)).unwrap(); sel.decrement(tracks);
// } assert_eq!(sel.state.selected(), Some(0));
// }
for _ in 0..(tracks.len() + 5) {
sel.increment(tracks);
}
assert_eq!(sel.state.selected(), Some(tracks.len() - 1));
// Artifical test case to verify upper limit.
sel.state.select(Some(std::usize::MAX));
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
sel.increment(&vec![]);
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
}
#[test]
fn test_album_selection() {
let albums = &COLLECTION[0].albums;
assert!(albums.len() > 1);
let empty = AlbumSelection::initialise(None);
assert_eq!(empty.state.selected(), None);
let empty = AlbumSelection::initialise(Some(&vec![]));
assert_eq!(empty.state.selected(), None);
let mut sel = AlbumSelection::initialise(Some(albums));
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.track.state.selected(), Some(0));
sel.increment_track(albums);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.track.state.selected(), Some(1));
// Verify that decrement that doesn't change index does not reset track.
sel.decrement(albums);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.track.state.selected(), Some(1));
sel.increment(albums);
assert_eq!(sel.state.selected(), Some(1));
assert_eq!(sel.track.state.selected(), Some(0));
sel.decrement(albums);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.track.state.selected(), Some(0));
for _ in 0..(albums.len() + 5) {
sel.increment(albums);
}
assert_eq!(sel.state.selected(), Some(albums.len() - 1));
assert_eq!(sel.track.state.selected(), Some(0));
sel.increment_track(albums);
assert_eq!(sel.state.selected(), Some(albums.len() - 1));
assert_eq!(sel.track.state.selected(), Some(1));
// Verify that increment that doesn't change index does not reset track.
sel.increment(albums);
assert_eq!(sel.state.selected(), Some(albums.len() - 1));
assert_eq!(sel.track.state.selected(), Some(1));
// Artifical test case to verify upper limit.
sel.state.select(Some(std::usize::MAX));
sel.track.state.select(Some(1));
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
assert_eq!(sel.track.state.selected(), Some(1));
sel.increment(&vec![]);
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
assert_eq!(sel.track.state.selected(), Some(1));
}
#[test]
fn test_artist_selection() {
let artists = &COLLECTION;
assert!(artists.len() > 1);
let empty = ArtistSelection::initialise(None);
assert_eq!(empty.state.selected(), None);
let empty = ArtistSelection::initialise(Some(&vec![]));
assert_eq!(empty.state.selected(), None);
let mut sel = ArtistSelection::initialise(Some(artists));
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.album.state.selected(), Some(0));
sel.increment_album(artists);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.album.state.selected(), Some(1));
// Verify that decrement that doesn't change index does not reset album.
sel.decrement(artists);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.album.state.selected(), Some(1));
sel.increment(artists);
assert_eq!(sel.state.selected(), Some(1));
assert_eq!(sel.album.state.selected(), Some(0));
sel.decrement(artists);
assert_eq!(sel.state.selected(), Some(0));
assert_eq!(sel.album.state.selected(), Some(0));
for _ in 0..(artists.len() + 5) {
sel.increment(artists);
}
assert_eq!(sel.state.selected(), Some(artists.len() - 1));
assert_eq!(sel.album.state.selected(), Some(0));
sel.increment_album(artists);
assert_eq!(sel.state.selected(), Some(artists.len() - 1));
assert_eq!(sel.album.state.selected(), Some(1));
// Verify that increment that doesn't change index does not reset album.
sel.increment(artists);
assert_eq!(sel.state.selected(), Some(artists.len() - 1));
assert_eq!(sel.album.state.selected(), Some(1));
// Artifical test case to verify upper limit.
sel.state.select(Some(std::usize::MAX));
sel.album.state.select(Some(1));
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
assert_eq!(sel.album.state.selected(), Some(1));
sel.increment(&vec![]);
assert_eq!(sel.state.selected(), Some(std::usize::MAX));
assert_eq!(sel.album.state.selected(), Some(1));
}
#[test]
fn app_running() {
let mut collection_manager = MockCollectionManager::new();
collection_manager
.expect_rescan_library()
.times(1)
.return_once(|| Ok(()));
collection_manager
.expect_get_collection()
.return_const(COLLECTION.to_owned());
let mut app = MhUi::new(collection_manager).unwrap();
assert!(app.is_running());
app.quit();
assert!(!app.is_running());
}
#[test]
fn app_modifiers() {
let mut collection_manager = MockCollectionManager::new();
collection_manager
.expect_rescan_library()
.times(1)
.return_once(|| Ok(()));
collection_manager
.expect_get_collection()
.return_const(COLLECTION.to_owned());
let mut app = MhUi::new(collection_manager).unwrap();
assert!(app.is_running());
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_selection();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_category();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_category();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(1));
app.increment_category();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(1));
app.decrement_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_selection();
app.decrement_category();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(1));
app.decrement_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_selection();
app.decrement_category();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.decrement_selection();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
app.increment_category();
app.increment_selection();
app.decrement_category();
app.decrement_selection();
app.decrement_category();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(1));
assert_eq!(app.selection.artist.album.track.state.selected(), Some(0));
}
#[test]
fn app_no_tracks() {
let mut collection_manager = MockCollectionManager::new();
let mut collection = COLLECTION.to_owned();
collection[0].albums[0].tracks = vec![];
collection_manager
.expect_rescan_library()
.times(1)
.return_once(|| Ok(()));
collection_manager
.expect_get_collection()
.return_const(collection);
let mut app = MhUi::new(collection_manager).unwrap();
assert!(app.is_running());
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_category();
app.increment_category();
app.increment_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.track.state.selected(), None);
}
#[test]
fn app_no_albums() {
let mut collection_manager = MockCollectionManager::new();
let mut collection = COLLECTION.to_owned();
collection[0].albums = vec![];
collection_manager
.expect_rescan_library()
.times(1)
.return_once(|| Ok(()));
collection_manager
.expect_get_collection()
.return_const(collection);
let mut app = MhUi::new(collection_manager).unwrap();
assert!(app.is_running());
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_category();
app.increment_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_category();
app.increment_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), Some(0));
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
}
#[test]
fn app_no_artists() {
let mut collection_manager = MockCollectionManager::new();
let collection = vec![];
collection_manager
.expect_rescan_library()
.times(1)
.return_once(|| Ok(()));
collection_manager
.expect_get_collection()
.return_const(collection);
let mut app = MhUi::new(collection_manager).unwrap();
assert!(app.is_running());
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_selection();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Artist);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_category();
app.increment_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Album);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.increment_category();
app.increment_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
app.decrement_selection();
assert_eq!(app.selection.active, Category::Track);
assert_eq!(app.selection.artist.state.selected(), None);
assert_eq!(app.selection.artist.album.state.selected(), None);
assert_eq!(app.selection.artist.album.track.state.selected(), None);
}
// This is UI so the only sensible unit test is to run the code through various app states.
#[test]
fn empty() {
let mut terminal = terminal();
let mut app = app(vec![]);
terminal.draw(|frame| app.render(frame)).unwrap();
}
#[test]
fn collection() {
let mut terminal = terminal();
let mut app = app(COLLECTION.to_owned());
terminal.draw(|frame| app.render(frame)).unwrap();
// Change the track (which has a different track format).
app.increment_category();
app.increment_category();
app.increment_selection();
terminal.draw(|frame| app.render(frame)).unwrap();
}
}