feat(ui): Sonarr support for the series details popup
This commit is contained in:
@@ -1,50 +1,26 @@
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{layout_block, style_block_highlight};
|
||||
use derive_setters::Setters;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Constraint, Flex, Layout, Rect};
|
||||
use ratatui::prelude::{Style, Text, Widget};
|
||||
use ratatui::style::Styled;
|
||||
use ratatui::widgets::Paragraph;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "button_tests.rs"]
|
||||
mod button_tests;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Setters)]
|
||||
pub struct Button<'a> {
|
||||
title: &'a str,
|
||||
#[setters(strip_option)]
|
||||
label: Option<&'a str>,
|
||||
#[setters(strip_option)]
|
||||
icon: Option<&'a str>,
|
||||
#[setters(into)]
|
||||
style: Style,
|
||||
#[setters(rename = "selected")]
|
||||
is_selected: bool,
|
||||
}
|
||||
|
||||
impl<'a> Button<'a> {
|
||||
pub fn title(mut self, title: &'a str) -> Button<'a> {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn label(mut self, label: &'a str) -> Button<'a> {
|
||||
self.label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn icon(mut self, icon: &'a str) -> Button<'a> {
|
||||
self.icon = Some(icon);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn style<S: Into<Style>>(mut self, style: S) -> Button<'a> {
|
||||
self.style = style.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selected(mut self, is_selected: bool) -> Button<'a> {
|
||||
self.is_selected = is_selected;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_button_with_icon(self, area: Rect, buf: &mut Buffer) {
|
||||
let [title_area, icon_area] = Layout::horizontal([
|
||||
Constraint::Length(self.title.len() as u16),
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ui::widgets::button::Button;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use ratatui::style::{Style, Stylize};
|
||||
|
||||
#[test]
|
||||
fn test_title() {
|
||||
let button = Button::default().title("Title");
|
||||
|
||||
assert_str_eq!(button.title, "Title");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_label() {
|
||||
let button = Button::default().label("Label");
|
||||
|
||||
assert_eq!(button.label, Some("Label"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_icon() {
|
||||
let button = Button::default().icon("Icon");
|
||||
|
||||
assert_eq!(button.icon, Some("Icon"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_style() {
|
||||
let button = Button::default().style(Style::new().bold());
|
||||
|
||||
assert_eq!(button.style, Style::new().bold());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_selected() {
|
||||
let button = Button::default().selected(true);
|
||||
|
||||
assert!(button.is_selected);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use derive_setters::Setters;
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{borderless_block, layout_block, style_block_highlight};
|
||||
use ratatui::buffer::Buffer;
|
||||
@@ -6,14 +7,13 @@ use ratatui::prelude::Text;
|
||||
use ratatui::style::Stylize;
|
||||
use ratatui::widgets::{Paragraph, Widget};
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "checkbox_tests.rs"]
|
||||
mod checkbox_tests;
|
||||
|
||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Setters)]
|
||||
pub struct Checkbox<'a> {
|
||||
#[setters(skip)]
|
||||
label: &'a str,
|
||||
#[setters(rename = "checked")]
|
||||
is_checked: bool,
|
||||
#[setters(rename = "highlighted")]
|
||||
is_highlighted: bool,
|
||||
}
|
||||
|
||||
@@ -26,16 +26,6 @@ impl<'a> Checkbox<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checked(mut self, is_checked: bool) -> Checkbox<'a> {
|
||||
self.is_checked = is_checked;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn highlighted(mut self, is_selected: bool) -> Checkbox<'a> {
|
||||
self.is_highlighted = is_selected;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_checkbox(self, area: Rect, buf: &mut Buffer) {
|
||||
let check = if self.is_checked { "✔" } else { "" };
|
||||
let [label_area, checkbox_area] =
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ui::widgets::checkbox::Checkbox;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
|
||||
#[test]
|
||||
fn test_checkbox_new() {
|
||||
let checkbox = Checkbox::new("test");
|
||||
|
||||
assert_str_eq!(checkbox.label, "test");
|
||||
assert!(!checkbox.is_checked);
|
||||
assert!(!checkbox.is_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_checkbox_checked() {
|
||||
let checkbox = Checkbox::new("test").checked(true);
|
||||
|
||||
assert_str_eq!(checkbox.label, "test");
|
||||
assert!(checkbox.is_checked);
|
||||
assert!(!checkbox.is_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_checkbox_highlighted() {
|
||||
let checkbox = Checkbox::new("test").highlighted(true);
|
||||
|
||||
assert_str_eq!(checkbox.label, "test");
|
||||
assert!(!checkbox.is_checked);
|
||||
assert!(checkbox.is_highlighted);
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,19 @@ use ratatui::layout::{Constraint, Flex, Layout, Rect};
|
||||
use ratatui::text::Text;
|
||||
use ratatui::widgets::{Paragraph, Widget};
|
||||
use std::iter;
|
||||
use derive_setters::Setters;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "confirmation_prompt_tests.rs"]
|
||||
mod confirmation_prompt_tests;
|
||||
|
||||
#[derive(Setters)]
|
||||
pub struct ConfirmationPrompt<'a> {
|
||||
title: &'a str,
|
||||
prompt: &'a str,
|
||||
#[setters(strip_option)]
|
||||
content: Option<Paragraph<'a>>,
|
||||
#[setters(strip_option)]
|
||||
checkboxes: Option<Vec<Checkbox<'a>>>,
|
||||
yes_no_value: bool,
|
||||
yes_no_highlighted: bool,
|
||||
@@ -34,36 +38,6 @@ impl<'a> ConfirmationPrompt<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(mut self, title: &'a str) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn prompt(mut self, prompt: &'a str) -> Self {
|
||||
self.prompt = prompt;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn content(mut self, content: Paragraph<'a>) -> Self {
|
||||
self.content = Some(content);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn checkboxes(mut self, checkboxes: Vec<Checkbox<'a>>) -> Self {
|
||||
self.checkboxes = Some(checkboxes);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn yes_no_value(mut self, yes_highlighted: bool) -> Self {
|
||||
self.yes_no_value = yes_highlighted;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn yes_no_highlighted(mut self, yes_highlighted: bool) -> Self {
|
||||
self.yes_no_highlighted = yes_highlighted;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_confirmation_prompt_with_checkboxes(self, area: Rect, buf: &mut Buffer) {
|
||||
title_block_centered(self.title).render(area, buf);
|
||||
let help_text =
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ui::widgets::checkbox::Checkbox;
|
||||
use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use ratatui::widgets::Paragraph;
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_new() {
|
||||
@@ -16,78 +14,4 @@ mod tests {
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_title() {
|
||||
let confirmation_prompt = ConfirmationPrompt::new().title("title");
|
||||
|
||||
assert_str_eq!(confirmation_prompt.title, "title");
|
||||
assert_str_eq!(confirmation_prompt.prompt, "");
|
||||
assert_eq!(confirmation_prompt.content, None);
|
||||
assert_eq!(confirmation_prompt.checkboxes, None);
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_prompt() {
|
||||
let confirmation_prompt = ConfirmationPrompt::new().prompt("prompt");
|
||||
|
||||
assert_str_eq!(confirmation_prompt.prompt, "prompt");
|
||||
assert_str_eq!(confirmation_prompt.title, "");
|
||||
assert_eq!(confirmation_prompt.content, None);
|
||||
assert_eq!(confirmation_prompt.checkboxes, None);
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_content() {
|
||||
let content = Paragraph::new("content");
|
||||
let confirmation_prompt = ConfirmationPrompt::new().content(content.clone());
|
||||
|
||||
assert_eq!(confirmation_prompt.content, Some(content));
|
||||
assert_str_eq!(confirmation_prompt.title, "");
|
||||
assert_str_eq!(confirmation_prompt.prompt, "");
|
||||
assert_eq!(confirmation_prompt.checkboxes, None);
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_checkboxes() {
|
||||
let checkboxes = vec![Checkbox::new("test").highlighted(true).checked(false)];
|
||||
let confirmation_prompt = ConfirmationPrompt::new().checkboxes(checkboxes.clone());
|
||||
|
||||
assert_eq!(confirmation_prompt.checkboxes, Some(checkboxes));
|
||||
assert_str_eq!(confirmation_prompt.title, "");
|
||||
assert_str_eq!(confirmation_prompt.prompt, "");
|
||||
assert_eq!(confirmation_prompt.content, None);
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_yes_no_value() {
|
||||
let confirmation_prompt = ConfirmationPrompt::new().yes_no_value(true);
|
||||
|
||||
assert!(confirmation_prompt.yes_no_value);
|
||||
assert_str_eq!(confirmation_prompt.title, "");
|
||||
assert_str_eq!(confirmation_prompt.prompt, "");
|
||||
assert_eq!(confirmation_prompt.content, None);
|
||||
assert_eq!(confirmation_prompt.checkboxes, None);
|
||||
assert!(confirmation_prompt.yes_no_highlighted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_confirmation_prompt_yes_no_highlighted() {
|
||||
let confirmation_prompt = ConfirmationPrompt::new().yes_no_highlighted(false);
|
||||
|
||||
assert!(!confirmation_prompt.yes_no_highlighted);
|
||||
assert_str_eq!(confirmation_prompt.title, "");
|
||||
assert_str_eq!(confirmation_prompt.prompt, "");
|
||||
assert_eq!(confirmation_prompt.content, None);
|
||||
assert_eq!(confirmation_prompt.checkboxes, None);
|
||||
assert!(!confirmation_prompt.yes_no_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use derive_setters::Setters;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Constraint, Layout, Position, Rect};
|
||||
use ratatui::prelude::Text;
|
||||
@@ -12,16 +13,20 @@ use crate::ui::utils::{borderless_block, layout_block};
|
||||
#[path = "input_box_tests.rs"]
|
||||
mod input_box_tests;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Setters)]
|
||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||
pub struct InputBox<'a> {
|
||||
content: &'a str,
|
||||
offset: usize,
|
||||
#[setters(into)]
|
||||
style: Style,
|
||||
block: Block<'a>,
|
||||
#[setters(strip_option)]
|
||||
label: Option<&'a str>,
|
||||
cursor_after_string: bool,
|
||||
#[setters(rename = "highlighted", strip_option)]
|
||||
is_highlighted: Option<bool>,
|
||||
#[setters(rename = "selected", strip_option)]
|
||||
is_selected: Option<bool>,
|
||||
}
|
||||
|
||||
@@ -39,41 +44,6 @@ impl<'a> InputBox<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn style<S: Into<Style>>(mut self, style: S) -> InputBox<'a> {
|
||||
self.style = style.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn block(mut self, block: Block<'a>) -> InputBox<'a> {
|
||||
self.block = block;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn label(mut self, label: &'a str) -> InputBox<'a> {
|
||||
self.label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn offset(mut self, offset: usize) -> InputBox<'a> {
|
||||
self.offset = offset;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cursor_after_string(mut self, cursor_after_string: bool) -> InputBox<'a> {
|
||||
self.cursor_after_string = cursor_after_string;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn highlighted(mut self, is_highlighted: bool) -> InputBox<'a> {
|
||||
self.is_highlighted = Some(is_highlighted);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selected(mut self, is_selected: bool) -> InputBox<'a> {
|
||||
self.is_selected = Some(is_selected);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn is_selected(&self) -> bool {
|
||||
self.is_selected.unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -20,104 +20,6 @@ mod tests {
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_style() {
|
||||
let input_box = InputBox::new("test").style(Style::new().highlight());
|
||||
|
||||
assert_eq!(input_box.style, Style::new().highlight());
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_block() {
|
||||
let input_box = InputBox::new("test").block(layout_block().title("title"));
|
||||
|
||||
assert_eq!(input_box.block, layout_block().title("title"));
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_label() {
|
||||
let input_box = InputBox::new("test").label("label");
|
||||
|
||||
assert_str_eq!(input_box.label.unwrap(), "label");
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_offset() {
|
||||
let input_box = InputBox::new("test").offset(1);
|
||||
|
||||
assert_eq!(input_box.offset, 1);
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_cursor_after_string() {
|
||||
let input_box = InputBox::new("test").cursor_after_string(false);
|
||||
|
||||
assert!(!input_box.cursor_after_string);
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_highlighted() {
|
||||
let input_box = InputBox::new("test").highlighted(true);
|
||||
|
||||
assert_eq!(input_box.is_highlighted, Some(true));
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_selected, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_selected() {
|
||||
let input_box = InputBox::new("test").selected(true);
|
||||
|
||||
assert_eq!(input_box.is_selected, Some(true));
|
||||
assert_str_eq!(input_box.content, "test");
|
||||
assert_eq!(input_box.offset, 0);
|
||||
assert_eq!(input_box.style, Style::new().default());
|
||||
assert_eq!(input_box.block, layout_block());
|
||||
assert_eq!(input_box.label, None);
|
||||
assert!(input_box.cursor_after_string);
|
||||
assert_eq!(input_box.is_highlighted, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_input_box_is_selected() {
|
||||
let input_box = InputBox::new("test").selected(true);
|
||||
|
||||
@@ -12,7 +12,7 @@ use ratatui::widgets::{Block, ListItem, Paragraph, Row, StatefulWidget, Table, W
|
||||
use ratatui::Frame;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use derive_setters::Setters;
|
||||
use super::input_box_popup::InputBoxPopup;
|
||||
use super::message::Message;
|
||||
use super::popup::Size;
|
||||
@@ -21,24 +21,32 @@ use super::popup::Size;
|
||||
#[path = "managarr_table_tests.rs"]
|
||||
mod managarr_table_tests;
|
||||
|
||||
#[derive(Setters)]
|
||||
pub struct ManagarrTable<'a, T, F>
|
||||
where
|
||||
F: Fn(&T) -> Row<'a>,
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
{
|
||||
#[setters(strip_option)]
|
||||
content: Option<&'a mut StatefulTable<T>>,
|
||||
#[setters(skip)]
|
||||
table_headers: Vec<String>,
|
||||
#[setters(skip)]
|
||||
constraints: Vec<Constraint>,
|
||||
row_mapper: F,
|
||||
footer: Option<String>,
|
||||
footer_alignment: Alignment,
|
||||
block: Block<'a>,
|
||||
margin: u16,
|
||||
#[setters(rename = "loading")]
|
||||
is_loading: bool,
|
||||
highlight_rows: bool,
|
||||
#[setters(rename = "sorting")]
|
||||
is_sorting: bool,
|
||||
#[setters(rename = "searching")]
|
||||
is_searching: bool,
|
||||
search_produced_empty_results: bool,
|
||||
#[setters(rename = "filtering")]
|
||||
is_filtering: bool,
|
||||
filter_produced_empty_results: bool,
|
||||
search_box_content_length: usize,
|
||||
@@ -107,61 +115,6 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn footer(mut self, footer: Option<String>) -> Self {
|
||||
self.footer = footer;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn footer_alignment(mut self, alignment: Alignment) -> Self {
|
||||
self.footer_alignment = alignment;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn block(mut self, block: Block<'a>) -> Self {
|
||||
self.block = block;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn margin(mut self, margin: u16) -> Self {
|
||||
self.margin = margin;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn loading(mut self, is_loading: bool) -> Self {
|
||||
self.is_loading = is_loading;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn highlight_rows(mut self, highlight_rows: bool) -> Self {
|
||||
self.highlight_rows = highlight_rows;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sorting(mut self, is_sorting: bool) -> Self {
|
||||
self.is_sorting = is_sorting;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn searching(mut self, is_searching: bool) -> Self {
|
||||
self.is_searching = is_searching;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn search_produced_empty_results(mut self, no_search_results: bool) -> Self {
|
||||
self.search_produced_empty_results = no_search_results;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn filtering(mut self, is_filtering: bool) -> Self {
|
||||
self.is_filtering = is_filtering;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn filter_produced_empty_results(mut self, no_filter_results: bool) -> Self {
|
||||
self.filter_produced_empty_results = no_filter_results;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_table(self, area: Rect, buf: &mut Buffer) {
|
||||
let table_headers = self.parse_headers();
|
||||
let table_area = if let Some(ref footer) = self.footer {
|
||||
|
||||
@@ -3,7 +3,6 @@ mod tests {
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
use crate::models::stateful_table::{SortOption, StatefulTable};
|
||||
use crate::models::{HorizontallyScrollableText, Scrollable};
|
||||
use crate::ui::utils::layout_block;
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::layout::{Alignment, Constraint};
|
||||
@@ -180,358 +179,6 @@ mod tests {
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_footer() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
let footer = "footer".to_owned();
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.footer(Some(footer.clone()));
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert_eq!(managarr_table.footer, Some(footer));
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_footer_alignment() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.footer_alignment(Alignment::Center);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Center);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_block() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.block(layout_block());
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert_eq!(managarr_table.block, layout_block());
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_margin() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)])).margin(1);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert_eq!(managarr_table.margin, 1);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_loading() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.loading(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.is_loading);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_highlight_rows() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.highlight_rows(false);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(!managarr_table.highlight_rows);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_sorting() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.sorting(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.is_sorting);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_is_searching() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.searching(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.is_searching);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_search_produced_empty_results() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.search_produced_empty_results(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.search_produced_empty_results);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_is_filtering() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.filtering(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.is_filtering);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_filter_produced_empty_results() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_items(items.clone());
|
||||
|
||||
let managarr_table =
|
||||
ManagarrTable::new(Some(&mut stateful_table), |&s| Row::new(vec![Cell::new(s)]))
|
||||
.filter_produced_empty_results(true);
|
||||
|
||||
let row_mapper = managarr_table.row_mapper;
|
||||
assert!(managarr_table.filter_produced_empty_results);
|
||||
assert_eq!(managarr_table.content.unwrap().items, items);
|
||||
assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")]));
|
||||
assert_eq!(managarr_table.table_headers, Vec::<String>::new());
|
||||
assert_eq!(managarr_table.constraints, Vec::new());
|
||||
assert_eq!(managarr_table.footer, None);
|
||||
assert_eq!(managarr_table.footer_alignment, Alignment::Left);
|
||||
assert_eq!(managarr_table.block, Block::new());
|
||||
assert_eq!(managarr_table.margin, 0);
|
||||
assert!(!managarr_table.is_loading);
|
||||
assert!(managarr_table.highlight_rows);
|
||||
assert!(!managarr_table.is_sorting);
|
||||
assert!(!managarr_table.is_searching);
|
||||
assert!(!managarr_table.search_produced_empty_results);
|
||||
assert!(!managarr_table.is_filtering);
|
||||
assert_eq!(managarr_table.search_box_content_length, 0);
|
||||
assert_eq!(managarr_table.search_box_offset, 0);
|
||||
assert_eq!(managarr_table.filter_box_content_length, 0);
|
||||
assert_eq!(managarr_table.filter_box_offset, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managarr_table_parse_headers() {
|
||||
let items = vec!["item1", "item2", "item3"];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::title_block_centered;
|
||||
use derive_setters::Setters;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Alignment, Rect};
|
||||
use ratatui::style::{Style, Stylize};
|
||||
@@ -10,6 +11,7 @@ use ratatui::widgets::{Paragraph, Widget, Wrap};
|
||||
#[path = "message_tests.rs"]
|
||||
mod message_tests;
|
||||
|
||||
#[derive(Setters)]
|
||||
pub struct Message<'a> {
|
||||
text: Text<'a>,
|
||||
title: &'a str,
|
||||
@@ -30,21 +32,6 @@ impl<'a> Message<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(mut self, title: &'a str) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn style(mut self, style: Style) -> Self {
|
||||
self.style = style;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn alignment(mut self, alignment: Alignment) -> Self {
|
||||
self.alignment = alignment;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_message(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new(self.text)
|
||||
.style(self.style)
|
||||
|
||||
@@ -18,42 +18,4 @@ mod tests {
|
||||
assert_eq!(message.style, Style::new().failure().bold());
|
||||
assert_eq!(message.alignment, Alignment::Center);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_title() {
|
||||
let test_message = "This is a message";
|
||||
let title = "Success";
|
||||
|
||||
let message = Message::new(test_message).title(title);
|
||||
|
||||
assert_str_eq!(message.title, title);
|
||||
assert_eq!(message.text, Text::from(test_message));
|
||||
assert_eq!(message.style, Style::new().failure().bold());
|
||||
assert_eq!(message.alignment, Alignment::Center);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_style() {
|
||||
let test_message = "This is a message";
|
||||
let style = Style::new().success().bold();
|
||||
|
||||
let message = Message::new(test_message).style(style);
|
||||
|
||||
assert_eq!(message.style, style);
|
||||
assert_eq!(message.text, Text::from(test_message));
|
||||
assert_str_eq!(message.title, "Error");
|
||||
assert_eq!(message.alignment, Alignment::Center);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_alignment() {
|
||||
let test_message = "This is a message";
|
||||
|
||||
let message = Message::new(test_message).alignment(Alignment::Left);
|
||||
|
||||
assert_eq!(message.alignment, Alignment::Left);
|
||||
assert_eq!(message.text, Text::from(test_message));
|
||||
assert_str_eq!(message.title, "Error");
|
||||
assert_eq!(message.style, Style::new().failure().bold());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user