Provide search functionality through the TUI #134

Merged
wojtek merged 35 commits from 24---provide-search-functionality-through-the-tui into main 2024-02-18 22:12:42 +01:00
7 changed files with 195 additions and 15 deletions
Showing only changes of commit 68b70f6b04 - Show all commits

View File

@ -32,6 +32,7 @@ jobs:
--output-types html
--source-dir .
--ignore-not-existing
--ignore "build.rs"
--ignore "tests/*"
--ignore "src/main.rs"
--ignore "src/bin/musichoard-edit.rs"

View File

@ -32,6 +32,7 @@ grcov codecov/debug/profraw \
--output-types html \
--source-dir . \
--ignore-not-existing \
--ignore "build.rs" \
--ignore "tests/*" \
--ignore "src/main.rs" \
--ignore "src/bin/musichoard-edit.rs" \

View File

@ -93,9 +93,12 @@ impl<MH: IMusicHoard> IAppInteractBrowse for AppMachine<MH, AppBrowse> {
#[cfg(test)]
mod tests {
use crate::tui::app::{
use crate::tui::{
app::{
machine::tests::{inner, music_hoard},
IAppInteract,
Category, IAppInteract,
},
testmod::COLLECTION,
};
use super::*;
@ -132,6 +135,49 @@ mod tests {
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]
fn show_info_overlay() {
let browse = AppMachine::browse(inner(music_hoard(vec![])));
@ -145,4 +191,18 @@ mod tests {
let app = browse.show_reload_menu();
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();
}
}

View File

@ -56,4 +56,11 @@ mod tests {
let app = info.hide_info_overlay();
app.unwrap_browse();
}
#[test]
fn no_op() {
let info = AppMachine::info(inner(music_hoard(vec![])));
let app = info.no_op();
app.unwrap_info();
}
}

View File

@ -136,9 +136,8 @@ mod tests {
use musichoard::collection::Collection;
use crate::tui::{
app::{AppState, IAppInteract},
app::{AppState, IAppInteract, IAppInteractBrowse},
lib::MockIMusicHoard,
testmod::COLLECTION,
};
use super::*;
@ -214,21 +213,107 @@ mod tests {
}
#[test]
fn force_quit() {
let app = App::new(music_hoard_init(COLLECTION.to_owned()));
fn state_browse() {
let mut app = App::new(music_hoard_init(vec![]));
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();
assert!(!app.is_running());
}
#[test]
fn error_force_quit() {
let mut app = App::new(music_hoard_init(COLLECTION.to_owned()));
fn state_info() {
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());
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();
assert!(!app.is_running());
}
@ -244,7 +329,6 @@ mod tests {
music_hoard.expect_get_collection().return_const(vec![]);
let app = App::new(music_hoard);
assert!(app.is_running());
app.unwrap_critical();
}

View File

@ -134,4 +134,11 @@ mod tests {
let app = reload.reload_database();
app.unwrap_error();
}
#[test]
fn no_op() {
let reload = AppMachine::reload(inner(music_hoard(vec![])));
let app = reload.no_op();
app.unwrap_reload();
}
}

View File

@ -180,14 +180,14 @@ impl<MH: IMusicHoard> IAppInteractSearchPrivate for AppMachine<MH, AppSearch> {
}
fn normalize_search(search: &str, lowercase: bool, asciify: bool) -> String {
if lowercase {
if asciify {
if lowercase {
AC.replace_all(&search.to_lowercase(), &REPLACE)
} else {
search.to_lowercase()
}
} else if asciify {
AC.replace_all(search, &REPLACE)
}
} else if lowercase {
search.to_lowercase()
} else {
search.to_owned()
}
@ -282,6 +282,19 @@ mod tests {
search.incremental_search(false);
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.
let mut search =
AppMachine::search(inner(music_hoard(COLLECTION.to_owned())), orig(Some(1)));
@ -441,6 +454,13 @@ mod tests {
let browse = search.cancel_search().unwrap_browse();
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)]