Skip to content

Commit

Permalink
tests: tests for schema_list
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed Apr 22, 2024
1 parent 1592695 commit eefc2a2
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
reqtui.log
tarpaulin-report.html
mutants.out*
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ tracing-appender = "0.2.3"

[dev-dependencies]
tempfile = "3.10.1"
mutants = "0.0.3"

[[bin]]
name = "rqt"
Expand Down
125 changes: 117 additions & 8 deletions tui/src/components/dashboard/schema_list.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{collections::VecDeque, ops::Add};
use std::{
collections::VecDeque,
ops::{Add, Div, Mul},
};

use ratatui::{
buffer::Buffer,
Expand Down Expand Up @@ -57,11 +60,11 @@ impl<'a> SchemaList<'a> {
}

pub fn items_per_row(&self, size: &Rect) -> usize {
(size.width.saturating_sub(1) / self.min_col_width).into()
(size.width.saturating_sub(1).div(self.min_col_width)).into()
}

pub fn total_rows(&self, size: &Rect) -> usize {
(size.height / self.row_height).into()
(size.height.div(self.row_height)).into()
}

fn build_layout(&self, size: &Rect) -> VecDeque<Rect> {
Expand All @@ -76,7 +79,7 @@ impl<'a> SchemaList<'a> {
.constraints((0..items_per_row).map(|_| Constraint::Min(self.min_col_width)))
.split(Rect::new(
size.x,
size.y + (self.row_height * row as u16),
size.y + (self.row_height.mul(row as u16)),
size.width,
self.row_height,
))
Expand All @@ -99,7 +102,7 @@ impl<'a> SchemaList<'a> {

let border_color = if state
.selected
.is_some_and(|selected| selected.eq(&(index + state.scroll)))
.is_some_and(|selected| selected.eq(&(index.add(state.scroll))))
{
self.colors.bright.magenta
} else {
Expand All @@ -124,19 +127,19 @@ impl StatefulWidget for SchemaList<'_> {
let mut rects = self.build_layout(&list_size);

let mut scrollbar_state =
ScrollbarState::new(state.items.len() / self.items_per_row(&size))
ScrollbarState::new(state.items.len().div(self.items_per_row(&size)))
.position(state.scroll);

let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight)
.style(Style::default().fg(self.colors.normal.magenta.into()))
.begin_symbol(Some("↑"))
.end_symbol(Some("↓"));

let items_on_display = self.items_per_row(&size) * self.total_rows(&size);
let items_on_display = self.items_per_row(&size).mul(self.total_rows(&size));
if let Some(index) = state.selected {
index
.gt(&items_on_display.saturating_sub(1).add(state.scroll))
.then(|| state.scroll += self.items_per_row(&size));
.then(|| state.scroll.add(self.items_per_row(&size)));

state.scroll.gt(&0).then(|| {
index
Expand All @@ -159,3 +162,109 @@ impl StatefulWidget for SchemaList<'_> {
scrollbar.render(scrollbar_size, buf, &mut scrollbar_state);
}
}

#[cfg(test)]
mod tests {
use std::ops::Sub;

use super::*;
use ratatui::{backend::CrosstermBackend, buffer::Cell, Terminal};
use reqtui::schema::types::*;

fn sample_schema() -> Schema {
Schema {
info: Info {
name: String::from("any_name"),
description: None,
},
path: "any_path".into(),
requests: None,
}
}

#[test]
fn test_build_layout() {
let colors = colors::Colors::default();
let schema_list = SchemaList::new(&colors);
let size = Rect::new(0, 0, 31, 10);

let layout = schema_list.build_layout(&size);

assert!(!layout.is_empty());
assert_eq!(layout.len(), 2);
}

#[test]
fn test_items_per_row() {
let colors = colors::Colors::default();
let schema_list = SchemaList::new(&colors);
let zero_items = Rect::new(0, 0, 30, 10);
let one_item = Rect::new(0, 0, 31, 10);

let amount = schema_list.items_per_row(&zero_items);
assert_eq!(amount, 0);

let amount = schema_list.items_per_row(&one_item);
assert_eq!(amount, 1);
}

#[test]
fn test_build_card() {
let colors = colors::Colors::default();
let schema_list = SchemaList::new(&colors);
let schemas = vec![Schema {
info: Info {
name: String::from("any_name"),
description: None,
},
path: "any_path".into(),
requests: None,
}];
let state = SchemaListState::new(schemas.clone());

let lines = vec![
"any_name".fg(colors.normal.white).into(),
"".fg(colors.bright.yellow).into(),
];
let expected = Paragraph::new(lines).block(
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(colors.primary.hover.into())),
);

let card = schema_list.build_card(&state, &schemas[0], 0);

assert_eq!(card, expected);
}

#[test]
fn test_rendering() {
let colors = colors::Colors::default();
let schemas = (0..100).map(|_| sample_schema()).collect::<Vec<_>>();

let backend = CrosstermBackend::new(std::io::stdout());
let mut terminal = Terminal::new(backend).unwrap();
let size = terminal.size().unwrap();
let mut frame = terminal.get_frame();

let mut state = SchemaListState::new(schemas.clone());
let schema_list = SchemaList::new(&colors);

for cell in &frame.buffer_mut().content {
assert_eq!(cell, &Cell::default());
}

schema_list.render(size, frame.buffer_mut(), &mut state);

for cell in frame
.buffer_mut()
.content
.iter()
.skip(size.width.sub(1).into())
.step_by(size.width.into())
{
assert!(cell.symbol().ne(" "));
}
}
}
25 changes: 22 additions & 3 deletions tui/src/event_pool.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crossterm::event::{Event as CrosstermEvent, KeyEventKind};
use futures::{FutureExt, StreamExt};
use ratatui::layout::Rect;
use std::ops::Div;
use tokio::task::JoinHandle;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Event {
Key(crossterm::event::KeyEvent),
Mouse(crossterm::event::MouseEvent),
Expand All @@ -26,6 +27,7 @@ impl EventPool {
pub fn new(tick_rate: f64, frame_rate: f64) -> Self {
let (event_tx, event_rx) = tokio::sync::mpsc::unbounded_channel();
let task = tokio::spawn(async {});

EventPool {
event_rx,
event_tx,
Expand All @@ -35,9 +37,10 @@ impl EventPool {
}
}

#[cfg_attr(test, mutants::skip)]
pub fn start(&mut self) {
let tick_delay = std::time::Duration::from_secs_f64(1.0 / self.tick_rate);
let render_delay = std::time::Duration::from_secs_f64(1.0 / self.frame_rate);
let tick_delay = std::time::Duration::from_secs_f64(1.0.div(self.tick_rate));
let render_delay = std::time::Duration::from_secs_f64(1.0.div(self.frame_rate));

let _event_tx = self.event_tx.clone();
self.task = tokio::spawn(async move {
Expand Down Expand Up @@ -85,3 +88,19 @@ impl EventPool {
self.event_rx.recv().await
}
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_receive_init_event() {
let mut event_pool = EventPool::new(30f64, 60f64);

event_pool.start();
let event = event_pool.next().await;

assert!(event.is_some());
assert_eq!(event, Some(Event::Init));
}
}

0 comments on commit eefc2a2

Please sign in to comment.