app complete coverage
This commit is contained in:
parent
0cc477fb05
commit
369b4ecf98
@ -19,12 +19,12 @@ use crate::tui::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type FetchReceiver = mpsc::Receiver<MbApiResult>;
|
||||||
pub struct FetchState {
|
pub struct FetchState {
|
||||||
fetch_rx: FetchReceiver,
|
fetch_rx: FetchReceiver,
|
||||||
lookup_rx: Option<FetchReceiver>,
|
lookup_rx: Option<FetchReceiver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FetchReceiver = mpsc::Receiver<MbApiResult>;
|
|
||||||
impl FetchState {
|
impl FetchState {
|
||||||
pub fn new(fetch_rx: FetchReceiver) -> Self {
|
pub fn new(fetch_rx: FetchReceiver) -> Self {
|
||||||
FetchState {
|
FetchState {
|
||||||
@ -38,7 +38,7 @@ impl FetchState {
|
|||||||
let result = lookup_rx.try_recv();
|
let result = lookup_rx.try_recv();
|
||||||
match result {
|
match result {
|
||||||
Ok(_) | Err(TryRecvError::Empty) => return result,
|
Ok(_) | Err(TryRecvError::Empty) => return result,
|
||||||
_ => {
|
Err(TryRecvError::Disconnected) => {
|
||||||
self.lookup_rx.take();
|
self.lookup_rx.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,12 +214,47 @@ mod tests {
|
|||||||
machine::tests::{inner, music_hoard},
|
machine::tests::{inner, music_hoard},
|
||||||
Delta, IApp, IAppAccess, IAppInteractBrowse, MatchStateInfo, MissOption, SearchOption,
|
Delta, IApp, IAppAccess, IAppInteractBrowse, MatchStateInfo, MissOption, SearchOption,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::{self, api::Match, daemon::MockIMbJobSender},
|
lib::interface::musicbrainz::{
|
||||||
|
self,
|
||||||
|
api::{Lookup, Match},
|
||||||
|
daemon::MockIMbJobSender,
|
||||||
|
},
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn mbid() -> Mbid {
|
||||||
|
"00000000-0000-0000-0000-000000000000".try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_recv() {
|
||||||
|
let (fetch_tx, fetch_rx) = mpsc::channel();
|
||||||
|
let (lookup_tx, lookup_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
let mut fetch = FetchState::new(fetch_rx);
|
||||||
|
fetch.lookup_rx.replace(lookup_rx);
|
||||||
|
|
||||||
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
|
||||||
|
let matches: Vec<Match<ArtistMeta>> = vec![];
|
||||||
|
let fetch_result = MatchStateInfo::artist_search(artist.clone(), matches);
|
||||||
|
fetch_tx.send(Ok(fetch_result.clone())).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
||||||
|
|
||||||
|
let lookup = Lookup::new(artist.clone());
|
||||||
|
let lookup_result = MatchStateInfo::artist_lookup(artist.clone(), lookup);
|
||||||
|
lookup_tx.send(Ok(lookup_result.clone())).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(fetch.try_recv(), Ok(Ok(lookup_result)));
|
||||||
|
|
||||||
|
assert_eq!(fetch.try_recv(), Err(TryRecvError::Empty));
|
||||||
|
drop(lookup_tx);
|
||||||
|
assert_eq!(fetch.try_recv(), Ok(Ok(fetch_result)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fetch_no_artist() {
|
fn fetch_no_artist() {
|
||||||
let app = AppMachine::app_fetch_new(inner(music_hoard(vec![])));
|
let app = AppMachine::app_fetch_new(inner(music_hoard(vec![])));
|
||||||
@ -265,6 +300,31 @@ mod tests {
|
|||||||
assert!(matches!(app, AppState::Match(_)));
|
assert!(matches!(app, AppState::Match(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_album_expectation(job_sender: &mut MockIMbJobSender, album: &AlbumMeta) {
|
||||||
|
let requests = VecDeque::from([MbParams::lookup_release_group(album.clone(), mbid())]);
|
||||||
|
job_sender
|
||||||
|
.expect_submit_foreground_job()
|
||||||
|
.with(predicate::always(), predicate::eq(requests))
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_, _| Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_album() {
|
||||||
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
|
||||||
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
|
lookup_album_expectation(&mut mb_job_sender, &album);
|
||||||
|
|
||||||
|
let music_hoard = music_hoard(COLLECTION.to_owned());
|
||||||
|
let inner = AppInner::new(music_hoard, mb_job_sender);
|
||||||
|
|
||||||
|
let (_fetch_tx, fetch_rx) = mpsc::channel();
|
||||||
|
let fetch = FetchState::new(fetch_rx);
|
||||||
|
|
||||||
|
AppMachine::app_lookup_album(inner, fetch, &album, mbid());
|
||||||
|
}
|
||||||
|
|
||||||
fn search_artist_expectation(job_sender: &mut MockIMbJobSender, artist: &ArtistMeta) {
|
fn search_artist_expectation(job_sender: &mut MockIMbJobSender, artist: &ArtistMeta) {
|
||||||
let requests = VecDeque::from([MbParams::search_artist(artist.clone())]);
|
let requests = VecDeque::from([MbParams::search_artist(artist.clone())]);
|
||||||
job_sender
|
job_sender
|
||||||
@ -294,6 +354,31 @@ mod tests {
|
|||||||
assert!(matches!(app, AppState::Match(_)));
|
assert!(matches!(app, AppState::Match(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_artist_expectation(job_sender: &mut MockIMbJobSender, artist: &ArtistMeta) {
|
||||||
|
let requests = VecDeque::from([MbParams::lookup_artist(artist.clone(), mbid())]);
|
||||||
|
job_sender
|
||||||
|
.expect_submit_foreground_job()
|
||||||
|
.with(predicate::always(), predicate::eq(requests))
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_, _| Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_artist() {
|
||||||
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
|
||||||
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
lookup_artist_expectation(&mut mb_job_sender, &artist);
|
||||||
|
|
||||||
|
let music_hoard = music_hoard(COLLECTION.to_owned());
|
||||||
|
let inner = AppInner::new(music_hoard, mb_job_sender);
|
||||||
|
|
||||||
|
let (_fetch_tx, fetch_rx) = mpsc::channel();
|
||||||
|
let fetch = FetchState::new(fetch_rx);
|
||||||
|
|
||||||
|
AppMachine::app_lookup_artist(inner, fetch, &artist, mbid());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fetch_artist_job_sender_err() {
|
fn fetch_artist_job_sender_err() {
|
||||||
let mut mb_job_sender = MockIMbJobSender::new();
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
@ -310,6 +395,26 @@ mod tests {
|
|||||||
assert!(matches!(app, AppState::Error(_)));
|
assert!(matches!(app, AppState::Error(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_artist_job_sender_err() {
|
||||||
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
|
||||||
|
mb_job_sender
|
||||||
|
.expect_submit_foreground_job()
|
||||||
|
.return_once(|_, _| Err(DaemonError::JobChannelDisconnected));
|
||||||
|
|
||||||
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
|
||||||
|
let music_hoard = music_hoard(COLLECTION.to_owned());
|
||||||
|
let inner = AppInner::new(music_hoard, mb_job_sender);
|
||||||
|
|
||||||
|
let (_fetch_tx, fetch_rx) = mpsc::channel();
|
||||||
|
let fetch = FetchState::new(fetch_rx);
|
||||||
|
|
||||||
|
let app = AppMachine::app_lookup_artist(inner, fetch, &artist, mbid());
|
||||||
|
assert!(matches!(app, AppState::Error(_)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn recv_ok_fetch_ok() {
|
fn recv_ok_fetch_ok() {
|
||||||
let (tx, rx) = mpsc::channel::<MbApiResult>();
|
let (tx, rx) = mpsc::channel::<MbApiResult>();
|
||||||
|
@ -64,20 +64,12 @@ impl IAppInput for AppInputMode {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tui::app::{
|
use crate::tui::app::{
|
||||||
machine::tests::{mb_job_sender, music_hoard_init},
|
machine::tests::{input_event, mb_job_sender, music_hoard_init},
|
||||||
IApp,
|
IApp,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn input_event(c: char) -> InputEvent {
|
|
||||||
crossterm::event::KeyEvent::new(
|
|
||||||
crossterm::event::KeyCode::Char(c),
|
|
||||||
crossterm::event::KeyModifiers::empty(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn handle_input() {
|
fn handle_input() {
|
||||||
let mut app = App::new(music_hoard_init(vec![]), mb_job_sender());
|
let mut app = App::new(music_hoard_init(vec![]), mb_job_sender());
|
||||||
|
@ -218,8 +218,9 @@ impl IAppInteractMatch for AppMachine<MatchState> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::sync::mpsc;
|
use std::{collections::VecDeque, sync::mpsc};
|
||||||
|
|
||||||
|
use mockall::predicate;
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType},
|
album::{AlbumDate, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType},
|
||||||
artist::{ArtistId, ArtistMeta},
|
artist::{ArtistId, ArtistMeta},
|
||||||
@ -227,10 +228,13 @@ mod tests {
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
machine::tests::{inner, music_hoard},
|
machine::tests::{inner, inner_with_mb, input_event, music_hoard},
|
||||||
IApp, IAppAccess, IAppInput,
|
IApp, IAppAccess, IAppInput,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::api::Match,
|
lib::interface::musicbrainz::{
|
||||||
|
api::{Lookup, Match},
|
||||||
|
daemon::{MbParams, MockIMbJobSender},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -245,6 +249,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Lookup<T> {
|
||||||
|
pub fn new(item: T) -> Self {
|
||||||
|
Lookup {
|
||||||
|
item,
|
||||||
|
disambiguation: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn artist_match() -> MatchStateInfo {
|
fn artist_match() -> MatchStateInfo {
|
||||||
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
||||||
|
|
||||||
@ -259,6 +272,12 @@ mod tests {
|
|||||||
MatchStateInfo::artist_search(artist, list)
|
MatchStateInfo::artist_search(artist, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn artist_lookup() -> MatchStateInfo {
|
||||||
|
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
||||||
|
let lookup = Lookup::new(artist.clone());
|
||||||
|
MatchStateInfo::artist_lookup(artist, lookup)
|
||||||
|
}
|
||||||
|
|
||||||
fn album_match() -> MatchStateInfo {
|
fn album_match() -> MatchStateInfo {
|
||||||
let album = AlbumMeta::new(
|
let album = AlbumMeta::new(
|
||||||
AlbumId::new("Album"),
|
AlbumId::new("Album"),
|
||||||
@ -279,6 +298,17 @@ mod tests {
|
|||||||
MatchStateInfo::album_search(album, list)
|
MatchStateInfo::album_search(album, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn album_lookup() -> MatchStateInfo {
|
||||||
|
let album = AlbumMeta::new(
|
||||||
|
AlbumId::new("Album"),
|
||||||
|
AlbumDate::new(Some(1990), Some(5), None),
|
||||||
|
Some(AlbumPrimaryType::Album),
|
||||||
|
vec![AlbumSecondaryType::Live, AlbumSecondaryType::Compilation],
|
||||||
|
);
|
||||||
|
let lookup = Lookup::new(album.clone());
|
||||||
|
MatchStateInfo::album_lookup(album, lookup)
|
||||||
|
}
|
||||||
|
|
||||||
fn fetch_state() -> FetchState {
|
fn fetch_state() -> FetchState {
|
||||||
let (_, rx) = mpsc::channel();
|
let (_, rx) = mpsc::channel();
|
||||||
FetchState::new(rx)
|
FetchState::new(rx)
|
||||||
@ -329,7 +359,7 @@ mod tests {
|
|||||||
assert_eq!(public_matches.state, &widget_state);
|
assert_eq!(public_matches.state, &widget_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_state_flow(mut matches_info: MatchStateInfo) {
|
fn match_state_flow(mut matches_info: MatchStateInfo, len: usize) {
|
||||||
// tx must exist for rx to return Empty rather than Disconnected.
|
// tx must exist for rx to return Empty rather than Disconnected.
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
@ -350,27 +380,30 @@ mod tests {
|
|||||||
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(0));
|
assert_eq!(matches.state.state.list.selected(), Some(0));
|
||||||
|
|
||||||
let matches = matches.next_match().unwrap_match();
|
let mut matches = matches;
|
||||||
|
for ii in 1..len {
|
||||||
|
matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(1));
|
assert_eq!(matches.state.state.list.selected(), Some(ii));
|
||||||
|
}
|
||||||
|
|
||||||
// Next is CannotHaveMBID
|
// Next is CannotHaveMBID
|
||||||
let matches = matches.next_match().unwrap_match();
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(2));
|
assert_eq!(matches.state.state.list.selected(), Some(len));
|
||||||
|
|
||||||
// Next is ManualInputMbid
|
// Next is ManualInputMbid
|
||||||
let matches = matches.next_match().unwrap_match();
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(3));
|
assert_eq!(matches.state.state.list.selected(), Some(len + 1));
|
||||||
|
|
||||||
let matches = matches.next_match().unwrap_match();
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(3));
|
assert_eq!(matches.state.state.list.selected(), Some(len + 1));
|
||||||
|
|
||||||
// Go prev_match first as selecting on manual input does not go back to fetch.
|
// Go prev_match first as selecting on manual input does not go back to fetch.
|
||||||
let matches = matches.prev_match().unwrap_match();
|
let matches = matches.prev_match().unwrap_match();
|
||||||
@ -379,12 +412,22 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn artist_matches_flow() {
|
fn artist_matches_flow() {
|
||||||
match_state_flow(artist_match());
|
match_state_flow(artist_match(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn artist_lookup_flow() {
|
||||||
|
match_state_flow(artist_lookup(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn album_matches_flow() {
|
fn album_matches_flow() {
|
||||||
match_state_flow(album_match());
|
match_state_flow(album_match(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn album_lookup_flow() {
|
||||||
|
match_state_flow(album_lookup(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -430,4 +473,73 @@ mod tests {
|
|||||||
let input = app.mode().unwrap_input();
|
let input = app.mode().unwrap_input();
|
||||||
input.confirm().unwrap_error();
|
input.confirm().unwrap_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mbid() -> Mbid {
|
||||||
|
"00000000-0000-0000-0000-000000000000".try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_mbid(mut app: App) -> App {
|
||||||
|
let mbid = mbid().uuid().to_string();
|
||||||
|
for c in mbid.chars() {
|
||||||
|
let input = app.mode().unwrap_input();
|
||||||
|
app = input.input(input_event(c));
|
||||||
|
}
|
||||||
|
app
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_manual_input_artist() {
|
||||||
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
let artist = ArtistMeta::new(ArtistId::new("Artist"));
|
||||||
|
let requests = VecDeque::from([MbParams::lookup_artist(artist.clone(), mbid())]);
|
||||||
|
mb_job_sender
|
||||||
|
.expect_submit_foreground_job()
|
||||||
|
.with(predicate::always(), predicate::eq(requests))
|
||||||
|
.return_once(|_, _| Ok(()));
|
||||||
|
|
||||||
|
let matches_vec: Vec<Match<ArtistMeta>> = vec![];
|
||||||
|
let artist_match = MatchStateInfo::artist_search(artist.clone(), matches_vec);
|
||||||
|
let matches = AppMachine::match_state(
|
||||||
|
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
||||||
|
match_state(Some(artist_match)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// There are no matches which means that the second option should be manual input.
|
||||||
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
|
let mut app = matches.select();
|
||||||
|
app = input_mbid(app);
|
||||||
|
|
||||||
|
let input = app.mode().unwrap_input();
|
||||||
|
input.confirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn select_manual_input_album() {
|
||||||
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
let album = AlbumMeta::new::<_, u32>("Album", 1990u32.into(), None, vec![]);
|
||||||
|
let requests = VecDeque::from([MbParams::lookup_release_group(album.clone(), mbid())]);
|
||||||
|
mb_job_sender
|
||||||
|
.expect_submit_foreground_job()
|
||||||
|
.with(predicate::always(), predicate::eq(requests))
|
||||||
|
.return_once(|_, _| Ok(()));
|
||||||
|
|
||||||
|
let matches_vec: Vec<Match<AlbumMeta>> = vec![];
|
||||||
|
let album_match = MatchStateInfo::album_search(album.clone(), matches_vec);
|
||||||
|
let matches = AppMachine::match_state(
|
||||||
|
inner_with_mb(music_hoard(vec![]), mb_job_sender),
|
||||||
|
match_state(Some(album_match)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// There are no matches which means that the second option should be manual input.
|
||||||
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
let matches = matches.next_match().unwrap_match();
|
||||||
|
|
||||||
|
let mut app = matches.select();
|
||||||
|
app = input_mbid(app);
|
||||||
|
|
||||||
|
let input = app.mode().unwrap_input();
|
||||||
|
input.confirm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ mod tests {
|
|||||||
use musichoard::collection::Collection;
|
use musichoard::collection::Collection;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{AppState, IApp, IAppInput, IAppInteractBrowse},
|
app::{AppState, IApp, IAppInput, IAppInteractBrowse, InputEvent},
|
||||||
lib::{interface::musicbrainz::daemon::MockIMbJobSender, MockIMusicHoard},
|
lib::{interface::musicbrainz::daemon::MockIMbJobSender, MockIMusicHoard},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -355,6 +355,14 @@ mod tests {
|
|||||||
AppInner::new(music_hoard, mb_job_sender)
|
AppInner::new(music_hoard, mb_job_sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn input_event(c: char) -> InputEvent {
|
||||||
|
crossterm::event::KeyEvent::new(
|
||||||
|
crossterm::event::KeyCode::Char(c),
|
||||||
|
crossterm::event::KeyModifiers::empty(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn input_mode() {
|
fn input_mode() {
|
||||||
let app = App::new(music_hoard_init(vec![]), mb_job_sender());
|
let app = App::new(music_hoard_init(vec![]), mb_job_sender());
|
||||||
|
138
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
138
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -110,7 +110,7 @@ impl IMbJobSender for JobSender {
|
|||||||
result_sender: ResultSender,
|
result_sender: ResultSender,
|
||||||
requests: VecDeque<MbParams>,
|
requests: VecDeque<MbParams>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.send_foreground_job(result_sender, requests)
|
self.send_job(JobPriority::Foreground, result_sender, requests)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit_background_job(
|
fn submit_background_job(
|
||||||
@ -118,27 +118,11 @@ impl IMbJobSender for JobSender {
|
|||||||
result_sender: ResultSender,
|
result_sender: ResultSender,
|
||||||
requests: VecDeque<MbParams>,
|
requests: VecDeque<MbParams>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.send_background_job(result_sender, requests)
|
self.send_job(JobPriority::Background, result_sender, requests)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JobSender {
|
impl JobSender {
|
||||||
fn send_foreground_job(
|
|
||||||
&self,
|
|
||||||
result_sender: ResultSender,
|
|
||||||
requests: VecDeque<MbParams>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.send_job(JobPriority::Foreground, result_sender, requests)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_background_job(
|
|
||||||
&self,
|
|
||||||
result_sender: ResultSender,
|
|
||||||
requests: VecDeque<MbParams>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.send_job(JobPriority::Background, result_sender, requests)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_job(
|
fn send_job(
|
||||||
&self,
|
&self,
|
||||||
priority: JobPriority,
|
priority: JobPriority,
|
||||||
@ -337,7 +321,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
event::{Event, EventError, MockIFetchCompleteEventSender},
|
event::{Event, EventError, MockIFetchCompleteEventSender},
|
||||||
lib::interface::musicbrainz::api::{Match, MockIMusicBrainz},
|
lib::interface::musicbrainz::api::{Lookup, Match, MockIMusicBrainz},
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -387,12 +371,28 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mbid() -> Mbid {
|
||||||
|
"00000000-0000-0000-0000-000000000000".try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_artist_requests() -> VecDeque<MbParams> {
|
||||||
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
let mbid = mbid();
|
||||||
|
VecDeque::from([MbParams::lookup_artist(artist, mbid)])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_release_group_requests() -> VecDeque<MbParams> {
|
||||||
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
|
let mbid = mbid();
|
||||||
|
VecDeque::from([MbParams::lookup_release_group(album, mbid)])
|
||||||
|
}
|
||||||
|
|
||||||
fn search_artist_requests() -> VecDeque<MbParams> {
|
fn search_artist_requests() -> VecDeque<MbParams> {
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
VecDeque::from([MbParams::search_artist(artist)])
|
VecDeque::from([MbParams::search_artist(artist)])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_expectations() -> (ArtistMeta, Vec<Match<ArtistMeta>>) {
|
fn search_artist_expectations() -> (ArtistMeta, Vec<Match<ArtistMeta>>) {
|
||||||
let artist = COLLECTION[3].meta.clone();
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
|
||||||
let artist_match_1 = Match::new(100, artist.clone());
|
let artist_match_1 = Match::new(100, artist.clone());
|
||||||
@ -420,7 +420,7 @@ mod tests {
|
|||||||
mbref.unwrap().mbid().clone()
|
mbref.unwrap().mbid().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_expectations_1() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
fn search_album_expectations_1() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
||||||
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
||||||
|
|
||||||
@ -431,7 +431,7 @@ mod tests {
|
|||||||
(album_1, matches_1)
|
(album_1, matches_1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn album_expectations_4() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
fn search_album_expectations_4() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
||||||
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
||||||
|
|
||||||
@ -515,6 +515,90 @@ mod tests {
|
|||||||
assert_eq!(result, Err(JobError::JobQueueEmpty));
|
assert_eq!(result, Err(JobError::JobQueueEmpty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lookup_artist_expectation(
|
||||||
|
musicbrainz: &mut MockIMusicBrainz,
|
||||||
|
mbid: &Mbid,
|
||||||
|
lookup: &Lookup<ArtistMeta>,
|
||||||
|
) {
|
||||||
|
let result = Ok(lookup.clone());
|
||||||
|
musicbrainz
|
||||||
|
.expect_lookup_artist()
|
||||||
|
.with(predicate::eq(mbid.clone()))
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_| result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn execute_lookup_artist() {
|
||||||
|
let mut musicbrainz = musicbrainz();
|
||||||
|
let mbid = mbid();
|
||||||
|
let artist = COLLECTION[3].meta.clone();
|
||||||
|
let lookup = Lookup::new(artist.clone());
|
||||||
|
lookup_artist_expectation(&mut musicbrainz, &mbid, &lookup);
|
||||||
|
|
||||||
|
let mut event_sender = event_sender();
|
||||||
|
fetch_complete_expectation(&mut event_sender, 1);
|
||||||
|
|
||||||
|
let (job_sender, job_receiver) = job_channel();
|
||||||
|
let mut daemon = daemon_with(musicbrainz, job_receiver, event_sender);
|
||||||
|
|
||||||
|
let requests = lookup_artist_requests();
|
||||||
|
let (result_sender, result_receiver) = mpsc::channel();
|
||||||
|
let result = job_sender.submit_foreground_job(result_sender, requests);
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = daemon.enqueue_all_pending_jobs();
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = daemon.execute_next_job();
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = result_receiver.try_recv().unwrap();
|
||||||
|
assert_eq!(result, Ok(MatchStateInfo::artist_lookup(artist, lookup)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_release_group_expectation(
|
||||||
|
musicbrainz: &mut MockIMusicBrainz,
|
||||||
|
mbid: &Mbid,
|
||||||
|
lookup: &Lookup<AlbumMeta>,
|
||||||
|
) {
|
||||||
|
let result = Ok(lookup.clone());
|
||||||
|
musicbrainz
|
||||||
|
.expect_lookup_release_group()
|
||||||
|
.with(predicate::eq(mbid.clone()))
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_| result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn execute_lookup_release_group() {
|
||||||
|
let mut musicbrainz = musicbrainz();
|
||||||
|
let mbid = mbid();
|
||||||
|
let album = COLLECTION[1].albums[0].meta.clone();
|
||||||
|
let lookup = Lookup::new(album.clone());
|
||||||
|
lookup_release_group_expectation(&mut musicbrainz, &mbid, &lookup);
|
||||||
|
|
||||||
|
let mut event_sender = event_sender();
|
||||||
|
fetch_complete_expectation(&mut event_sender, 1);
|
||||||
|
|
||||||
|
let (job_sender, job_receiver) = job_channel();
|
||||||
|
let mut daemon = daemon_with(musicbrainz, job_receiver, event_sender);
|
||||||
|
|
||||||
|
let requests = lookup_release_group_requests();
|
||||||
|
let (result_sender, result_receiver) = mpsc::channel();
|
||||||
|
let result = job_sender.submit_foreground_job(result_sender, requests);
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = daemon.enqueue_all_pending_jobs();
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = daemon.execute_next_job();
|
||||||
|
assert_eq!(result, Ok(()));
|
||||||
|
|
||||||
|
let result = result_receiver.try_recv().unwrap();
|
||||||
|
assert_eq!(result, Ok(MatchStateInfo::album_lookup(album, lookup)));
|
||||||
|
}
|
||||||
|
|
||||||
fn search_artist_expectation(
|
fn search_artist_expectation(
|
||||||
musicbrainz: &mut MockIMusicBrainz,
|
musicbrainz: &mut MockIMusicBrainz,
|
||||||
artist: &ArtistMeta,
|
artist: &ArtistMeta,
|
||||||
@ -531,7 +615,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn execute_search_artist() {
|
fn execute_search_artist() {
|
||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let (artist, matches) = artist_expectations();
|
let (artist, matches) = search_artist_expectations();
|
||||||
search_artist_expectation(&mut musicbrainz, &artist, &matches);
|
search_artist_expectation(&mut musicbrainz, &artist, &matches);
|
||||||
|
|
||||||
let mut event_sender = event_sender();
|
let mut event_sender = event_sender();
|
||||||
@ -575,8 +659,8 @@ mod tests {
|
|||||||
fn execute_search_release_groups() {
|
fn execute_search_release_groups() {
|
||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let arid = album_arid_expectation();
|
let arid = album_arid_expectation();
|
||||||
let (album_1, matches_1) = album_expectations_1();
|
let (album_1, matches_1) = search_album_expectations_1();
|
||||||
let (album_4, matches_4) = album_expectations_4();
|
let (album_4, matches_4) = search_album_expectations_4();
|
||||||
|
|
||||||
let mut seq = Sequence::new();
|
let mut seq = Sequence::new();
|
||||||
search_release_group_expectation(&mut musicbrainz, &mut seq, &arid, &album_1, &matches_1);
|
search_release_group_expectation(&mut musicbrainz, &mut seq, &arid, &album_1, &matches_1);
|
||||||
@ -613,7 +697,7 @@ mod tests {
|
|||||||
fn execute_search_release_groups_result_disconnect() {
|
fn execute_search_release_groups_result_disconnect() {
|
||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let arid = album_arid_expectation();
|
let arid = album_arid_expectation();
|
||||||
let (album_1, matches_1) = album_expectations_1();
|
let (album_1, matches_1) = search_album_expectations_1();
|
||||||
|
|
||||||
let mut seq = Sequence::new();
|
let mut seq = Sequence::new();
|
||||||
search_release_group_expectation(&mut musicbrainz, &mut seq, &arid, &album_1, &matches_1);
|
search_release_group_expectation(&mut musicbrainz, &mut seq, &arid, &album_1, &matches_1);
|
||||||
@ -643,7 +727,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn execute_search_artist_event_disconnect() {
|
fn execute_search_artist_event_disconnect() {
|
||||||
let mut musicbrainz = musicbrainz();
|
let mut musicbrainz = musicbrainz();
|
||||||
let (artist, matches) = artist_expectations();
|
let (artist, matches) = search_artist_expectations();
|
||||||
search_artist_expectation(&mut musicbrainz, &artist, &matches);
|
search_artist_expectation(&mut musicbrainz, &artist, &matches);
|
||||||
|
|
||||||
let mut event_sender = event_sender();
|
let mut event_sender = event_sender();
|
||||||
|
Loading…
Reference in New Issue
Block a user