feat: add insta snapshot testing for TUI components
- Add insta dev-dependency for visual regression testing - Create lib.rs to expose modules for integration tests - Add snapshot tests for progress_bar, topbar, library, help modal - Add unit tests for LibraryState navigation - Move all tests to tests/ directory (proper Rust convention) - Make build.rs skip proto compilation when protoc unavailable - Add docs/testing-possible-solutions.md with testing strategies
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" "
|
||||
" ┌─ Keybindings · evil-mode (Doom Emacs) ───────────────────────────────────────────────────────┐ "
|
||||
" │Motion · char/line Search & jumps SPC leader (Doom) │ "
|
||||
" │h j k l left / down / up / pat filter library SPC SPC M-x command │ "
|
||||
" │w / W next word / WORD ? pat search backward SPC b +buffer (tabs) │ "
|
||||
" │b / B prev word / WORD n / N next / prev match SPC f +file / library │ "
|
||||
" │e / E end of word / WOR* / # search word fwd/baSPC s +search │ "
|
||||
" │ge / gE back to end of (WC-o / C-i jumplist back / fwSPC w +window / pane │ "
|
||||
" │0 / ^ line start (focusm{a-z} set mark SPC t +toggle / theme │ "
|
||||
" │$ line end (focus r'{a-z} jump to mark line SPC n +notifications │ "
|
||||
" │{N}<motion> repeat motion N t`{a-z} jump to mark exactSPC a +actions / artist│ "
|
||||
" │ '' jump to last positSPC q +quit │ "
|
||||
" │Motion · file/page SPC h +help │ "
|
||||
" │g g first line Center · z_ SPC l/w/h/c → tab quick │ "
|
||||
" │G last line z z / z . center cursor │ "
|
||||
" │{N} G go to line N z t cursor → top Modes & ex commands │ "
|
||||
" │g t / g T next / prev tab z b / z - cursor → bottom :w / :sync save library │ "
|
||||
" │C-d / C-u ½ page down/up :q quit │ "
|
||||
" │C-f / C-b page down/up :theme dark | light │ "
|
||||
" │C-e / C-y scroll line down/ a · t · s · r add·toggle·search│ "
|
||||
" │H / M / L viewport top / mi 1‥6 switch tab │ "
|
||||
" │{ / } paragraph back/fw Enter / Esc open / back │ "
|
||||
" │[[ / ]] section back/fwd ? this help │ "
|
||||
" │[c / ]c prev / next chang │ "
|
||||
" │ │ "
|
||||
" │ │ "
|
||||
" │ │ "
|
||||
" │harmony · v0.4.2 · canonical evil-mode bindings (Vim/Doom Emacs) │ "
|
||||
" └──────────────────────────────────────────────────────────────────────────────────────────────┘ "
|
||||
" "
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" "
|
||||
" ┌─ Keybindings · evil-mode (Doom Emacs) ───────────────┐ "
|
||||
" │Motion · char/lineSearch & jumps SPC leader (Doom) │ "
|
||||
" │h j k l left/ pat filtSPC SPC M-x │ "
|
||||
" │w / W next? pat searSPC b +buf│ "
|
||||
" │b / B prevn / N nextSPC f +fil│ "
|
||||
" │e / E end * / # searSPC s +sea│ "
|
||||
" │ge / gE backC-o / C-i jumpSPC w +win│ "
|
||||
" │0 / ^ linem{a-z} set SPC t +tog│ "
|
||||
" │$ line'{a-z} jumpSPC n +not│ "
|
||||
" │{N}<motion> repe`{a-z} jumpSPC a +act│ "
|
||||
" │ '' jumpSPC q +qui│ "
|
||||
" │Motion · file/page SPC h +hel│ "
|
||||
" │g g firsCenter · z_ SPC l/w/h/c → ta│ "
|
||||
" │G lastz z / z . cent │ "
|
||||
" │{N} G go tz t cursModes & ex command│ "
|
||||
" │g t / g T nextz b / z - curs:w / :sync save│ "
|
||||
" │harmony · v0.4.2 · canonical evil-mode bindings (Vim/D│ "
|
||||
" └──────────────────────────────────────────────────────┘ "
|
||||
" "
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"┌─[ Artists · 2 ]──────────────┐┌─[ Detail · UK · Alternative ]────────────────────────────────────┐"
|
||||
"│◐ Radiohead 17/22 ││Radiohead │"
|
||||
"│! Pink Floyd 0/10 ││ │"
|
||||
"│ ││status ● Monitored path /music/Radiohead │"
|
||||
"│ ││quality FLAC size 2.5 GB │"
|
||||
"│ ││albums 2 tracks 17 / 22 │"
|
||||
"│ ││ │"
|
||||
"│ ││─ albums ─ 2 releases │"
|
||||
"│ ││● OK Computer [Album] 1997 ▰▰▰▰▰▰▰▰▰▰ 12/12 FLAC │"
|
||||
"│ ││◐ Kid A [Album] 2000 ▰▰▰▰▰▱▱▱▱▱ 5/10 FLAC │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││─ tracks · OK Computer ─ 12/12 │"
|
||||
"│ ││(no album selected) │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"└──────────────────────────────┘└──────────────────────────────────────────────────────────────────┘"
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"┌─[ Artists · 0 ]──────────────┐┌─[ Detail · ]────────────────────────────────────────────────────┐"
|
||||
"│ ││No artist selected │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"└──────────────────────────────┘└──────────────────────────────────────────────────────────────────┘"
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"┌─[ Artists · 2 ]──────────────┐┌─[ Detail · UK · Alternative ]────────────────────────────────────┐"
|
||||
"│◐ Radiohead 17/22 ││Radiohead │"
|
||||
"│! Pink Floyd 0/10 ││ │"
|
||||
"│ ││status ● Monitored path /music/Radiohead │"
|
||||
"│ ││quality FLAC size 2.5 GB │"
|
||||
"│ ││albums 2 tracks 17 / 22 │"
|
||||
"│ ││ │"
|
||||
"│ ││─ albums ─ 2 releases │"
|
||||
"│ ││● OK Computer [Album] 1997 ▰▰▰▰▰▰▰▰▰▰ 12/12 FLAC │"
|
||||
"│ ││◐ Kid A [Album] 2000 ▰▰▰▰▰▱▱▱▱▱ 5/10 FLAC │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││─ tracks · OK Computer ─ 12/12 │"
|
||||
"│ ││(no album selected) │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"│ ││ │"
|
||||
"└──────────────────────────────┘└──────────────────────────────────────────────────────────────────┘"
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"▰▰▰▰▰▰▰▰▰▰ "
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"▱▱▱▱▱▱▱▱▱▱ "
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
"▰▰▰▰▰▱▱▱▱▱ "
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" ▲ harmony Library Wanted Queue History Calendar Settings ● Notifications "
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" ▲ harmony Library Wanted Queue History Calendar Settings ● Notifications (5) "
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tests/ui_snapshots.rs
|
||||
expression: terminal.backend()
|
||||
---
|
||||
" ▲ harmony Library Wanted 12 Queue 5 History Calendar Settings ● Notifications (3) "
|
||||
@@ -0,0 +1,245 @@
|
||||
use ratatui::{Terminal, backend::TestBackend, widgets::Paragraph};
|
||||
use ui_agregator::app::Tab;
|
||||
use ui_agregator::data::{Album, AlbumStatus, Artist, MonitorState};
|
||||
use ui_agregator::ui::library::{LibraryFocus, LibraryState, render_library};
|
||||
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,
|
||||
}],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
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 library_snapshots {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn 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 with_artists() {
|
||||
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());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn albums_focused() {
|
||||
let mut terminal = Terminal::new(TestBackend::new(100, 30)).unwrap();
|
||||
let mut state = LibraryState::new(test_artists());
|
||||
state.focus = LibraryFocus::Albums;
|
||||
terminal
|
||||
.draw(|f| {
|
||||
render_library(f, f.area(), &mut state);
|
||||
})
|
||||
.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_state {
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user