diff --git a/README.md b/README.md index 30b4483..8acd0c8 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,13 @@ grcov codecov/debug/profraw \ --ignore-not-existing \ --ignore "tests/*" \ --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/ xdg-open codecov/debug/coverage/index.html ``` Note that some changes may not be visible until `codecov/debug/coverage` is removed and the `grcov` command is rerun. + +For most cases `cargo clean` can be replaced with `rm -rf ./codecov/debug/{coverage,profraw}`. diff --git a/src/testing.rs b/src/testing.rs index ffcaaca..cd45baa 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -25,7 +25,7 @@ macro_rules! collection { "artist a.a.2.1".to_string(), "artist a.a.2.2".to_string(), ], - format: TrackFormat::Flac, + format: TrackFormat::Mp3, }, Track { number: 3, @@ -45,7 +45,7 @@ macro_rules! collection { number: 1, title: "track a.b.1".to_string(), artist: vec!["artist a.b.1".to_string()], - format: TrackFormat::Mp3, + format: TrackFormat::Flac, }, Track { number: 2, @@ -148,7 +148,7 @@ macro_rules! collection { number: 1, title: "track c.b.1".to_string(), artist: vec!["artist c.b.1".to_string()], - format: TrackFormat::Mp3, + format: TrackFormat::Flac, }, Track { number: 2, @@ -157,7 +157,7 @@ macro_rules! collection { "artist c.b.2.1".to_string(), "artist c.b.2.2".to_string(), ], - format: TrackFormat::Mp3, + format: TrackFormat::Flac, }, ], }, diff --git a/src/tui/event.rs b/src/tui/event.rs index dae98ea..3aad47d 100644 --- a/src/tui/event.rs +++ b/src/tui/event.rs @@ -45,7 +45,6 @@ pub struct EventChannel { receiver: mpsc::Receiver, } -#[derive(Clone)] pub struct EventSender { sender: mpsc::Sender, } @@ -89,6 +88,7 @@ pub struct EventListener { events: EventSender, } +// GRCOV_EXCL_START impl EventListener { pub fn new(events: EventSender) -> EventListener { 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()); + } +} diff --git a/src/tui/handler.rs b/src/tui/handler.rs index 5d0effc..4d33ef8 100644 --- a/src/tui/handler.rs +++ b/src/tui/handler.rs @@ -6,6 +6,7 @@ pub struct EventHandler { events: EventReceiver, } +// GRCOV_EXCL_START impl EventHandler { pub fn new(events: EventReceiver) -> Self { EventHandler { events } @@ -51,3 +52,4 @@ impl EventHandler { } } } +// GRCOV_EXCL_STOP diff --git a/src/tui/mod.rs b/src/tui/mod.rs index 9056c46..2780675 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -77,7 +77,7 @@ impl Tui { fn run_loop(&mut self) -> Result<(), Error> { while self.app.is_running() { 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)?; } diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 86dd56a..1fe07ce 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -313,10 +313,6 @@ impl Ui { } pub fn render(&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 app_state = Self::construct_app_state(app); @@ -325,3 +321,65 @@ impl Ui { 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(); + } +}