7a35958c42
- Replace single Detail pane with separate Albums and Tracks panes, each with its own border that highlights yellow when focused - Store rendered Rect areas on LibraryState instead of hardcoding layout offsets, fixing album click selection - Split render functions into public components for isolated testing - Restructure snapshot tests by component (artists, albums, tracks, header, detail) — 13 tests expanded to 26
510 lines
15 KiB
Rust
510 lines
15 KiB
Rust
use ratatui::{backend::TestBackend, widgets::Paragraph, Terminal};
|
|
use ui_agregator::app::Tab;
|
|
use ui_agregator::data::{Album, AlbumStatus, Artist, MonitorState, Track};
|
|
use ui_agregator::ui::library::{
|
|
LibraryFocus, LibraryState, render_albums_list, render_artist_header, render_artists_pane,
|
|
render_detail_pane, render_library, render_tracks_list,
|
|
};
|
|
use ui_agregator::ui::modals::render_help_modal;
|
|
use ui_agregator::ui::progress_bar::progress_bar;
|
|
use ui_agregator::ui::topbar::render_topbar;
|
|
|
|
fn test_artists() -> Vec<Artist> {
|
|
vec![
|
|
Artist {
|
|
id: "1".to_string(),
|
|
name: "Radiohead".to_string(),
|
|
country: "UK".to_string(),
|
|
genres: vec!["Alternative".to_string()],
|
|
monitor_state: MonitorState::Monitored,
|
|
path: "/music/Radiohead".to_string(),
|
|
quality: "FLAC".to_string(),
|
|
size_gb: 2.5,
|
|
albums: vec![
|
|
Album {
|
|
id: "a1".to_string(),
|
|
title: "OK Computer".to_string(),
|
|
year: 1997,
|
|
album_type: "Album".to_string(),
|
|
monitored: true,
|
|
total: 12,
|
|
have: 12,
|
|
quality: "FLAC".to_string(),
|
|
status: AlbumStatus::Complete,
|
|
},
|
|
Album {
|
|
id: "a2".to_string(),
|
|
title: "Kid A".to_string(),
|
|
year: 2000,
|
|
album_type: "Album".to_string(),
|
|
monitored: true,
|
|
total: 10,
|
|
have: 5,
|
|
quality: "FLAC".to_string(),
|
|
status: AlbumStatus::Partial,
|
|
},
|
|
],
|
|
},
|
|
Artist {
|
|
id: "2".to_string(),
|
|
name: "Pink Floyd".to_string(),
|
|
country: "UK".to_string(),
|
|
genres: vec!["Progressive Rock".to_string()],
|
|
monitor_state: MonitorState::Monitored,
|
|
path: "/music/Pink Floyd".to_string(),
|
|
quality: "FLAC".to_string(),
|
|
size_gb: 5.2,
|
|
albums: vec![Album {
|
|
id: "a3".to_string(),
|
|
title: "The Dark Side of the Moon".to_string(),
|
|
year: 1973,
|
|
album_type: "Album".to_string(),
|
|
monitored: true,
|
|
total: 10,
|
|
have: 0,
|
|
quality: "—".to_string(),
|
|
status: AlbumStatus::Wanted,
|
|
}],
|
|
},
|
|
]
|
|
}
|
|
|
|
fn test_tracks() -> Vec<Track> {
|
|
vec![
|
|
Track {
|
|
id: "t1".to_string(),
|
|
number: 1,
|
|
disc: 1,
|
|
title: "Airbag".to_string(),
|
|
duration: "4:44".to_string(),
|
|
have: true,
|
|
quality: "FLAC".to_string(),
|
|
},
|
|
Track {
|
|
id: "t2".to_string(),
|
|
number: 2,
|
|
disc: 1,
|
|
title: "Paranoid Android".to_string(),
|
|
duration: "6:23".to_string(),
|
|
have: true,
|
|
quality: "FLAC".to_string(),
|
|
},
|
|
Track {
|
|
id: "t3".to_string(),
|
|
number: 3,
|
|
disc: 1,
|
|
title: "Subterranean Homesick Alien".to_string(),
|
|
duration: "4:27".to_string(),
|
|
have: false,
|
|
quality: "—".to_string(),
|
|
},
|
|
]
|
|
}
|
|
|
|
mod progress_bar_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn complete() {
|
|
let mut terminal = Terminal::new(TestBackend::new(12, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let bar = progress_bar(10, 10, 10, AlbumStatus::Complete);
|
|
f.render_widget(Paragraph::new(bar), f.area());
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn partial() {
|
|
let mut terminal = Terminal::new(TestBackend::new(12, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let bar = progress_bar(5, 10, 10, AlbumStatus::Partial);
|
|
f.render_widget(Paragraph::new(bar), f.area());
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn empty() {
|
|
let mut terminal = Terminal::new(TestBackend::new(12, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
let bar = progress_bar(0, 10, 10, AlbumStatus::Wanted);
|
|
f.render_widget(Paragraph::new(bar), f.area());
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod topbar_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn library_active() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
render_topbar(f, f.area(), Tab::Library, 0, 0, 0, false);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_badges() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
render_topbar(f, f.area(), Tab::Queue, 5, 12, 3, false);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn notifications_open() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 1)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
render_topbar(f, f.area(), Tab::Library, 0, 0, 5, true);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod help_modal_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn normal_viewport() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 30)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
render_help_modal(f, f.area());
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn small_viewport() {
|
|
let mut terminal = Terminal::new(TestBackend::new(60, 20)).unwrap();
|
|
terminal
|
|
.draw(|f| {
|
|
render_help_modal(f, f.area());
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod library_page_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn full_page_empty() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 30)).unwrap();
|
|
let mut state = LibraryState::new(vec![]);
|
|
terminal
|
|
.draw(|f| render_library(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn full_page_with_data() {
|
|
let mut terminal = Terminal::new(TestBackend::new(100, 30)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
terminal
|
|
.draw(|f| render_library(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod artists_pane_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn empty() {
|
|
let mut terminal = Terminal::new(TestBackend::new(32, 20)).unwrap();
|
|
let mut state = LibraryState::new(vec![]);
|
|
terminal
|
|
.draw(|f| render_artists_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_artists_focused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(32, 20)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.focus = LibraryFocus::Artists;
|
|
terminal
|
|
.draw(|f| render_artists_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_artists_unfocused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(32, 20)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.focus = LibraryFocus::Albums;
|
|
terminal
|
|
.draw(|f| render_artists_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod artist_header_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn monitored_artist() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 6)).unwrap();
|
|
let artists = test_artists();
|
|
terminal
|
|
.draw(|f| render_artist_header(f, f.area(), &artists[0]))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn unmonitored_artist() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 6)).unwrap();
|
|
let artist = Artist {
|
|
id: "3".to_string(),
|
|
name: "Tool".to_string(),
|
|
country: "US".to_string(),
|
|
genres: vec!["Progressive Metal".to_string()],
|
|
monitor_state: MonitorState::Unmonitored,
|
|
path: "/music/Tool".to_string(),
|
|
quality: "FLAC".to_string(),
|
|
size_gb: 3.8,
|
|
albums: vec![],
|
|
};
|
|
terminal
|
|
.draw(|f| render_artist_header(f, f.area(), &artist))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod albums_list_snapshots {
|
|
use super::*;
|
|
use ratatui::widgets::ListState;
|
|
|
|
#[test]
|
|
fn with_albums_focused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 10)).unwrap();
|
|
let artists = test_artists();
|
|
let albums = &artists[0].albums;
|
|
let mut album_state = ListState::default();
|
|
album_state.select(Some(0));
|
|
terminal
|
|
.draw(|f| {
|
|
render_albums_list(
|
|
f,
|
|
f.area(),
|
|
albums,
|
|
LibraryFocus::Albums,
|
|
&mut album_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_albums_unfocused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 10)).unwrap();
|
|
let artists = test_artists();
|
|
let albums = &artists[0].albums;
|
|
let mut album_state = ListState::default();
|
|
album_state.select(Some(0));
|
|
terminal
|
|
.draw(|f| {
|
|
render_albums_list(
|
|
f,
|
|
f.area(),
|
|
albums,
|
|
LibraryFocus::Artists,
|
|
&mut album_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn mixed_statuses() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 10)).unwrap();
|
|
let albums = vec![
|
|
Album {
|
|
id: "1".to_string(),
|
|
title: "Complete Album".to_string(),
|
|
year: 2020,
|
|
album_type: "Album".to_string(),
|
|
monitored: true,
|
|
total: 10,
|
|
have: 10,
|
|
quality: "FLAC".to_string(),
|
|
status: AlbumStatus::Complete,
|
|
},
|
|
Album {
|
|
id: "2".to_string(),
|
|
title: "Wanted Album".to_string(),
|
|
year: 2021,
|
|
album_type: "Album".to_string(),
|
|
monitored: true,
|
|
total: 8,
|
|
have: 0,
|
|
quality: "—".to_string(),
|
|
status: AlbumStatus::Wanted,
|
|
},
|
|
Album {
|
|
id: "3".to_string(),
|
|
title: "Unmonitored Single".to_string(),
|
|
year: 2022,
|
|
album_type: "Single".to_string(),
|
|
monitored: false,
|
|
total: 1,
|
|
have: 0,
|
|
quality: "—".to_string(),
|
|
status: AlbumStatus::Unmonitored,
|
|
},
|
|
];
|
|
let mut album_state = ListState::default();
|
|
album_state.select(Some(1));
|
|
terminal
|
|
.draw(|f| {
|
|
render_albums_list(
|
|
f,
|
|
f.area(),
|
|
&albums,
|
|
LibraryFocus::Albums,
|
|
&mut album_state,
|
|
);
|
|
})
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod tracks_list_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn no_tracks() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 8)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
terminal
|
|
.draw(|f| render_tracks_list(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_tracks_focused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 8)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.tracks = test_tracks();
|
|
state.focus = LibraryFocus::Tracks;
|
|
terminal
|
|
.draw(|f| render_tracks_list(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_tracks_unfocused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 8)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.tracks = test_tracks();
|
|
state.focus = LibraryFocus::Artists;
|
|
terminal
|
|
.draw(|f| render_tracks_list(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod detail_pane_snapshots {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn no_artist_selected() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 24)).unwrap();
|
|
let mut state = LibraryState::new(vec![]);
|
|
terminal
|
|
.draw(|f| render_detail_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_artist_albums_focused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 24)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.focus = LibraryFocus::Albums;
|
|
terminal
|
|
.draw(|f| render_detail_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
|
|
#[test]
|
|
fn with_artist_tracks_focused() {
|
|
let mut terminal = Terminal::new(TestBackend::new(68, 24)).unwrap();
|
|
let mut state = LibraryState::new(test_artists());
|
|
state.tracks = test_tracks();
|
|
state.focus = LibraryFocus::Tracks;
|
|
terminal
|
|
.draw(|f| render_detail_pane(f, f.area(), &mut state))
|
|
.unwrap();
|
|
insta::assert_snapshot!(terminal.backend());
|
|
}
|
|
}
|
|
|
|
mod library_state_tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn navigation() {
|
|
let mut state = LibraryState::new(test_artists());
|
|
|
|
assert_eq!(state.selected_artist_index(), Some(0));
|
|
assert_eq!(state.focus, LibraryFocus::Artists);
|
|
|
|
state.move_down();
|
|
assert_eq!(state.selected_artist_index(), Some(1));
|
|
|
|
state.focus_right();
|
|
assert_eq!(state.focus, LibraryFocus::Albums);
|
|
|
|
state.focus_left();
|
|
assert_eq!(state.focus, LibraryFocus::Artists);
|
|
}
|
|
|
|
#[test]
|
|
fn cycle_focus() {
|
|
let mut state = LibraryState::new(test_artists());
|
|
|
|
assert_eq!(state.focus, LibraryFocus::Artists);
|
|
state.cycle_focus();
|
|
assert_eq!(state.focus, LibraryFocus::Albums);
|
|
state.cycle_focus();
|
|
assert_eq!(state.focus, LibraryFocus::Tracks);
|
|
state.cycle_focus();
|
|
assert_eq!(state.focus, LibraryFocus::Artists);
|
|
}
|
|
}
|