More unit testing of tui
This commit is contained in:
parent
230f3cb893
commit
c9c40b3c76
@ -25,10 +25,13 @@ grcov codecov/debug/profraw \
|
|||||||
--ignore-not-existing \
|
--ignore-not-existing \
|
||||||
--ignore "tests/*" \
|
--ignore "tests/*" \
|
||||||
--ignore "src/main.rs" \
|
--ignore "src/main.rs" \
|
||||||
--excl-start "mod tests \{" \
|
--excl-start "mod tests \{|GRCOV_EXCL_START" \
|
||||||
|
--excl-stop "GRCOV_EXCL_STOP" \
|
||||||
--output-path ./codecov/debug/coverage/
|
--output-path ./codecov/debug/coverage/
|
||||||
xdg-open codecov/debug/coverage/index.html
|
xdg-open codecov/debug/coverage/index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that some changes may not be visible until `codecov/debug/coverage` is removed and the `grcov`
|
Note that some changes may not be visible until `codecov/debug/coverage` is removed and the `grcov`
|
||||||
command is rerun.
|
command is rerun.
|
||||||
|
|
||||||
|
For most cases `cargo clean` can be replaced with `rm -rf ./codecov/debug/{coverage,profraw}`.
|
||||||
|
@ -25,7 +25,7 @@ macro_rules! collection {
|
|||||||
"artist a.a.2.1".to_string(),
|
"artist a.a.2.1".to_string(),
|
||||||
"artist a.a.2.2".to_string(),
|
"artist a.a.2.2".to_string(),
|
||||||
],
|
],
|
||||||
format: TrackFormat::Flac,
|
format: TrackFormat::Mp3,
|
||||||
},
|
},
|
||||||
Track {
|
Track {
|
||||||
number: 3,
|
number: 3,
|
||||||
@ -45,7 +45,7 @@ macro_rules! collection {
|
|||||||
number: 1,
|
number: 1,
|
||||||
title: "track a.b.1".to_string(),
|
title: "track a.b.1".to_string(),
|
||||||
artist: vec!["artist a.b.1".to_string()],
|
artist: vec!["artist a.b.1".to_string()],
|
||||||
format: TrackFormat::Mp3,
|
format: TrackFormat::Flac,
|
||||||
},
|
},
|
||||||
Track {
|
Track {
|
||||||
number: 2,
|
number: 2,
|
||||||
@ -148,7 +148,7 @@ macro_rules! collection {
|
|||||||
number: 1,
|
number: 1,
|
||||||
title: "track c.b.1".to_string(),
|
title: "track c.b.1".to_string(),
|
||||||
artist: vec!["artist c.b.1".to_string()],
|
artist: vec!["artist c.b.1".to_string()],
|
||||||
format: TrackFormat::Mp3,
|
format: TrackFormat::Flac,
|
||||||
},
|
},
|
||||||
Track {
|
Track {
|
||||||
number: 2,
|
number: 2,
|
||||||
@ -157,7 +157,7 @@ macro_rules! collection {
|
|||||||
"artist c.b.2.1".to_string(),
|
"artist c.b.2.1".to_string(),
|
||||||
"artist c.b.2.2".to_string(),
|
"artist c.b.2.2".to_string(),
|
||||||
],
|
],
|
||||||
format: TrackFormat::Mp3,
|
format: TrackFormat::Flac,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,6 @@ pub struct EventChannel {
|
|||||||
receiver: mpsc::Receiver<Event>,
|
receiver: mpsc::Receiver<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct EventSender {
|
pub struct EventSender {
|
||||||
sender: mpsc::Sender<Event>,
|
sender: mpsc::Sender<Event>,
|
||||||
}
|
}
|
||||||
@ -89,6 +88,7 @@ pub struct EventListener {
|
|||||||
events: EventSender,
|
events: EventSender,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GRCOV_EXCL_START
|
||||||
impl EventListener {
|
impl EventListener {
|
||||||
pub fn new(events: EventSender) -> EventListener {
|
pub fn new(events: EventSender) -> EventListener {
|
||||||
EventListener { events }
|
EventListener { events }
|
||||||
@ -117,3 +117,42 @@ impl EventListener {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// GRCOV_EXCL_STOP
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
||||||
|
use super::{Event, EventChannel};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn event_sender() {
|
||||||
|
let channel = EventChannel::new();
|
||||||
|
let sender = channel.sender();
|
||||||
|
let receiver = channel.receiver();
|
||||||
|
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
|
||||||
|
|
||||||
|
let result = sender.send(event);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
drop(receiver);
|
||||||
|
let result = sender.send(event);
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn event_receiver() {
|
||||||
|
let channel = EventChannel::new();
|
||||||
|
let sender = channel.sender();
|
||||||
|
let receiver = channel.receiver();
|
||||||
|
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
|
||||||
|
|
||||||
|
sender.send(event).unwrap();
|
||||||
|
let result = receiver.recv();
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
drop(sender);
|
||||||
|
let result = receiver.recv();
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ pub struct EventHandler {
|
|||||||
events: EventReceiver,
|
events: EventReceiver,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GRCOV_EXCL_START
|
||||||
impl EventHandler {
|
impl EventHandler {
|
||||||
pub fn new(events: EventReceiver) -> Self {
|
pub fn new(events: EventReceiver) -> Self {
|
||||||
EventHandler { events }
|
EventHandler { events }
|
||||||
@ -51,3 +52,4 @@ impl EventHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// GRCOV_EXCL_STOP
|
||||||
|
@ -77,7 +77,7 @@ impl<B: Backend> Tui<B> {
|
|||||||
fn run_loop(&mut self) -> Result<(), Error> {
|
fn run_loop(&mut self) -> Result<(), Error> {
|
||||||
while self.app.is_running() {
|
while self.app.is_running() {
|
||||||
self.terminal
|
self.terminal
|
||||||
.draw(|frame| self.ui.render(&mut self.app, frame))?;
|
.draw(|frame| self.ui.render(&self.app, frame))?;
|
||||||
self.handler.handle_next_event(&mut self.app)?;
|
self.handler.handle_next_event(&mut self.app)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,10 +313,6 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<B: Backend>(&mut self, app: &App, frame: &mut Frame<'_, B>) {
|
pub fn render<B: Backend>(&mut self, app: &App, frame: &mut Frame<'_, B>) {
|
||||||
// This is where you add new widgets.
|
|
||||||
// See the following resources:
|
|
||||||
// - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
|
|
||||||
// - https://github.com/tui-rs-revival/ratatui/tree/master/examples
|
|
||||||
let areas = Self::construct_areas(frame.size());
|
let areas = Self::construct_areas(frame.size());
|
||||||
let app_state = Self::construct_app_state(app);
|
let app_state = Self::construct_app_state(app);
|
||||||
|
|
||||||
@ -325,3 +321,65 @@ impl Ui {
|
|||||||
Self::render_track_column(app_state.tracks, areas.tracks, frame);
|
Self::render_track_column(app_state.tracks, areas.tracks, frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
// This is UI so the only sensible unit test is to run the code through various app states.
|
||||||
|
|
||||||
|
use ratatui::{backend::TestBackend, Terminal};
|
||||||
|
|
||||||
|
use crate::{tests::{MockCollectionManager, COLLECTION}, tui::app::App};
|
||||||
|
|
||||||
|
use super::Ui;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty() {
|
||||||
|
let backend = TestBackend::new(150, 30);
|
||||||
|
let mut terminal = Terminal::new(backend).unwrap();
|
||||||
|
|
||||||
|
let mut collection_manager = MockCollectionManager::new();
|
||||||
|
let collection = vec![];
|
||||||
|
|
||||||
|
collection_manager
|
||||||
|
.expect_rescan_library()
|
||||||
|
.returning(|| Ok(()));
|
||||||
|
collection_manager
|
||||||
|
.expect_get_collection()
|
||||||
|
.return_const(collection);
|
||||||
|
|
||||||
|
let app = App::new(Box::new(collection_manager)).unwrap();
|
||||||
|
|
||||||
|
let mut ui = Ui::new();
|
||||||
|
|
||||||
|
terminal.draw(|frame| ui.render(&app, frame)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn collection() {
|
||||||
|
let backend = TestBackend::new(150, 30);
|
||||||
|
let mut terminal = Terminal::new(backend).unwrap();
|
||||||
|
|
||||||
|
let mut collection_manager = MockCollectionManager::new();
|
||||||
|
let collection = COLLECTION.to_owned();
|
||||||
|
|
||||||
|
collection_manager
|
||||||
|
.expect_rescan_library()
|
||||||
|
.returning(|| Ok(()));
|
||||||
|
collection_manager
|
||||||
|
.expect_get_collection()
|
||||||
|
.return_const(collection);
|
||||||
|
|
||||||
|
let mut app = App::new(Box::new(collection_manager)).unwrap();
|
||||||
|
|
||||||
|
let mut ui = Ui::new();
|
||||||
|
|
||||||
|
terminal.draw(|frame| ui.render(&app, frame)).unwrap();
|
||||||
|
|
||||||
|
// Change the track (which has a different track format).
|
||||||
|
app.increment_category();
|
||||||
|
app.increment_category();
|
||||||
|
app.increment_selection();
|
||||||
|
|
||||||
|
terminal.draw(|frame| ui.render(&app, frame)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user