Files
oxkerclone/src/ui/draw_blocks/commands.rs
T
Jack Wills 9362d7b481 test: Use insta, closes #57
Use insta for UI tests, adds snapshots of UI layout
2025-04-16 11:24:08 +00:00

404 lines
13 KiB
Rust

use std::sync::Arc;
use super::RIGHT_ARROW;
use crate::{
app_data::AppData,
config::AppColors,
ui::{FrameData, GuiState, SelectablePanel},
};
use parking_lot::Mutex;
use ratatui::{
Frame,
layout::{Alignment, Rect},
style::{Modifier, Style, Stylize},
text::{Line, Span},
widgets::{List, ListItem, Paragraph},
};
use super::generate_block;
/// Draw the command panel
pub fn draw(
app_data: &Arc<Mutex<AppData>>,
area: Rect,
colors: AppColors,
f: &mut Frame,
fd: &FrameData,
gui_state: &Arc<Mutex<GuiState>>,
) {
let block = generate_block(area, colors, fd, gui_state, SelectablePanel::Commands)
.bg(colors.commands.background);
let items = app_data.lock().get_control_items().map_or(vec![], |i| {
i.iter()
.map(|c| {
let lines = Line::from(vec![Span::styled(
c.to_string(),
Style::default().fg(c.get_color(colors)),
)]);
ListItem::new(lines)
})
.collect::<Vec<_>>()
});
if let Some(i) = app_data.lock().get_control_state() {
let items = List::new(items)
.block(block)
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol(RIGHT_ARROW);
f.render_stateful_widget(items, area, i);
} else {
let paragraph = Paragraph::new("").block(block).alignment(Alignment::Center);
f.render_widget(paragraph, area);
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier};
use crate::{
config::AppColors,
tests::gen_container_summary,
ui::{
FrameData,
draw_blocks::tests::{BORDER_CHARS, get_result, test_setup},
},
};
// cusomt border colors
#[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this case, no commands are drawn
fn test_draw_blocks_commands_none() {
let mut setup = test_setup(12, 6, false, false);
let colors = setup.app_data.lock().config.app_colors;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
}
#[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this test, container is running
fn test_draw_blocks_commands_some() {
let mut setup = test_setup(12, 6, true, true);
let colors = setup.app_data.lock().config.app_colors;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.bg, Color::Reset);
match (row_index, result_cell_index) {
// Borders & delete
(0 | 5, _) | (1..=4, 0 | 11) | (4, 3..=8) => {
assert_eq!(result_cell.fg, Color::Gray);
}
// pause
(1, 3..=7) => {
assert_eq!(result_cell.fg, Color::Yellow);
}
// restart
(2, 3..=9) => {
assert_eq!(result_cell.fg, Color::Magenta);
}
// stop
(3, 3..=6) => {
assert_eq!(result_cell.fg, Color::Red);
}
_ => {
assert_eq!(result_cell.fg, Color::Reset);
}
}
}
}
}
#[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this test, container is paused
fn test_draw_blocks_commands_some_paused() {
let mut setup = test_setup(12, 6, true, true);
let colors = setup.app_data.lock().config.app_colors;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
// Set the container state to paused
setup
.app_data
.lock()
.update_containers(vec![gen_container_summary(1, "paused")]);
setup.app_data.lock().docker_controls_next();
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.bg, Color::Reset);
match (row_index, result_cell_index) {
// resume
(1, 3..=8) => {
assert_eq!(result_cell.fg, Color::Blue);
}
// stop
(2, 3..=6) => {
assert_eq!(result_cell.fg, Color::Red);
}
// delete
(0 | 5, _) | (1..=4, 0 | 11) | (3, 3..=8) => {
assert_eq!(result_cell.fg, Color::Gray);
}
_ => {
assert_eq!(result_cell.fg, Color::Reset);
}
}
}
}
}
#[test]
/// When control panel is selected, the border is blue, if not then white, selected text is highlighted
fn test_draw_blocks_commands_panel_selected_color() {
let mut setup = test_setup(12, 6, true, true);
let colors = setup.app_data.lock().config.app_colors;
// Unselected, has a grey border
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (_, result_row) in get_result(&setup) {
for result_cell in result_row {
if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::Gray);
}
}
}
// Control panel now selected, should have a blue border
setup.gui_state.lock().next_panel();
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&fd,
&setup.gui_state,
);
})
.unwrap();
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
if row_index == 0
|| row_index == 5
|| result_cell_index == 0
|| result_cell_index == 11
{
assert_eq!(result_cell.fg, Color::LightCyan);
}
if row_index == 1 && result_cell_index > 0 && result_cell_index < 11 {
assert_eq!(result_cell.modifier, Modifier::BOLD);
} else {
assert!(result_cell.modifier.is_empty());
}
}
}
}
#[test]
/// Custom colors are rendered correctly
fn test_draw_blocks_commands_custom_colors_running() {
let mut setup = test_setup(12, 6, true, true);
let mut colors = AppColors::new();
colors.commands.background = Color::White;
colors.commands.pause = Color::Black;
colors.commands.restart = Color::Green;
colors.commands.stop = Color::Blue;
colors.commands.delete = Color::Magenta;
colors.commands.resume = Color::Yellow;
colors.commands.start = Color::Cyan;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.bg, Color::White);
match (row_index, result_cell_index) {
// pause
(1, 3..=7) => {
assert_eq!(result_cell.fg, Color::Black);
}
// restart
(2, 3..=9) => {
assert_eq!(result_cell.fg, Color::Green);
}
// stop
(3, 3..=6) => {
assert_eq!(result_cell.fg, Color::Blue);
}
// delete
(4, 3..=8) => {
assert_eq!(result_cell.fg, Color::Magenta);
}
_ => (),
}
}
}
}
#[test]
/// Custom colors are rendered correctly
fn test_draw_blocks_commands_custom_colors_paused() {
let mut setup = test_setup(12, 6, true, true);
let mut colors = AppColors::new();
colors.commands.background = Color::White;
colors.commands.pause = Color::Black;
colors.commands.restart = Color::Green;
colors.commands.stop = Color::Blue;
colors.commands.delete = Color::Magenta;
colors.commands.resume = Color::Yellow;
colors.commands.start = Color::Cyan;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
// Set the controls state
setup
.app_data
.lock()
.update_containers(vec![gen_container_summary(1, "paused")]);
setup.app_data.lock().docker_controls_next();
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.bg, Color::White);
match (row_index, result_cell_index) {
// resume
(1, 3..=7) => {
assert_eq!(result_cell.fg, Color::Yellow);
}
// stop
(2, 3..=6) => {
assert_eq!(result_cell.fg, Color::Blue);
}
// delete
(3, 3..=8) => {
assert_eq!(result_cell.fg, Color::Magenta);
}
_ => (),
}
}
}
}
}