Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tests for widgets #49

Merged
merged 1 commit into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions src/expected_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl ExpectedInput {
let surrounding_symbols = ['[', ']', '{', '}', '(', ')', '"', '"', '\'', '\''];

let mut rng = thread_rng();
let mut str = str
let mut str: Vec<String> = str
.split("\n")
.map(|word| {
let mut word = word.to_string();
Expand Down Expand Up @@ -120,8 +120,7 @@ impl ExpectedInputInterface for ExpectedInput {

#[cfg(test)]
mod tests {
use crate::color_scheme::ColorScheme;
use std::{io::Write, time::Duration};
use std::io::Write;

use super::*;

Expand All @@ -140,17 +139,8 @@ mod tests {
.write_all(r#"halo"#.as_bytes())
.expect("Unable to write to temp file");
let config = Config {
duration: Duration::from_secs(30),
numbers: false,
numbers_ratio: 0.05,
symbols: false,
symbols_ratio: 0.10,
dictionary_path: Some(config_file.path().to_path_buf()),
uppercase: false,
uppercase_ratio: 0.45,
colors: ColorScheme::default(),
save_results: false,
results_path: None,
..Config::default()
};

let expected_input = ExpectedInput::new(&config).expect("unable to create expected input");
Expand Down
184 changes: 118 additions & 66 deletions src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,64 @@ impl<'a, 'b, B: Backend> FrameWrapperInterface for FrameWrapper<'a, 'b, B> {
mod test {
use mockall::predicate;

use crate::expected_input::MockExpectedInputInterface;
use crate::expected_input::{ExpectedInput, MockExpectedInputInterface};
use ratatui::{backend::TestBackend, buffer::Buffer};
use std::io::Write;

use super::*;

fn get_config(dictionary: Vec<&str>) -> (Config, tempfile::NamedTempFile) {
let mut config_file = tempfile::NamedTempFile::new().expect("Unable to create temp file");
config_file
.write_all(dictionary.join(" ").as_bytes())
.expect("Unable to write to temp file");

(
Config {
dictionary_path: Some(config_file.path().to_path_buf()),
..Config::default()
},
config_file, // It keeps tmp file while test is running
)
}

/// Tests the [`Runner`] widget against the expected [`Buffer`] by rendering it onto an equal
/// area and comparing the rendered and expected content.
fn test_runner(
runner: &mut Runner,
expected: Buffer,
callback: fn(frame: &mut FrameWrapper<'_, '_, TestBackend>, runner: &mut Runner) -> (),
) {
let backend = TestBackend::new(expected.area.width, expected.area.height);
let mut terminal = Terminal::new(backend).unwrap();

terminal
.draw(|f| {
let mut frame_wrapper = FrameWrapper::new(f);
callback(&mut frame_wrapper, runner);
})
.unwrap();

terminal.backend().assert_buffer(&expected);
}

fn create_buffer(rect: Rect, lines: Vec<Vec<(&str, Color)>>) -> Buffer {
let mut buffer = Buffer::empty(rect);
for (y, line) in lines.iter().enumerate() {
let mut x: usize = 0;
for (sub_string, color) in line.iter() {
buffer.set_string(x as u16, y as u16, sub_string, Style::default().fg(*color));
x += sub_string.chars().count();
}
}

buffer
}

#[test]
fn should_render_single_line_input() {
let config = Config::default();

let mut expected_input = MockExpectedInputInterface::default();

expected_input
Expand Down Expand Up @@ -511,105 +562,106 @@ mod test {

#[test]
fn should_render_multi_line_input() {
let config = Config::default();
let mut expected_input = MockExpectedInputInterface::default();

expected_input
.expect_get_string()
.with(predicate::eq(4 * 3))
.return_const("foobarbazqux".to_string());
let (config, _config_file) = get_config(vec!["foobarbazquxaboba"]);
let expected_input = ExpectedInput::new(&config).expect("unable to create expected input");

let mut runner = Runner::new(config, expected_input);

runner.input_mode = InputMode::Editing;
runner.input = "foobar".to_string();

let mut frame = MockFrameWrapperInterface::default();
let buffer = create_buffer(
Rect {
x: 0,
y: 0,
width: 50,
height: 3,
},
vec![
vec![
("foobar", Color::Green),
("bazquxaboba foobarbazquxaboba foobarbazquxab", Color::Gray),
],
vec![(
"oba foobarbazquxaboba foobarbazquxaboba foobarbazq",
Color::DarkGray,
)],
vec![
("30 seconds left", Color::Yellow),
(" ", Color::Reset),
("press 'Esc' to pause the test", Color::Yellow),
],
],
);

frame.expect_size().times(2).return_const(Rect {
x: 0,
y: 0,
width: 4,
height: 3,
test_runner(&mut runner, buffer, |frame, runner| {
runner.render(frame, 0);
});

frame
.expect_render_widget::<Paragraph>()
.times(10)
.return_const(());

frame
.expect_set_cursor()
.with(predicate::eq(2), predicate::eq(1))
.times(1)
.return_const(());

runner.render(&mut frame, 0);
}

#[test]
fn should_print_input() {
let config = Config::default();
let expected_input = MockExpectedInputInterface::default();
let (config, _config_file) = get_config(vec!["foo"]);
let expected_input = ExpectedInput::new(&config).expect("unable to create expected input");
let mut runner = Runner::new(config, expected_input);

runner.input = "foo".to_string();

let mut frame = MockFrameWrapperInterface::default();

frame
.expect_render_widget::<Paragraph>()
.times(3)
.return_const(());

runner.print_input(
&mut frame,
"foo",
let buffer = create_buffer(
Rect {
x: 0,
y: 0,
width: 50,
height: 1,
},
50,
vec![vec![("foo", Color::Green)]],
);

test_runner(&mut runner, buffer, |frame, runner| {
runner.print_input(
frame,
"foo",
Rect {
x: 0,
y: 0,
width: 50,
height: 1,
},
50,
);
});
}

#[test]
fn should_print_block_of_text() {
let config = Config::default();
let expected_input = MockExpectedInputInterface::default();
let runner = Runner::new(config, expected_input);

let mut frame = MockFrameWrapperInterface::default();

frame
.expect_render_widget::<Paragraph>()
.withf(|_widget: &Paragraph<'_>, area| {
*area
== Rect {
x: 0,
y: 0,
width: 50,
height: 1,
}
})
.times(1)
.return_const(());
let (config, _config_file) = get_config(vec!["foo"]);
let expected_input = ExpectedInput::new(&config).expect("unable to create expected input");
let mut runner = Runner::new(config, expected_input);

runner.print_block_of_text(
&mut frame,
"foo".to_string(),
let buffer = create_buffer(
Rect {
x: 0,
y: 0,
width: 50,
height: 1,
},
Color::Gray,
false,
false,
vec![vec![("foo", Color::Gray)]],
);

test_runner(&mut runner, buffer, |frame, runner| {
runner.print_block_of_text(
frame,
"foo".to_string(),
Rect {
x: 0,
y: 0,
width: 50,
height: 1,
},
Color::Gray,
false,
false,
);
});
}

#[test]
Expand Down