Make fetch also fetch artist MBID if it is missing #201
@ -354,7 +354,29 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_musicbrainz_api_error() {
|
||||
fn fetch_musicbrainz_artist_api_error() {
|
||||
let mut mb_api = Box::new(MockIMusicBrainz::new());
|
||||
|
||||
let error = Err(musicbrainz::Error::RateLimit);
|
||||
|
||||
mb_api
|
||||
.expect_search_artist()
|
||||
.times(1)
|
||||
.return_once(|_| error);
|
||||
|
||||
let browse = AppMachine::browse(inner_with_mb(music_hoard(COLLECTION.to_owned()), mb_api));
|
||||
|
||||
// Use the fourth artist for this test as they have no MBID.
|
||||
let browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||
let browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||
let browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||
|
||||
let app = browse.fetch_musicbrainz();
|
||||
app.unwrap_error();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_musicbrainz_album_api_error() {
|
||||
let mut mb_api = Box::new(MockIMusicBrainz::new());
|
||||
|
||||
let error = Err(musicbrainz::Error::RateLimit);
|
||||
|
@ -204,7 +204,10 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use musichoard::collection::album::{AlbumDate, AlbumId, AlbumPrimaryType, AlbumSecondaryType};
|
||||
use musichoard::collection::{
|
||||
album::{AlbumDate, AlbumId, AlbumPrimaryType, AlbumSecondaryType},
|
||||
artist::ArtistId,
|
||||
};
|
||||
|
||||
use crate::tui::app::{
|
||||
machine::tests::{inner, music_hoard},
|
||||
@ -222,7 +225,31 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_info_vec() -> Vec<AppMatchesInfo> {
|
||||
fn artist_matches_info_vec() -> Vec<AppMatchesInfo> {
|
||||
let artist_1 = Artist::new(ArtistId::new("Artist 1"));
|
||||
|
||||
let artist_1_1 = artist_1.clone();
|
||||
let artist_match_1_1 = Match::new(100, artist_1_1);
|
||||
|
||||
let artist_1_2 = artist_1.clone();
|
||||
let mut artist_match_1_2 = Match::new(100, artist_1_2);
|
||||
artist_match_1_2.set_disambiguation("some disambiguation");
|
||||
|
||||
let list = vec![artist_match_1_1.clone(), artist_match_1_2.clone()];
|
||||
let matches_info_1 = AppMatchesInfo::artist(artist_1.clone(), list);
|
||||
|
||||
let artist_2 = Artist::new(ArtistId::new("Artist 2"));
|
||||
|
||||
let artist_2_1 = artist_1.clone();
|
||||
let album_match_2_1 = Match::new(100, artist_2_1);
|
||||
|
||||
let list = vec![album_match_2_1.clone()];
|
||||
let matches_info_2 = AppMatchesInfo::artist(artist_2.clone(), list);
|
||||
|
||||
vec![matches_info_1, matches_info_2]
|
||||
}
|
||||
|
||||
fn album_matches_info_vec() -> Vec<AppMatchesInfo> {
|
||||
let album_1 = Album::new(
|
||||
AlbumId::new("Album 1"),
|
||||
AlbumDate::new(Some(1990), Some(5), None),
|
||||
@ -231,25 +258,15 @@ mod tests {
|
||||
);
|
||||
|
||||
let album_1_1 = album_1.clone();
|
||||
let album_match_1_1 = Match {
|
||||
score: 100,
|
||||
item: album_1_1,
|
||||
disambiguation: None,
|
||||
};
|
||||
let album_match_1_1 = Match::new(100, album_1_1);
|
||||
|
||||
let mut album_1_2 = album_1.clone();
|
||||
album_1_2.id.title.push_str(" extra title part");
|
||||
album_1_2.secondary_types.pop();
|
||||
let album_match_1_2 = Match {
|
||||
score: 100,
|
||||
item: album_1_2,
|
||||
disambiguation: None,
|
||||
};
|
||||
let album_match_1_2 = Match::new(100, album_1_2);
|
||||
|
||||
let matches_info_1 = AppMatchesInfo::Album(AppAlbumMatchesInfo {
|
||||
matching: album_1.clone(),
|
||||
list: vec![album_match_1_1.clone(), album_match_1_2.clone()],
|
||||
});
|
||||
let list = vec![album_match_1_1.clone(), album_match_1_2.clone()];
|
||||
let matches_info_1 = AppMatchesInfo::album(album_1.clone(), list);
|
||||
|
||||
let album_2 = Album::new(
|
||||
AlbumId::new("Album 2"),
|
||||
@ -259,16 +276,10 @@ mod tests {
|
||||
);
|
||||
|
||||
let album_2_1 = album_1.clone();
|
||||
let album_match_2_1 = Match {
|
||||
score: 100,
|
||||
item: album_2_1,
|
||||
disambiguation: None,
|
||||
};
|
||||
let album_match_2_1 = Match::new(100, album_2_1);
|
||||
|
||||
let matches_info_2 = AppMatchesInfo::Album(AppAlbumMatchesInfo {
|
||||
matching: album_2.clone(),
|
||||
list: vec![album_match_2_1.clone()],
|
||||
});
|
||||
let list = vec![album_match_2_1.clone()];
|
||||
let matches_info_2 = AppMatchesInfo::album(album_2.clone(), list);
|
||||
|
||||
vec![matches_info_1, matches_info_2]
|
||||
}
|
||||
@ -293,7 +304,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_nonempty() {
|
||||
let matches_info_vec = matches_info_vec();
|
||||
let matches_info_vec = album_matches_info_vec();
|
||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
||||
|
||||
let mut widget_state = WidgetState::default();
|
||||
@ -323,9 +334,7 @@ mod tests {
|
||||
assert_eq!(public_matches.state, &widget_state);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_flow() {
|
||||
let matches_info_vec = matches_info_vec();
|
||||
fn matches_flow(matches_info_vec: Vec<AppMatchesInfo>) {
|
||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
||||
|
||||
let mut widget_state = WidgetState::default();
|
||||
@ -359,9 +368,19 @@ mod tests {
|
||||
matches.select().unwrap_browse();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn artist_matches_flow() {
|
||||
matches_flow(artist_matches_info_vec());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn album_matches_flow() {
|
||||
matches_flow(album_matches_info_vec());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matches_abort() {
|
||||
let matches_info_vec = matches_info_vec();
|
||||
let matches_info_vec = album_matches_info_vec();
|
||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
||||
|
||||
let mut widget_state = WidgetState::default();
|
||||
|
@ -98,11 +98,11 @@ impl UiDisplay {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_artist_matching_info(artist: &Artist) -> String {
|
||||
pub fn display_artist_matching(artist: &Artist) -> String {
|
||||
format!("Matching artist: {}", &artist.id.name)
|
||||
}
|
||||
|
||||
pub fn display_album_matching_info(album: &Album) -> String {
|
||||
pub fn display_album_matching(album: &Album) -> String {
|
||||
format!(
|
||||
"Matching album: {} | {}",
|
||||
UiDisplay::display_album_date(&album.date),
|
||||
@ -110,25 +110,34 @@ impl UiDisplay {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn display_matching_nothing_info() -> &'static str {
|
||||
pub fn display_nothing_matching() -> &'static str {
|
||||
"Matching nothing"
|
||||
}
|
||||
|
||||
pub fn display_matching_info(matches: Option<&AppPublicMatchesKind>) -> String {
|
||||
match matches.as_ref() {
|
||||
Some(kind) => match kind {
|
||||
AppPublicMatchesKind::Artist(m) => {
|
||||
UiDisplay::display_artist_matching_info(m.matching)
|
||||
}
|
||||
AppPublicMatchesKind::Album(m) => {
|
||||
UiDisplay::display_album_matching_info(m.matching)
|
||||
}
|
||||
AppPublicMatchesKind::Artist(m) => UiDisplay::display_artist_matching(m.matching),
|
||||
AppPublicMatchesKind::Album(m) => UiDisplay::display_album_matching(m.matching),
|
||||
},
|
||||
None => UiDisplay::display_matching_nothing_info().to_string(),
|
||||
None => UiDisplay::display_nothing_matching().to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_album_match_string(match_album: &Match<Album>) -> String {
|
||||
pub fn display_artist_match(match_artist: &Match<Artist>) -> String {
|
||||
format!(
|
||||
"{}{} ({}%)",
|
||||
&match_artist.item.id.name,
|
||||
&match_artist
|
||||
.disambiguation
|
||||
.as_ref()
|
||||
.map(|d| format!(" ({d})"))
|
||||
.unwrap_or_default(),
|
||||
match_artist.score,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn display_album_match(match_album: &Match<Album>) -> String {
|
||||
format!(
|
||||
"{:010} | {} [{}] ({}%)",
|
||||
UiDisplay::display_album_date(&match_album.item.date),
|
||||
@ -140,17 +149,6 @@ impl UiDisplay {
|
||||
match_album.score,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn display_artist_match_string(match_artist: &Match<Artist>) -> String {
|
||||
let disambiguation_string = match match_artist.disambiguation.as_ref() {
|
||||
Some(d) => format!(" ({d})"),
|
||||
None => String::from(""),
|
||||
};
|
||||
format!(
|
||||
"{}{} ({}%)",
|
||||
&match_artist.item.id.name, &disambiguation_string, match_artist.score,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -26,19 +26,19 @@ impl<'a, 'b> MatchesState<'a, 'b> {
|
||||
|
||||
fn empty(state: &'b mut WidgetState) -> Self {
|
||||
MatchesState {
|
||||
matching: UiDisplay::display_matching_nothing_info().to_string(),
|
||||
matching: UiDisplay::display_nothing_matching().to_string(),
|
||||
list: List::default(),
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
fn artists(matching: &Artist, matches: &[Match<Artist>], state: &'b mut WidgetState) -> Self {
|
||||
let matching = UiDisplay::display_artist_matching_info(matching);
|
||||
let matching = UiDisplay::display_artist_matching(matching);
|
||||
|
||||
let list = List::new(
|
||||
matches
|
||||
.iter()
|
||||
.map(UiDisplay::display_artist_match_string)
|
||||
.map(UiDisplay::display_artist_match)
|
||||
.map(ListItem::new)
|
||||
.collect::<Vec<ListItem>>(),
|
||||
);
|
||||
@ -51,12 +51,12 @@ impl<'a, 'b> MatchesState<'a, 'b> {
|
||||
}
|
||||
|
||||
fn albums(matching: &Album, matches: &[Match<Album>], state: &'b mut WidgetState) -> Self {
|
||||
let matching = UiDisplay::display_album_matching_info(matching);
|
||||
let matching = UiDisplay::display_album_matching(matching);
|
||||
|
||||
let list = List::new(
|
||||
matches
|
||||
.iter()
|
||||
.map(UiDisplay::display_album_match_string)
|
||||
.map(UiDisplay::display_album_match)
|
||||
.map(ListItem::new)
|
||||
.collect::<Vec<ListItem>>(),
|
||||
);
|
||||
|
@ -246,27 +246,35 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn public_inner<'app>(
|
||||
collection: &'app Collection,
|
||||
selection: &'app mut Selection,
|
||||
) -> AppPublicInner<'app> {
|
||||
AppPublicInner {
|
||||
collection,
|
||||
selection,
|
||||
}
|
||||
}
|
||||
|
||||
fn artist_matches<'app>(
|
||||
matching: &'app Artist,
|
||||
list: &'app [Match<Artist>],
|
||||
) -> AppPublicMatchesKind<'app> {
|
||||
AppPublicMatchesKind::Artist(AppPublicArtistMatches { matching, list })
|
||||
}
|
||||
|
||||
fn album_matches<'app>(
|
||||
matching: &'app Album,
|
||||
list: &'app [Match<Album>],
|
||||
) -> AppPublicMatchesKind<'app> {
|
||||
AppPublicMatchesKind::Album(AppPublicAlbumMatches { matching, list })
|
||||
}
|
||||
|
||||
fn draw_test_suite(collection: &Collection, selection: &mut Selection) {
|
||||
let mut terminal = terminal();
|
||||
|
||||
let album = Album::new(
|
||||
AlbumId::new("An Album"),
|
||||
AlbumDate::new(Some(1990), Some(5), None),
|
||||
Some(AlbumPrimaryType::Album),
|
||||
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
|
||||
);
|
||||
|
||||
let album_match = Match {
|
||||
score: 80,
|
||||
item: album.clone(),
|
||||
disambiguation: None,
|
||||
};
|
||||
|
||||
let mut app = AppPublic {
|
||||
inner: AppPublicInner {
|
||||
collection,
|
||||
selection,
|
||||
},
|
||||
inner: public_inner(collection, selection),
|
||||
state: AppState::Browse(()),
|
||||
};
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
@ -280,27 +288,6 @@ mod tests {
|
||||
app.state = AppState::Search("");
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
|
||||
let album_matches = [album_match.clone(), album_match.clone()];
|
||||
let mut widget_state = WidgetState::default();
|
||||
widget_state.list.select(Some(0));
|
||||
|
||||
app.state = AppState::Matches(AppPublicMatches {
|
||||
matches: Some(AppPublicMatchesKind::Album(AppPublicAlbumMatches {
|
||||
matching: &album,
|
||||
list: &album_matches,
|
||||
})),
|
||||
state: &mut widget_state,
|
||||
});
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
|
||||
let mut widget_state = WidgetState::default();
|
||||
|
||||
app.state = AppState::Matches(AppPublicMatches {
|
||||
matches: None,
|
||||
state: &mut widget_state,
|
||||
});
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
|
||||
app.state = AppState::Error("get rekt scrub");
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
|
||||
@ -348,4 +335,86 @@ mod tests {
|
||||
|
||||
draw_test_suite(artists, &mut selection);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draw_empty_matches() {
|
||||
let collection = &COLLECTION;
|
||||
let mut selection = Selection::new(collection);
|
||||
|
||||
let mut terminal = terminal();
|
||||
|
||||
let mut widget_state = WidgetState::default();
|
||||
|
||||
let mut app = AppPublic {
|
||||
inner: public_inner(collection, &mut selection),
|
||||
state: AppState::Matches(AppPublicMatches {
|
||||
matches: None,
|
||||
state: &mut widget_state,
|
||||
}),
|
||||
};
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draw_artist_matches() {
|
||||
let collection = &COLLECTION;
|
||||
let mut selection = Selection::new(collection);
|
||||
|
||||
let mut terminal = terminal();
|
||||
|
||||
let artist = Artist::new(ArtistId::new("an artist"));
|
||||
|
||||
let artist_match = Match {
|
||||
score: 80,
|
||||
item: artist.clone(),
|
||||
disambiguation: None,
|
||||
};
|
||||
|
||||
let list = [artist_match.clone(), artist_match.clone()];
|
||||
let mut widget_state = WidgetState::default();
|
||||
widget_state.list.select(Some(0));
|
||||
|
||||
let mut app = AppPublic {
|
||||
inner: public_inner(collection, &mut selection),
|
||||
state: AppState::Matches(AppPublicMatches {
|
||||
matches: Some(artist_matches(&artist, &list)),
|
||||
state: &mut widget_state,
|
||||
}),
|
||||
};
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draw_album_matches() {
|
||||
let collection = &COLLECTION;
|
||||
let mut selection = Selection::new(collection);
|
||||
|
||||
let mut terminal = terminal();
|
||||
|
||||
let album = Album::new(
|
||||
AlbumId::new("An Album"),
|
||||
AlbumDate::new(Some(1990), Some(5), None),
|
||||
Some(AlbumPrimaryType::Album),
|
||||
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
|
||||
);
|
||||
|
||||
let album_match = Match {
|
||||
score: 80,
|
||||
item: album.clone(),
|
||||
disambiguation: None,
|
||||
};
|
||||
|
||||
let list = [album_match.clone(), album_match.clone()];
|
||||
let mut widget_state = WidgetState::default();
|
||||
widget_state.list.select(Some(0));
|
||||
|
||||
let mut app = AppPublic {
|
||||
inner: public_inner(collection, &mut selection),
|
||||
state: AppState::Matches(AppPublicMatches {
|
||||
matches: Some(album_matches(&album, &list)),
|
||||
state: &mut widget_state,
|
||||
}),
|
||||
};
|
||||
terminal.draw(|frame| Ui::render(&mut app, frame)).unwrap();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user