Provide search functionality through the TUI #134
@ -32,6 +32,7 @@ jobs:
|
|||||||
--output-types html
|
--output-types html
|
||||||
--source-dir .
|
--source-dir .
|
||||||
--ignore-not-existing
|
--ignore-not-existing
|
||||||
|
--ignore "build.rs"
|
||||||
--ignore "tests/*"
|
--ignore "tests/*"
|
||||||
--ignore "src/main.rs"
|
--ignore "src/main.rs"
|
||||||
--ignore "src/bin/musichoard-edit.rs"
|
--ignore "src/bin/musichoard-edit.rs"
|
||||||
|
@ -32,6 +32,7 @@ grcov codecov/debug/profraw \
|
|||||||
--output-types html \
|
--output-types html \
|
||||||
--source-dir . \
|
--source-dir . \
|
||||||
--ignore-not-existing \
|
--ignore-not-existing \
|
||||||
|
--ignore "build.rs" \
|
||||||
--ignore "tests/*" \
|
--ignore "tests/*" \
|
||||||
--ignore "src/main.rs" \
|
--ignore "src/main.rs" \
|
||||||
--ignore "src/bin/musichoard-edit.rs" \
|
--ignore "src/bin/musichoard-edit.rs" \
|
||||||
|
@ -93,9 +93,12 @@ impl<MH: IMusicHoard> IAppInteractBrowse for AppMachine<MH, AppBrowse> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tui::app::{
|
use crate::tui::{
|
||||||
machine::tests::{inner, music_hoard},
|
app::{
|
||||||
IAppInteract,
|
machine::tests::{inner, music_hoard},
|
||||||
|
Category, IAppInteract,
|
||||||
|
},
|
||||||
|
testmod::COLLECTION,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -132,6 +135,49 @@ mod tests {
|
|||||||
app.unwrap_error();
|
app.unwrap_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn increment_decrement() {
|
||||||
|
let mut browse = AppMachine::browse(inner(music_hoard(COLLECTION.to_owned())));
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Artist);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Artist);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(1));
|
||||||
|
|
||||||
|
browse = browse.increment_category().unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Album);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(1));
|
||||||
|
assert_eq!(sel.artist.album.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Album);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(1));
|
||||||
|
assert_eq!(sel.artist.album.state.list.selected(), Some(1));
|
||||||
|
|
||||||
|
browse = browse.decrement_selection(Delta::Line).unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Album);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(1));
|
||||||
|
assert_eq!(sel.artist.album.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
browse = browse.decrement_category().unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Artist);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(1));
|
||||||
|
assert_eq!(sel.artist.album.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
browse = browse.decrement_selection(Delta::Line).unwrap_browse();
|
||||||
|
let sel = &browse.inner.selection;
|
||||||
|
assert_eq!(sel.active, Category::Artist);
|
||||||
|
assert_eq!(sel.artist.state.list.selected(), Some(0));
|
||||||
|
assert_eq!(sel.artist.album.state.list.selected(), Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn show_info_overlay() {
|
fn show_info_overlay() {
|
||||||
let browse = AppMachine::browse(inner(music_hoard(vec![])));
|
let browse = AppMachine::browse(inner(music_hoard(vec![])));
|
||||||
@ -145,4 +191,18 @@ mod tests {
|
|||||||
let app = browse.show_reload_menu();
|
let app = browse.show_reload_menu();
|
||||||
app.unwrap_reload();
|
app.unwrap_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn begin_search() {
|
||||||
|
let browse = AppMachine::browse(inner(music_hoard(vec![])));
|
||||||
|
let app = browse.begin_search();
|
||||||
|
app.unwrap_search();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_op() {
|
||||||
|
let browse = AppMachine::browse(inner(music_hoard(vec![])));
|
||||||
|
let app = browse.no_op();
|
||||||
|
app.unwrap_browse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,4 +56,11 @@ mod tests {
|
|||||||
let app = info.hide_info_overlay();
|
let app = info.hide_info_overlay();
|
||||||
app.unwrap_browse();
|
app.unwrap_browse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_op() {
|
||||||
|
let info = AppMachine::info(inner(music_hoard(vec![])));
|
||||||
|
let app = info.no_op();
|
||||||
|
app.unwrap_info();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,9 +136,8 @@ mod tests {
|
|||||||
use musichoard::collection::Collection;
|
use musichoard::collection::Collection;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{AppState, IAppInteract},
|
app::{AppState, IAppInteract, IAppInteractBrowse},
|
||||||
lib::MockIMusicHoard,
|
lib::MockIMusicHoard,
|
||||||
testmod::COLLECTION,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -214,21 +213,107 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn force_quit() {
|
fn state_browse() {
|
||||||
let app = App::new(music_hoard_init(COLLECTION.to_owned()));
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
assert!(app.is_running());
|
assert!(app.is_running());
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Browse(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Browse(_));
|
||||||
|
|
||||||
let app = app.force_quit();
|
let app = app.force_quit();
|
||||||
assert!(!app.is_running());
|
assert!(!app.is_running());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn error_force_quit() {
|
fn state_info() {
|
||||||
let mut app = App::new(music_hoard_init(COLLECTION.to_owned()));
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
|
assert!(app.is_running());
|
||||||
|
|
||||||
|
app = app.unwrap_browse().show_info_overlay();
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Info(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Info(_));
|
||||||
|
|
||||||
|
let app = app.force_quit();
|
||||||
|
assert!(!app.is_running());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn state_reload() {
|
||||||
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
|
assert!(app.is_running());
|
||||||
|
|
||||||
|
app = app.unwrap_browse().show_reload_menu();
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Reload(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Reload(_));
|
||||||
|
|
||||||
|
let app = app.force_quit();
|
||||||
|
assert!(!app.is_running());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn state_search() {
|
||||||
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
|
assert!(app.is_running());
|
||||||
|
|
||||||
|
app = app.unwrap_browse().begin_search();
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Search(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Search(""));
|
||||||
|
|
||||||
|
let app = app.force_quit();
|
||||||
|
assert!(!app.is_running());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn state_error() {
|
||||||
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
assert!(app.is_running());
|
assert!(app.is_running());
|
||||||
|
|
||||||
app = AppMachine::error(app.unwrap_browse().inner, "get rekt").into();
|
app = AppMachine::error(app.unwrap_browse().inner, "get rekt").into();
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Error(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Error("get rekt"));
|
||||||
|
|
||||||
|
app = app.force_quit();
|
||||||
|
assert!(!app.is_running());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn state_critical() {
|
||||||
|
let mut app = App::new(music_hoard_init(vec![]));
|
||||||
|
assert!(app.is_running());
|
||||||
|
|
||||||
|
app = AppMachine::critical(app.unwrap_browse().inner, "get rekt").into();
|
||||||
|
|
||||||
|
let state = app.state();
|
||||||
|
matches!(state, AppState::Critical(_));
|
||||||
|
app = state;
|
||||||
|
|
||||||
|
let public = app.get();
|
||||||
|
matches!(public.state, AppState::Critical("get rekt"));
|
||||||
|
|
||||||
app = app.force_quit();
|
app = app.force_quit();
|
||||||
assert!(!app.is_running());
|
assert!(!app.is_running());
|
||||||
}
|
}
|
||||||
@ -244,7 +329,6 @@ mod tests {
|
|||||||
music_hoard.expect_get_collection().return_const(vec![]);
|
music_hoard.expect_get_collection().return_const(vec![]);
|
||||||
|
|
||||||
let app = App::new(music_hoard);
|
let app = App::new(music_hoard);
|
||||||
|
|
||||||
assert!(app.is_running());
|
assert!(app.is_running());
|
||||||
app.unwrap_critical();
|
app.unwrap_critical();
|
||||||
}
|
}
|
||||||
|
@ -134,4 +134,11 @@ mod tests {
|
|||||||
let app = reload.reload_database();
|
let app = reload.reload_database();
|
||||||
app.unwrap_error();
|
app.unwrap_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_op() {
|
||||||
|
let reload = AppMachine::reload(inner(music_hoard(vec![])));
|
||||||
|
let app = reload.no_op();
|
||||||
|
app.unwrap_reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +180,14 @@ impl<MH: IMusicHoard> IAppInteractSearchPrivate for AppMachine<MH, AppSearch> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_search(search: &str, lowercase: bool, asciify: bool) -> String {
|
fn normalize_search(search: &str, lowercase: bool, asciify: bool) -> String {
|
||||||
if lowercase {
|
if asciify {
|
||||||
if asciify {
|
if lowercase {
|
||||||
AC.replace_all(&search.to_lowercase(), &REPLACE)
|
AC.replace_all(&search.to_lowercase(), &REPLACE)
|
||||||
} else {
|
} else {
|
||||||
search.to_lowercase()
|
AC.replace_all(search, &REPLACE)
|
||||||
}
|
}
|
||||||
} else if asciify {
|
} else if lowercase {
|
||||||
AC.replace_all(search, &REPLACE)
|
search.to_lowercase()
|
||||||
} else {
|
} else {
|
||||||
search.to_owned()
|
search.to_owned()
|
||||||
}
|
}
|
||||||
@ -282,6 +282,19 @@ mod tests {
|
|||||||
search.incremental_search(false);
|
search.incremental_search(false);
|
||||||
assert_eq!(search.inner.selection.artist.state.list.selected(), Some(2));
|
assert_eq!(search.inner.selection.artist.state.list.selected(), Some(2));
|
||||||
|
|
||||||
|
// Non-lowercase, non-ascii.
|
||||||
|
let mut search =
|
||||||
|
AppMachine::search(inner(music_hoard(COLLECTION.to_owned())), orig(Some(1)));
|
||||||
|
assert_eq!(search.inner.selection.artist.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
search.state.string = String::from("Album_Artist ");
|
||||||
|
search.incremental_search(false);
|
||||||
|
assert_eq!(search.inner.selection.artist.state.list.selected(), Some(0));
|
||||||
|
|
||||||
|
search.state.string = String::from("Album_Artist ‘C’");
|
||||||
|
search.incremental_search(false);
|
||||||
|
assert_eq!(search.inner.selection.artist.state.list.selected(), Some(2));
|
||||||
|
|
||||||
// Stop at name, not sort name.
|
// Stop at name, not sort name.
|
||||||
let mut search =
|
let mut search =
|
||||||
AppMachine::search(inner(music_hoard(COLLECTION.to_owned())), orig(Some(1)));
|
AppMachine::search(inner(music_hoard(COLLECTION.to_owned())), orig(Some(1)));
|
||||||
@ -441,6 +454,13 @@ mod tests {
|
|||||||
let browse = search.cancel_search().unwrap_browse();
|
let browse = search.cancel_search().unwrap_browse();
|
||||||
assert_eq!(browse.inner.selection.artist.state.list.selected(), None);
|
assert_eq!(browse.inner.selection.artist.state.list.selected(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_op() {
|
||||||
|
let search = AppMachine::search(inner(music_hoard(vec![])), orig(None));
|
||||||
|
let app = search.no_op();
|
||||||
|
app.unwrap_search();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nightly)]
|
#[cfg(nightly)]
|
||||||
|
Loading…
Reference in New Issue
Block a user