use ratatui::{Terminal, backend::TestBackend, widgets::Paragraph}; 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 { 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 { 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); } }