Unit test tui/app
This commit is contained in:
parent
e0da5d20a9
commit
230f3cb893
@ -43,41 +43,51 @@ impl From<database::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CollectionManager {
|
||||||
|
/// Rescan the library and integrate any updates into the collection.
|
||||||
|
fn rescan_library(&mut self) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Save the collection state to the database.
|
||||||
|
fn save_to_database(&mut self) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Get the current collection.
|
||||||
|
fn get_collection(&self) -> &Collection;
|
||||||
|
}
|
||||||
|
|
||||||
/// The collection manager. It is responsible for pulling information from both the library and the
|
/// The collection manager. It is responsible for pulling information from both the library and the
|
||||||
/// database, ensuring its consistent and writing back any changes.
|
/// database, ensuring its consistent and writing back any changes.
|
||||||
pub struct CollectionManager {
|
pub struct MhCollectionManager {
|
||||||
library: Box<dyn Library + Send + Sync>,
|
library: Box<dyn Library + Send + Sync>,
|
||||||
database: Box<dyn Database + Send + Sync>,
|
database: Box<dyn Database + Send + Sync>,
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CollectionManager {
|
impl MhCollectionManager {
|
||||||
/// Create a new [`CollectionManager`] with the provided [`Library`] and [`Database`].
|
/// Create a new [`CollectionManager`] with the provided [`Library`] and [`Database`].
|
||||||
pub fn new(
|
pub fn new(
|
||||||
library: Box<dyn Library + Send + Sync>,
|
library: Box<dyn Library + Send + Sync>,
|
||||||
database: Box<dyn Database + Send + Sync>,
|
database: Box<dyn Database + Send + Sync>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
CollectionManager {
|
MhCollectionManager {
|
||||||
library,
|
library,
|
||||||
database,
|
database,
|
||||||
collection: vec![],
|
collection: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Rescan the library and integrate any updates into the collection.
|
impl CollectionManager for MhCollectionManager {
|
||||||
pub fn rescan_library(&mut self) -> Result<(), Error> {
|
fn rescan_library(&mut self) -> Result<(), Error> {
|
||||||
self.collection = self.library.list(&Query::default())?;
|
self.collection = self.library.list(&Query::default())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save the collection state to the database.
|
fn save_to_database(&mut self) -> Result<(), Error> {
|
||||||
pub fn save_to_database(&mut self) -> Result<(), Error> {
|
|
||||||
self.database.write(&self.collection)?;
|
self.database.write(&self.collection)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current collection.
|
fn get_collection(&self) -> &Collection {
|
||||||
pub fn get_collection(&self) -> &Collection {
|
|
||||||
&self.collection
|
&self.collection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +102,7 @@ mod tests {
|
|||||||
tests::COLLECTION,
|
tests::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CollectionManager, Error};
|
use super::{CollectionManager, Error, MhCollectionManager};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_get_write() {
|
fn read_get_write() {
|
||||||
@ -117,7 +127,8 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_| database_result);
|
.return_once(|_| database_result);
|
||||||
|
|
||||||
let mut collection_manager = CollectionManager::new(Box::new(library), Box::new(database));
|
let mut collection_manager =
|
||||||
|
MhCollectionManager::new(Box::new(library), Box::new(database));
|
||||||
|
|
||||||
collection_manager.rescan_library().unwrap();
|
collection_manager.rescan_library().unwrap();
|
||||||
assert_eq!(collection_manager.get_collection(), &*COLLECTION);
|
assert_eq!(collection_manager.get_collection(), &*COLLECTION);
|
||||||
@ -136,7 +147,8 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_| library_result);
|
.return_once(|_| library_result);
|
||||||
|
|
||||||
let mut collection_manager = CollectionManager::new(Box::new(library), Box::new(database));
|
let mut collection_manager =
|
||||||
|
MhCollectionManager::new(Box::new(library), Box::new(database));
|
||||||
|
|
||||||
let actual_err = collection_manager.rescan_library().unwrap_err();
|
let actual_err = collection_manager.rescan_library().unwrap_err();
|
||||||
let expected_err = Error::LibraryError(
|
let expected_err = Error::LibraryError(
|
||||||
@ -159,7 +171,8 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.return_once(|_| database_result);
|
.return_once(|_| database_result);
|
||||||
|
|
||||||
let mut collection_manager = CollectionManager::new(Box::new(library), Box::new(database));
|
let mut collection_manager =
|
||||||
|
MhCollectionManager::new(Box::new(library), Box::new(database));
|
||||||
|
|
||||||
let actual_err = collection_manager.save_to_database().unwrap_err();
|
let actual_err = collection_manager.save_to_database().unwrap_err();
|
||||||
let expected_err =
|
let expected_err =
|
||||||
|
97
src/lib.rs
97
src/lib.rs
@ -54,97 +54,14 @@ pub struct Artist {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
#[macro_use]
|
||||||
use super::*;
|
mod testing;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| {
|
use super::*;
|
||||||
vec![
|
|
||||||
Artist {
|
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| collection!());
|
||||||
id: ArtistId {
|
|
||||||
name: "album_artist a".to_string(),
|
|
||||||
},
|
|
||||||
albums: vec![
|
|
||||||
Album {
|
|
||||||
id: AlbumId {
|
|
||||||
year: 1998,
|
|
||||||
title: "album_title a.a".to_string(),
|
|
||||||
},
|
|
||||||
tracks: vec![
|
|
||||||
Track {
|
|
||||||
number: 1,
|
|
||||||
title: "track a.a.1".to_string(),
|
|
||||||
artist: vec!["artist a.a.1".to_string()],
|
|
||||||
format: TrackFormat::Flac,
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
number: 2,
|
|
||||||
title: "track a.a.2".to_string(),
|
|
||||||
artist: vec![
|
|
||||||
"artist a.a.2.1".to_string(),
|
|
||||||
"artist a.a.2.2".to_string(),
|
|
||||||
],
|
|
||||||
format: TrackFormat::Flac,
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
number: 3,
|
|
||||||
title: "track a.a.3".to_string(),
|
|
||||||
artist: vec!["artist a.a.3".to_string()],
|
|
||||||
format: TrackFormat::Flac,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Album {
|
|
||||||
id: AlbumId {
|
|
||||||
year: 2015,
|
|
||||||
title: "album_title a.b".to_string(),
|
|
||||||
},
|
|
||||||
tracks: vec![
|
|
||||||
Track {
|
|
||||||
number: 1,
|
|
||||||
title: "track a.b.1".to_string(),
|
|
||||||
artist: vec!["artist a.b.1".to_string()],
|
|
||||||
format: TrackFormat::Mp3,
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
number: 2,
|
|
||||||
title: "track a.b.2".to_string(),
|
|
||||||
artist: vec!["artist a.b.2".to_string()],
|
|
||||||
format: TrackFormat::Flac,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
Artist {
|
|
||||||
id: ArtistId {
|
|
||||||
name: "album_artist b.a".to_string(),
|
|
||||||
},
|
|
||||||
albums: vec![Album {
|
|
||||||
id: AlbumId {
|
|
||||||
year: 2003,
|
|
||||||
title: "album_title b.a".to_string(),
|
|
||||||
},
|
|
||||||
tracks: vec![
|
|
||||||
Track {
|
|
||||||
number: 1,
|
|
||||||
title: "track b.a.1".to_string(),
|
|
||||||
artist: vec!["artist b.a.1".to_string()],
|
|
||||||
format: TrackFormat::Mp3,
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
number: 2,
|
|
||||||
title: "track b.a.2".to_string(),
|
|
||||||
artist: vec![
|
|
||||||
"artist b.a.2.1".to_string(),
|
|
||||||
"artist b.a.2.2".to_string(),
|
|
||||||
],
|
|
||||||
format: TrackFormat::Mp3,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -404,13 +404,14 @@ mod tests {
|
|||||||
// Putting the last track first will make the entire artist come first in the output.
|
// Putting the last track first will make the entire artist come first in the output.
|
||||||
expected.rotate_right(1);
|
expected.rotate_right(1);
|
||||||
|
|
||||||
// Same applies to that artists' albums, but here the artist has only one album.
|
// Same applies to that artists' albums.
|
||||||
assert_eq!(expected[0].albums.len(), 1);
|
expected[0].albums.rotate_right(1);
|
||||||
|
|
||||||
// Same applies to that album's tracks.
|
// Same applies to that album's tracks.
|
||||||
expected[0].albums[0].tracks.rotate_right(1);
|
expected[0].albums[0].tracks.rotate_right(1);
|
||||||
|
|
||||||
// And the (now) second album's tracks first track comes last.
|
// And the original first album's (now the first album of the second artist) tracks first
|
||||||
|
// track comes last.
|
||||||
expected[1].albums[0].tracks.rotate_left(1);
|
expected[1].albums[0].tracks.rotate_left(1);
|
||||||
|
|
||||||
let mut executor = MockBeetsLibraryExecutor::new();
|
let mut executor = MockBeetsLibraryExecutor::new();
|
||||||
|
33
src/main.rs
33
src/main.rs
@ -6,7 +6,7 @@ use std::path::PathBuf;
|
|||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use musichoard::{
|
use musichoard::{
|
||||||
collection::CollectionManager,
|
collection::MhCollectionManager,
|
||||||
database::json::{JsonDatabase, JsonDatabaseFileBackend},
|
database::json::{JsonDatabase, JsonDatabaseFileBackend},
|
||||||
library::beets::{BeetsLibrary, BeetsLibraryCommandExecutor},
|
library::beets::{BeetsLibrary, BeetsLibraryCommandExecutor},
|
||||||
};
|
};
|
||||||
@ -52,7 +52,7 @@ fn main() {
|
|||||||
&opt.database_file_path,
|
&opt.database_file_path,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let collection_manager = CollectionManager::new(Box::new(beets), Box::new(database));
|
let collection_manager = MhCollectionManager::new(Box::new(beets), Box::new(database));
|
||||||
|
|
||||||
// Initialize the terminal user interface.
|
// Initialize the terminal user interface.
|
||||||
let backend = CrosstermBackend::new(io::stdout());
|
let backend = CrosstermBackend::new(io::stdout());
|
||||||
@ -64,10 +64,37 @@ fn main() {
|
|||||||
|
|
||||||
let ui = Ui::new();
|
let ui = Ui::new();
|
||||||
|
|
||||||
let app = App::new(collection_manager).expect("failed to initialise app");
|
let app = App::new(Box::new(collection_manager)).expect("failed to initialise app");
|
||||||
|
|
||||||
let tui = Tui::new(terminal, listener, handler, ui, app);
|
let tui = Tui::new(terminal, listener, handler, ui, app);
|
||||||
|
|
||||||
// Run the TUI application.
|
// Run the TUI application.
|
||||||
tui.run().expect("failed to run tui");
|
tui.run().expect("failed to run tui");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use]
|
||||||
|
mod testing;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use mockall::mock;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
use musichoard::*;
|
||||||
|
use musichoard::collection::{self, Collection, CollectionManager};
|
||||||
|
|
||||||
|
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| {
|
||||||
|
collection!()
|
||||||
|
});
|
||||||
|
|
||||||
|
mock! {
|
||||||
|
pub CollectionManager {}
|
||||||
|
|
||||||
|
impl CollectionManager for CollectionManager {
|
||||||
|
fn rescan_library(&mut self) -> Result<(), collection::Error>;
|
||||||
|
fn save_to_database(&mut self) -> Result<(), collection::Error>;
|
||||||
|
fn get_collection(&self) -> &Collection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
168
src/testing.rs
Normal file
168
src/testing.rs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
macro_rules! collection {
|
||||||
|
() => {
|
||||||
|
vec![
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: "album_artist a".to_string(),
|
||||||
|
},
|
||||||
|
albums: vec![
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 1998,
|
||||||
|
title: "album_title a.a".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track a.a.1".to_string(),
|
||||||
|
artist: vec!["artist a.a.1".to_string()],
|
||||||
|
format: TrackFormat::Flac,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track a.a.2".to_string(),
|
||||||
|
artist: vec![
|
||||||
|
"artist a.a.2.1".to_string(),
|
||||||
|
"artist a.a.2.2".to_string(),
|
||||||
|
],
|
||||||
|
format: TrackFormat::Flac,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 3,
|
||||||
|
title: "track a.a.3".to_string(),
|
||||||
|
artist: vec!["artist a.a.3".to_string()],
|
||||||
|
format: TrackFormat::Flac,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2015,
|
||||||
|
title: "album_title a.b".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track a.b.1".to_string(),
|
||||||
|
artist: vec!["artist a.b.1".to_string()],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track a.b.2".to_string(),
|
||||||
|
artist: vec!["artist a.b.2".to_string()],
|
||||||
|
format: TrackFormat::Flac,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: "album_artist b".to_string(),
|
||||||
|
},
|
||||||
|
albums: vec![
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2003,
|
||||||
|
title: "album_title b.a".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track b.a.1".to_string(),
|
||||||
|
artist: vec!["artist b.a.1".to_string()],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track b.a.2".to_string(),
|
||||||
|
artist: vec![
|
||||||
|
"artist b.a.2.1".to_string(),
|
||||||
|
"artist b.a.2.2".to_string(),
|
||||||
|
],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2008,
|
||||||
|
title: "album_title b.b".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track b.b.1".to_string(),
|
||||||
|
artist: vec!["artist b.b.1".to_string()],
|
||||||
|
format: TrackFormat::Flac,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track b.b.2".to_string(),
|
||||||
|
artist: vec![
|
||||||
|
"artist b.b.2.1".to_string(),
|
||||||
|
"artist b.b.2.2".to_string(),
|
||||||
|
],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: "album_artist c".to_string(),
|
||||||
|
},
|
||||||
|
albums: vec![
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 1985,
|
||||||
|
title: "album_title c.a".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track c.a.1".to_string(),
|
||||||
|
artist: vec!["artist c.a.1".to_string()],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track c.a.2".to_string(),
|
||||||
|
artist: vec![
|
||||||
|
"artist c.a.2.1".to_string(),
|
||||||
|
"artist c.a.2.2".to_string(),
|
||||||
|
],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2018,
|
||||||
|
title: "album_title c.b".to_string(),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
number: 1,
|
||||||
|
title: "track c.b.1".to_string(),
|
||||||
|
artist: vec!["artist c.b.1".to_string()],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
number: 2,
|
||||||
|
title: "track c.b.2".to_string(),
|
||||||
|
artist: vec![
|
||||||
|
"artist c.b.2.1".to_string(),
|
||||||
|
"artist c.b.2.2".to_string(),
|
||||||
|
],
|
||||||
|
format: TrackFormat::Mp3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
543
src/tui/app.rs
543
src/tui/app.rs
@ -2,7 +2,7 @@ use musichoard::{collection::CollectionManager, Album, AlbumId, Artist, ArtistId
|
|||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Category {
|
pub enum Category {
|
||||||
Artist,
|
Artist,
|
||||||
Album,
|
Album,
|
||||||
@ -10,7 +10,7 @@ pub enum Category {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TrackSelection {
|
struct TrackSelection {
|
||||||
index: u16,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrackSelection {
|
impl TrackSelection {
|
||||||
@ -24,7 +24,7 @@ impl TrackSelection {
|
|||||||
|
|
||||||
fn increment(&mut self, tracks: &Vec<Track>) {
|
fn increment(&mut self, tracks: &Vec<Track>) {
|
||||||
if let Some(result) = self.index.checked_add(1) {
|
if let Some(result) = self.index.checked_add(1) {
|
||||||
if (result as usize) < tracks.len() {
|
if result < tracks.len() {
|
||||||
self.index = result;
|
self.index = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ impl TrackSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct AlbumSelection {
|
struct AlbumSelection {
|
||||||
index: u16,
|
index: usize,
|
||||||
track: Option<TrackSelection>,
|
track: Option<TrackSelection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +56,9 @@ impl AlbumSelection {
|
|||||||
|
|
||||||
fn increment(&mut self, albums: &Vec<Album>) {
|
fn increment(&mut self, albums: &Vec<Album>) {
|
||||||
if let Some(result) = self.index.checked_add(1) {
|
if let Some(result) = self.index.checked_add(1) {
|
||||||
if (result as usize) < albums.len() {
|
if result < albums.len() {
|
||||||
self.index = result;
|
self.index = result;
|
||||||
self.track = TrackSelection::initialise(&albums[self.index as usize].tracks);
|
self.track = TrackSelection::initialise(&albums[self.index].tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,13 +66,13 @@ impl AlbumSelection {
|
|||||||
fn decrement(&mut self, albums: &Vec<Album>) {
|
fn decrement(&mut self, albums: &Vec<Album>) {
|
||||||
if let Some(result) = self.index.checked_sub(1) {
|
if let Some(result) = self.index.checked_sub(1) {
|
||||||
self.index = result;
|
self.index = result;
|
||||||
self.track = TrackSelection::initialise(&albums[self.index as usize].tracks);
|
self.track = TrackSelection::initialise(&albums[self.index].tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArtistSelection {
|
struct ArtistSelection {
|
||||||
index: u16,
|
index: usize,
|
||||||
album: Option<AlbumSelection>,
|
album: Option<AlbumSelection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,9 +90,9 @@ impl ArtistSelection {
|
|||||||
|
|
||||||
fn increment(&mut self, artists: &Vec<Artist>) {
|
fn increment(&mut self, artists: &Vec<Artist>) {
|
||||||
if let Some(result) = self.index.checked_add(1) {
|
if let Some(result) = self.index.checked_add(1) {
|
||||||
if (result as usize) < artists.len() {
|
if result < artists.len() {
|
||||||
self.index = result;
|
self.index = result;
|
||||||
self.album = AlbumSelection::initialise(&artists[self.index as usize].albums);
|
self.album = AlbumSelection::initialise(&artists[self.index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ impl ArtistSelection {
|
|||||||
fn decrement(&mut self, artists: &Vec<Artist>) {
|
fn decrement(&mut self, artists: &Vec<Artist>) {
|
||||||
if let Some(result) = self.index.checked_sub(1) {
|
if let Some(result) = self.index.checked_sub(1) {
|
||||||
self.index = result;
|
self.index = result;
|
||||||
self.album = AlbumSelection::initialise(&artists[self.index as usize].albums);
|
self.album = AlbumSelection::initialise(&artists[self.index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,13 +111,13 @@ struct Selection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
collection_manager: CollectionManager,
|
collection_manager: Box<dyn CollectionManager>,
|
||||||
selection: Selection,
|
selection: Selection,
|
||||||
running: bool,
|
running: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(mut collection_manager: CollectionManager) -> Result<Self, Error> {
|
pub fn new(mut collection_manager: Box<dyn CollectionManager>) -> Result<Self, Error> {
|
||||||
collection_manager.rescan_library()?;
|
collection_manager.rescan_library()?;
|
||||||
let selection = Selection {
|
let selection = Selection {
|
||||||
active: Category::Artist,
|
active: Category::Artist,
|
||||||
@ -184,7 +184,7 @@ impl App {
|
|||||||
if let Some(ref mut artist_selection) = self.selection.artist {
|
if let Some(ref mut artist_selection) = self.selection.artist {
|
||||||
if let Some(ref mut album_selection) = artist_selection.album {
|
if let Some(ref mut album_selection) = artist_selection.album {
|
||||||
let artists = &self.collection_manager.get_collection();
|
let artists = &self.collection_manager.get_collection();
|
||||||
let albums = &artists[artist_selection.index as usize].albums;
|
let albums = &artists[artist_selection.index].albums;
|
||||||
album_selection.increment(albums);
|
album_selection.increment(albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ impl App {
|
|||||||
if let Some(ref mut artist_selection) = self.selection.artist {
|
if let Some(ref mut artist_selection) = self.selection.artist {
|
||||||
if let Some(ref mut album_selection) = artist_selection.album {
|
if let Some(ref mut album_selection) = artist_selection.album {
|
||||||
let artists = &self.collection_manager.get_collection();
|
let artists = &self.collection_manager.get_collection();
|
||||||
let albums = &artists[artist_selection.index as usize].albums;
|
let albums = &artists[artist_selection.index].albums;
|
||||||
album_selection.decrement(albums);
|
album_selection.decrement(albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,8 +205,8 @@ impl App {
|
|||||||
if let Some(ref mut album_selection) = artist_selection.album {
|
if let Some(ref mut album_selection) = artist_selection.album {
|
||||||
if let Some(ref mut track_selection) = album_selection.track {
|
if let Some(ref mut track_selection) = album_selection.track {
|
||||||
let artists = &self.collection_manager.get_collection();
|
let artists = &self.collection_manager.get_collection();
|
||||||
let albums = &artists[artist_selection.index as usize].albums;
|
let albums = &artists[artist_selection.index].albums;
|
||||||
let tracks = &albums[album_selection.index as usize].tracks;
|
let tracks = &albums[album_selection.index].tracks;
|
||||||
track_selection.increment(tracks);
|
track_selection.increment(tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,8 +218,8 @@ impl App {
|
|||||||
if let Some(ref mut album_selection) = artist_selection.album {
|
if let Some(ref mut album_selection) = artist_selection.album {
|
||||||
if let Some(ref mut track_selection) = album_selection.track {
|
if let Some(ref mut track_selection) = album_selection.track {
|
||||||
let artists = &self.collection_manager.get_collection();
|
let artists = &self.collection_manager.get_collection();
|
||||||
let albums = &artists[artist_selection.index as usize].albums;
|
let albums = &artists[artist_selection.index].albums;
|
||||||
let tracks = &albums[album_selection.index as usize].tracks;
|
let tracks = &albums[album_selection.index].tracks;
|
||||||
track_selection.decrement(tracks);
|
track_selection.decrement(tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,20 +230,17 @@ impl App {
|
|||||||
self.selection.active
|
self.selection.active
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_artists(&self) -> Option<&Vec<Artist>> {
|
fn get_artists(&self) -> &Vec<Artist> {
|
||||||
Some(&self.collection_manager.get_collection())
|
&self.collection_manager.get_collection()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_albums(&self) -> Option<&Vec<Album>> {
|
fn get_albums(&self) -> Option<&Vec<Album>> {
|
||||||
if let Some(artists) = self.get_artists() {
|
let artists = self.get_artists();
|
||||||
if let Some(artist_index) = self.selected_artist() {
|
if let Some(artist_index) = self.selected_artist() {
|
||||||
Some(&artists[artist_index].albums)
|
Some(&artists[artist_index].albums)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tracks(&self) -> Option<&Vec<Track>> {
|
fn get_tracks(&self) -> Option<&Vec<Track>> {
|
||||||
@ -259,11 +256,8 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_artist_ids(&self) -> Vec<&ArtistId> {
|
pub fn get_artist_ids(&self) -> Vec<&ArtistId> {
|
||||||
if let Some(artists) = self.get_artists() {
|
let artists = self.get_artists();
|
||||||
artists.iter().map(|a| &a.id).collect()
|
artists.iter().map(|a| &a.id).collect()
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_album_ids(&self) -> Vec<&AlbumId> {
|
pub fn get_album_ids(&self) -> Vec<&AlbumId> {
|
||||||
@ -284,7 +278,7 @@ impl App {
|
|||||||
|
|
||||||
pub fn selected_artist(&self) -> Option<usize> {
|
pub fn selected_artist(&self) -> Option<usize> {
|
||||||
if let Some(ref artist_selection) = self.selection.artist {
|
if let Some(ref artist_selection) = self.selection.artist {
|
||||||
Some(artist_selection.index as usize)
|
Some(artist_selection.index)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -293,7 +287,7 @@ impl App {
|
|||||||
pub fn selected_album(&self) -> Option<usize> {
|
pub fn selected_album(&self) -> Option<usize> {
|
||||||
if let Some(ref artist_selection) = self.selection.artist {
|
if let Some(ref artist_selection) = self.selection.artist {
|
||||||
if let Some(ref album_selection) = artist_selection.album {
|
if let Some(ref album_selection) = artist_selection.album {
|
||||||
Some(album_selection.index as usize)
|
Some(album_selection.index)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -306,7 +300,7 @@ impl App {
|
|||||||
if let Some(ref artist_selection) = self.selection.artist {
|
if let Some(ref artist_selection) = self.selection.artist {
|
||||||
if let Some(ref album_selection) = artist_selection.album {
|
if let Some(ref album_selection) = artist_selection.album {
|
||||||
if let Some(ref track_selection) = album_selection.track {
|
if let Some(ref track_selection) = album_selection.track {
|
||||||
Some(track_selection.index as usize)
|
Some(track_selection.index)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -322,3 +316,488 @@ impl App {
|
|||||||
self.running = false;
|
self.running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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 = TrackSelection::initialise(&vec![]);
|
||||||
|
assert!(empty.is_none());
|
||||||
|
|
||||||
|
let sel = TrackSelection::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 = TrackSelection {
|
||||||
|
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 = AlbumSelection::initialise(&vec![]);
|
||||||
|
assert!(empty.is_none());
|
||||||
|
|
||||||
|
let sel = AlbumSelection::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 = AlbumSelection {
|
||||||
|
index: std::usize::MAX,
|
||||||
|
track: Some(TrackSelection { 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 = ArtistSelection::initialise(&vec![]);
|
||||||
|
assert!(empty.is_none());
|
||||||
|
|
||||||
|
let sel = ArtistSelection::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 = ArtistSelection {
|
||||||
|
index: std::usize::MAX,
|
||||||
|
album: Some(AlbumSelection {
|
||||||
|
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 = App::new(Box::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 = App::new(Box::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 = App::new(Box::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 = App::new(Box::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 = App::new(Box::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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user