Use a queue to communicate matches from browse to matches (#207)
Closes #202 Reviewed-on: #207
This commit is contained in:
parent
cda1487734
commit
6333b7a131
@ -1,4 +1,4 @@
|
|||||||
use std::{thread, time};
|
use std::{sync::mpsc, thread, time};
|
||||||
|
|
||||||
use musichoard::collection::musicbrainz::IMusicBrainzRef;
|
use musichoard::collection::musicbrainz::IMusicBrainzRef;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut matches = vec![];
|
let (matches_tx, matches_rx) = mpsc::channel::<AppMatchesInfo>();
|
||||||
|
|
||||||
match artist.musicbrainz {
|
match artist.musicbrainz {
|
||||||
Some(ref mbid) => {
|
Some(ref mbid) => {
|
||||||
@ -104,7 +104,9 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.inner.musicbrainz.search_release_group(arid, album) {
|
match self.inner.musicbrainz.search_release_group(arid, album) {
|
||||||
Ok(list) => matches.push(AppMatchesInfo::album(album.clone(), list)),
|
Ok(list) => matches_tx
|
||||||
|
.send(AppMatchesInfo::album(album.clone(), list))
|
||||||
|
.expect("send fails only if receiver is disconnected"),
|
||||||
Err(err) => return AppMachine::error(self.inner, err.to_string()).into(),
|
Err(err) => return AppMachine::error(self.inner, err.to_string()).into(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,12 +116,14 @@ impl IAppInteractBrowse for AppMachine<AppBrowse> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => match self.inner.musicbrainz.search_artist(artist) {
|
None => match self.inner.musicbrainz.search_artist(artist) {
|
||||||
Ok(list) => matches.push(AppMatchesInfo::artist(artist.clone(), list)),
|
Ok(list) => matches_tx
|
||||||
|
.send(AppMatchesInfo::artist(artist.clone(), list))
|
||||||
|
.expect("send fails only if receiver is disconnected"),
|
||||||
Err(err) => return AppMachine::error(self.inner, err.to_string()).into(),
|
Err(err) => return AppMachine::error(self.inner, err.to_string()).into(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
AppMachine::matches(self.inner, matches).into()
|
AppMachine::matches(self.inner, matches_rx).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn no_op(self) -> Self::APP {
|
fn no_op(self) -> Self::APP {
|
||||||
@ -135,7 +139,8 @@ mod tests {
|
|||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
machine::tests::{inner, inner_with_mb, music_hoard},
|
machine::tests::{inner, inner_with_mb, music_hoard},
|
||||||
Category, IAppAccess, IAppInteract, IAppInteractMatches,
|
AppPublicAlbumMatches, AppPublicArtistMatches, AppPublicMatchesInfo, Category,
|
||||||
|
IAppAccess, IAppInteract, IAppInteractMatches,
|
||||||
},
|
},
|
||||||
lib::interface::musicbrainz::{self, Match, MockIMusicBrainz},
|
lib::interface::musicbrainz::{self, Match, MockIMusicBrainz},
|
||||||
testmod::COLLECTION,
|
testmod::COLLECTION,
|
||||||
@ -258,19 +263,11 @@ mod tests {
|
|||||||
|
|
||||||
let public_matches = public.state.unwrap_matches();
|
let public_matches = public.state.unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(
|
let expected = Some(AppPublicMatchesInfo::Album(AppPublicAlbumMatches {
|
||||||
public_matches
|
matching: &album_1,
|
||||||
.matches
|
list: &matches_1,
|
||||||
.as_ref()
|
}));
|
||||||
.unwrap()
|
assert_eq!(public_matches.matches, expected);
|
||||||
.album_ref()
|
|
||||||
.matching,
|
|
||||||
&album_1
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
public_matches.matches.as_ref().unwrap().album_ref().list,
|
|
||||||
matches_1.as_slice()
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut app = app.unwrap_matches().select();
|
let mut app = app.unwrap_matches().select();
|
||||||
|
|
||||||
@ -279,19 +276,11 @@ mod tests {
|
|||||||
|
|
||||||
let public_matches = public.state.unwrap_matches();
|
let public_matches = public.state.unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(
|
let expected = Some(AppPublicMatchesInfo::Album(AppPublicAlbumMatches {
|
||||||
public_matches
|
matching: &album_4,
|
||||||
.matches
|
list: &matches_4,
|
||||||
.as_ref()
|
}));
|
||||||
.unwrap()
|
assert_eq!(public_matches.matches, expected);
|
||||||
.album_ref()
|
|
||||||
.matching,
|
|
||||||
&album_4
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
public_matches.matches.as_ref().unwrap().album_ref().list,
|
|
||||||
matches_4.as_slice()
|
|
||||||
);
|
|
||||||
|
|
||||||
let app = app.unwrap_matches().select();
|
let app = app.unwrap_matches().select();
|
||||||
app.unwrap_browse();
|
app.unwrap_browse();
|
||||||
@ -335,19 +324,11 @@ mod tests {
|
|||||||
|
|
||||||
let public_matches = public.state.unwrap_matches();
|
let public_matches = public.state.unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(
|
let expected = Some(AppPublicMatchesInfo::Artist(AppPublicArtistMatches {
|
||||||
public_matches
|
matching: &artist,
|
||||||
.matches
|
list: &matches,
|
||||||
.as_ref()
|
}));
|
||||||
.unwrap()
|
assert_eq!(public_matches.matches, expected);
|
||||||
.artist_ref()
|
|
||||||
.matching,
|
|
||||||
&artist
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
public_matches.matches.as_ref().unwrap().artist_ref().list,
|
|
||||||
matches.as_slice()
|
|
||||||
);
|
|
||||||
|
|
||||||
let app = app.unwrap_matches().select();
|
let app = app.unwrap_matches().select();
|
||||||
app.unwrap_browse();
|
app.unwrap_browse();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::cmp;
|
use std::{cmp, sync::mpsc};
|
||||||
|
|
||||||
use musichoard::collection::{album::Album, artist::Artist};
|
use musichoard::collection::{album::Album, artist::Artist};
|
||||||
|
|
||||||
@ -101,30 +101,20 @@ impl<'app> From<&'app AppMatchesInfo> for AppPublicMatchesInfo<'app> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppMatches {
|
pub struct AppMatches {
|
||||||
matches_info_vec: Vec<AppMatchesInfo>,
|
matches_rx: mpsc::Receiver<AppMatchesInfo>,
|
||||||
index: Option<usize>,
|
current: Option<AppMatchesInfo>,
|
||||||
state: WidgetState,
|
state: WidgetState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppMachine<AppMatches> {
|
impl AppMachine<AppMatches> {
|
||||||
pub fn matches(inner: AppInner, matches_info_vec: Vec<AppMatchesInfo>) -> Self {
|
pub fn matches(inner: AppInner, matches_rx: mpsc::Receiver<AppMatchesInfo>) -> Self {
|
||||||
let mut index = None;
|
let mut state = AppMatches {
|
||||||
let mut state = WidgetState::default();
|
matches_rx,
|
||||||
if let Some(matches_info) = matches_info_vec.first() {
|
current: None,
|
||||||
index = Some(0);
|
state: WidgetState::default(),
|
||||||
if !matches_info.is_empty() {
|
};
|
||||||
state.list.select(Some(0));
|
state.next_matches_info();
|
||||||
}
|
AppMachine { inner, state }
|
||||||
}
|
|
||||||
|
|
||||||
AppMachine {
|
|
||||||
inner,
|
|
||||||
state: AppMatches {
|
|
||||||
matches_info_vec,
|
|
||||||
index,
|
|
||||||
state,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,15 +126,10 @@ impl From<AppMachine<AppMatches>> for App {
|
|||||||
|
|
||||||
impl<'a> From<&'a mut AppMachine<AppMatches>> for AppPublic<'a> {
|
impl<'a> From<&'a mut AppMachine<AppMatches>> for AppPublic<'a> {
|
||||||
fn from(machine: &'a mut AppMachine<AppMatches>) -> Self {
|
fn from(machine: &'a mut AppMachine<AppMatches>) -> Self {
|
||||||
let matches = machine
|
|
||||||
.state
|
|
||||||
.index
|
|
||||||
.map(|index| (&machine.state.matches_info_vec[index]).into());
|
|
||||||
|
|
||||||
AppPublic {
|
AppPublic {
|
||||||
inner: (&mut machine.inner).into(),
|
inner: (&mut machine.inner).into(),
|
||||||
state: AppState::Matches(AppPublicMatches {
|
state: AppState::Matches(AppPublicMatches {
|
||||||
matches,
|
matches: machine.state.current.as_ref().map(Into::into),
|
||||||
state: &mut machine.state.state,
|
state: &mut machine.state.state,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@ -155,8 +140,8 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
|||||||
type APP = App;
|
type APP = App;
|
||||||
|
|
||||||
fn prev_match(mut self) -> Self::APP {
|
fn prev_match(mut self) -> Self::APP {
|
||||||
if let Some(list_index) = self.state.state.list.selected() {
|
if let Some(index) = self.state.state.list.selected() {
|
||||||
let result = list_index.saturating_sub(1);
|
let result = index.saturating_sub(1);
|
||||||
self.state.state.list.select(Some(result));
|
self.state.state.list.select(Some(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,13 +149,12 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_match(mut self) -> Self::APP {
|
fn next_match(mut self) -> Self::APP {
|
||||||
if let Some(list_index) = self.state.state.list.selected() {
|
if let Some(index) = self.state.state.list.selected() {
|
||||||
let result = list_index.saturating_add(1);
|
let result = index.saturating_add(1);
|
||||||
let to = cmp::min(
|
let to = cmp::min(
|
||||||
result,
|
result,
|
||||||
self.state.matches_info_vec[self.state.index.unwrap()]
|
// selected() implies current exists
|
||||||
.len()
|
self.state.current.as_ref().unwrap().len().saturating_sub(1),
|
||||||
.saturating_sub(1),
|
|
||||||
);
|
);
|
||||||
self.state.state.list.select(Some(to));
|
self.state.state.list.select(Some(to));
|
||||||
}
|
}
|
||||||
@ -179,18 +163,17 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn select(mut self) -> Self::APP {
|
fn select(mut self) -> Self::APP {
|
||||||
self.state.index = self.state.index.map(|i| i.saturating_add(1));
|
self.state.next_matches_info();
|
||||||
self.state.state = WidgetState::default();
|
match self.state.current {
|
||||||
if let Some(index) = self.state.index {
|
Some(ref matches_info) => {
|
||||||
if let Some(matches_info) = self.state.matches_info_vec.get(index) {
|
self.state.state = WidgetState::default();
|
||||||
if !matches_info.is_empty() {
|
if !matches_info.is_empty() {
|
||||||
self.state.state.list.select(Some(0));
|
self.state.state.list.select(Some(0));
|
||||||
}
|
}
|
||||||
return self.into();
|
self.into()
|
||||||
}
|
}
|
||||||
|
None => AppMachine::browse(self.inner).into(),
|
||||||
}
|
}
|
||||||
|
|
||||||
AppMachine::browse(self.inner).into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abort(self) -> Self::APP {
|
fn abort(self) -> Self::APP {
|
||||||
@ -202,8 +185,29 @@ impl IAppInteractMatches for AppMachine<AppMatches> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait IAppInteractMatchesPrivate {
|
||||||
|
fn next_matches_info(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IAppInteractMatchesPrivate for AppMatches {
|
||||||
|
fn next_matches_info(&mut self) {
|
||||||
|
// FIXME: try_recv might not be appropriate for asynchronous version.
|
||||||
|
(self.current, self.state) = match self.matches_rx.try_recv() {
|
||||||
|
Ok(next_match) => {
|
||||||
|
let mut state = WidgetState::default();
|
||||||
|
if !next_match.is_empty() {
|
||||||
|
state.list.select(Some(0));
|
||||||
|
}
|
||||||
|
(Some(next_match), state)
|
||||||
|
}
|
||||||
|
Err(_) => (None, WidgetState::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use mpsc::Receiver;
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{AlbumDate, AlbumId, AlbumPrimaryType, AlbumSecondaryType},
|
album::{AlbumDate, AlbumId, AlbumPrimaryType, AlbumSecondaryType},
|
||||||
artist::ArtistId,
|
artist::ArtistId,
|
||||||
@ -216,15 +220,6 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl AppMatchesInfo {
|
|
||||||
fn album_ref(&self) -> &AppAlbumMatchesInfo {
|
|
||||||
match self {
|
|
||||||
Self::Album(a) => a,
|
|
||||||
Self::Artist(_) => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn artist_matches_info_vec() -> Vec<AppMatchesInfo> {
|
fn artist_matches_info_vec() -> Vec<AppMatchesInfo> {
|
||||||
let artist_1 = Artist::new(ArtistId::new("Artist 1"));
|
let artist_1 = Artist::new(ArtistId::new("Artist 1"));
|
||||||
|
|
||||||
@ -284,14 +279,21 @@ mod tests {
|
|||||||
vec![matches_info_1, matches_info_2]
|
vec![matches_info_1, matches_info_2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn receiver(matches_info_vec: Vec<AppMatchesInfo>) -> Receiver<AppMatchesInfo> {
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
for matches_info in matches_info_vec.into_iter() {
|
||||||
|
tx.send(matches_info).unwrap();
|
||||||
|
}
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_empty() {
|
fn create_empty() {
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), vec![]);
|
let matches = AppMachine::matches(inner(music_hoard(vec![])), receiver(vec![]));
|
||||||
|
|
||||||
let widget_state = WidgetState::default();
|
let widget_state = WidgetState::default();
|
||||||
|
|
||||||
assert_eq!(matches.state.matches_info_vec, vec![]);
|
assert_eq!(matches.state.current, None);
|
||||||
assert_eq!(matches.state.index, None);
|
|
||||||
assert_eq!(matches.state.state, widget_state);
|
assert_eq!(matches.state.state, widget_state);
|
||||||
|
|
||||||
let mut app = matches.no_op();
|
let mut app = matches.no_op();
|
||||||
@ -305,63 +307,55 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn create_nonempty() {
|
fn create_nonempty() {
|
||||||
let matches_info_vec = album_matches_info_vec();
|
let matches_info_vec = album_matches_info_vec();
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
let matches = AppMachine::matches(
|
||||||
|
inner(music_hoard(vec![])),
|
||||||
|
receiver(matches_info_vec.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut widget_state = WidgetState::default();
|
let mut widget_state = WidgetState::default();
|
||||||
widget_state.list.select(Some(0));
|
widget_state.list.select(Some(0));
|
||||||
|
|
||||||
assert_eq!(matches.state.matches_info_vec, matches_info_vec);
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.index, Some(0));
|
|
||||||
assert_eq!(matches.state.state, widget_state);
|
assert_eq!(matches.state.state, widget_state);
|
||||||
|
|
||||||
let mut app = matches.no_op();
|
let mut app = matches.no_op();
|
||||||
let public = app.get();
|
let public = app.get();
|
||||||
let public_matches = public.state.unwrap_matches();
|
let public_matches = public.state.unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(public_matches.matches, Some((&matches_info_vec[0]).into()));
|
||||||
public_matches
|
|
||||||
.matches
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.album_ref()
|
|
||||||
.matching,
|
|
||||||
&matches_info_vec[0].album_ref().matching
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
public_matches.matches.as_ref().unwrap().album_ref().list,
|
|
||||||
matches_info_vec[0].album_ref().list.as_slice()
|
|
||||||
);
|
|
||||||
assert_eq!(public_matches.state, &widget_state);
|
assert_eq!(public_matches.state, &widget_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_flow(matches_info_vec: Vec<AppMatchesInfo>) {
|
fn matches_flow(matches_info_vec: Vec<AppMatchesInfo>) {
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
let matches = AppMachine::matches(
|
||||||
|
inner(music_hoard(vec![])),
|
||||||
|
receiver(matches_info_vec.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut widget_state = WidgetState::default();
|
let mut widget_state = WidgetState::default();
|
||||||
widget_state.list.select(Some(0));
|
widget_state.list.select(Some(0));
|
||||||
|
|
||||||
assert_eq!(matches.state.matches_info_vec, matches_info_vec);
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.index, Some(0));
|
|
||||||
assert_eq!(matches.state.state, widget_state);
|
assert_eq!(matches.state.state, widget_state);
|
||||||
|
|
||||||
let matches = matches.prev_match().unwrap_matches();
|
let matches = matches.prev_match().unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(matches.state.index, Some(0));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(0));
|
assert_eq!(matches.state.state.list.selected(), Some(0));
|
||||||
|
|
||||||
let matches = matches.next_match().unwrap_matches();
|
let matches = matches.next_match().unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(matches.state.index, Some(0));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(1));
|
assert_eq!(matches.state.state.list.selected(), Some(1));
|
||||||
|
|
||||||
let matches = matches.next_match().unwrap_matches();
|
let matches = matches.next_match().unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(matches.state.index, Some(0));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(1));
|
assert_eq!(matches.state.state.list.selected(), Some(1));
|
||||||
|
|
||||||
let matches = matches.select().unwrap_matches();
|
let matches = matches.select().unwrap_matches();
|
||||||
|
|
||||||
assert_eq!(matches.state.index, Some(1));
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[1]));
|
||||||
assert_eq!(matches.state.state.list.selected(), Some(0));
|
assert_eq!(matches.state.state.list.selected(), Some(0));
|
||||||
|
|
||||||
// And it's done
|
// And it's done
|
||||||
@ -381,13 +375,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn matches_abort() {
|
fn matches_abort() {
|
||||||
let matches_info_vec = album_matches_info_vec();
|
let matches_info_vec = album_matches_info_vec();
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), matches_info_vec.clone());
|
let matches = AppMachine::matches(
|
||||||
|
inner(music_hoard(vec![])),
|
||||||
|
receiver(matches_info_vec.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut widget_state = WidgetState::default();
|
let mut widget_state = WidgetState::default();
|
||||||
widget_state.list.select(Some(0));
|
widget_state.list.select(Some(0));
|
||||||
|
|
||||||
assert_eq!(matches.state.matches_info_vec, matches_info_vec);
|
assert_eq!(matches.state.current.as_ref(), Some(&matches_info_vec[0]));
|
||||||
assert_eq!(matches.state.index, Some(0));
|
|
||||||
assert_eq!(matches.state.state, widget_state);
|
assert_eq!(matches.state.state, widget_state);
|
||||||
|
|
||||||
matches.abort().unwrap_browse();
|
matches.abort().unwrap_browse();
|
||||||
@ -395,17 +391,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn matches_select_empty() {
|
fn matches_select_empty() {
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), vec![]);
|
let matches = AppMachine::matches(inner(music_hoard(vec![])), receiver(vec![]));
|
||||||
|
|
||||||
assert_eq!(matches.state.matches_info_vec, vec![]);
|
assert_eq!(matches.state.current, None);
|
||||||
assert_eq!(matches.state.index, None);
|
|
||||||
|
|
||||||
matches.select().unwrap_browse();
|
matches.select().unwrap_browse();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_op() {
|
fn no_op() {
|
||||||
let matches = AppMachine::matches(inner(music_hoard(vec![])), vec![]);
|
let matches = AppMachine::matches(inner(music_hoard(vec![])), receiver(vec![]));
|
||||||
let app = matches.no_op();
|
let app = matches.no_op();
|
||||||
app.unwrap_matches();
|
app.unwrap_matches();
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,8 @@ impl<'a> From<&'a mut AppInner> for AppPublicInner<'a> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use musichoard::collection::Collection;
|
use musichoard::collection::Collection;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
@ -311,7 +313,8 @@ mod tests {
|
|||||||
let mut app = App::new(music_hoard_init(vec![]), mb_api());
|
let mut app = App::new(music_hoard_init(vec![]), mb_api());
|
||||||
assert!(app.is_running());
|
assert!(app.is_running());
|
||||||
|
|
||||||
app = AppMachine::matches(app.unwrap_browse().inner, vec![]).into();
|
let (_, rx) = mpsc::channel();
|
||||||
|
app = AppMachine::matches(app.unwrap_browse().inner, rx).into();
|
||||||
|
|
||||||
let state = app.state();
|
let state = app.state();
|
||||||
assert!(matches!(state, AppState::Matches(_)));
|
assert!(matches!(state, AppState::Matches(_)));
|
||||||
|
@ -165,22 +165,6 @@ impl<BS, IS, RS, SS, MS, ES, CS> AppState<BS, IS, RS, SS, MS, ES, CS> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<'app> AppPublicMatchesInfo<'app> {
|
|
||||||
pub fn artist_ref(&self) -> &AppPublicArtistMatches<'app> {
|
|
||||||
match self {
|
|
||||||
Self::Artist(m) => m,
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn album_ref(&self) -> &AppPublicAlbumMatches<'app> {
|
|
||||||
match self {
|
|
||||||
Self::Album(m) => m,
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_is_state() {
|
fn app_is_state() {
|
||||||
let state = AppPublicState::Search("get rekt");
|
let state = AppPublicState::Search("get rekt");
|
||||||
|
Loading…
Reference in New Issue
Block a user