use super::*;
#[test]
fn test_display_not_bold() {
let style = Style::new(
None,
None,
Some(false),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(style.to_string(), "not bold");
}
#[test]
fn test_display_not_bold_with_color() {
let style = Style::new(
Some("red"),
None,
Some(false),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(style.to_string(), "not bold red");
}
#[test]
fn test_display_null() {
let style = Style::null();
assert_eq!(style.to_string(), "none");
}
#[test]
fn test_display_bold() {
let style = Style::new(
None,
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(style.to_string(), "bold");
}
#[test]
fn test_display_bold_red_on_black() {
let style = Style::new(
Some("red"),
Some("black"),
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(style.to_string(), "bold red on black");
}
#[test]
fn test_display_link() {
let style = Style::new(
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some("foo"),
)
.unwrap();
assert_eq!(style.to_string(), "link foo");
}
#[test]
fn test_display_all_attributes() {
let style = Style::new(
Some("red"),
Some("black"),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
None,
)
.unwrap();
let s = style.to_string();
assert!(s.contains("bold"));
assert!(s.contains("dim"));
assert!(s.contains("italic"));
assert!(s.contains("underline"));
assert!(s.contains("blink"));
assert!(s.contains("blink2"));
assert!(s.contains("reverse"));
assert!(s.contains("conceal"));
assert!(s.contains("strike"));
assert!(s.contains("underline2"));
assert!(s.contains("frame"));
assert!(s.contains("encircle"));
assert!(s.contains("overline"));
assert!(s.contains("red"));
assert!(s.contains("on black"));
}
#[test]
fn test_equality_same() {
let style1 = Style::new(
Some("red"),
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
let style2 = Style::new(
Some("red"),
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_eq!(style1, style2);
}
#[test]
fn test_equality_different_color() {
let style1 = Style::new(
Some("red"),
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
let style2 = Style::new(
Some("green"),
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert_ne!(style1, style2);
}
#[test]
fn test_is_null_true() {
let style = Style::null();
assert!(style.is_null());
}
#[test]
fn test_is_null_false_with_bold() {
let style = Style::new(
None,
None,
Some(true),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert!(!style.is_null());
}
#[test]
fn test_is_null_false_with_color() {
let style = Style::new(
Some("red"),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
)
.unwrap();
assert!(!style.is_null());
}
#[test]
fn test_parse_empty() {
let style = Style::parse("");
assert!(style.is_null());
}
#[test]
fn test_parse_red() {
let style = Style::parse("red");
assert_eq!(style.color().unwrap().name(), "red");
}
#[test]
fn test_parse_not_bold() {
let style = Style::parse("not bold");
assert_eq!(style.bold(), Some(false));
}
#[test]
fn test_parse_bold_red_on_black() {
let style = Style::parse("bold red on black");
assert_eq!(style.bold(), Some(true));
assert_eq!(style.color().unwrap().name(), "red");
assert_eq!(style.bgcolor().unwrap().name(), "black");
}
#[test]
fn test_parse_bold_link() {
let style = Style::parse("bold link https://example.org");
assert_eq!(style.bold(), Some(true));
assert_eq!(style.link(), Some("https://example.org"));
}
#[test]
fn test_parse_error_on_alone() {
let result = Style::parse_strict("on");
assert!(result.is_err());
}
#[test]
fn test_parse_error_on_invalid_color() {
let result = Style::parse_strict("on nothing");
assert!(result.is_err());
}
#[test]
fn test_parse_error_rgb_out_of_range() {
let result = Style::parse_strict("rgb(999,999,999)");
assert!(result.is_err());
}
#[test]
fn test_parse_error_not_unknown_attribute() {
let result = Style::parse_strict("not monkey");
assert!(result.is_err());
}
#[test]
fn test_parse_error_link_alone() {
let result = Style::parse_strict("link");
assert!(result.is_err());
}
#[test]
fn test_render_no_color_system() {
let style = Style::parse("red");
assert_eq!(style.render("foo", None), "foo");
}
#[test]
fn test_render_empty_text() {
let style = Style::parse("red");
assert_eq!(style.render("", Some(ColorSystem::TrueColor)), "");
}
#[test]
fn test_render_null_style() {
let style = Style::null();
assert_eq!(style.render("foo", Some(ColorSystem::TrueColor)), "foo");
}
#[test]
fn test_render_bold_red_on_black() {
let style = Style::parse("bold red on black");
let rendered = style.render("foo", Some(ColorSystem::TrueColor));
assert!(rendered.contains("\x1b[1;31;40m"));
assert!(rendered.contains("foo"));
assert!(rendered.contains("\x1b[0m"));
}
#[test]
fn test_render_all_attributes() {
let style = Style::parse("bold dim italic underline blink blink2 reverse conceal strike underline2 frame encircle overline red on black");
let rendered = style.render("foo", Some(ColorSystem::TrueColor));
assert!(rendered.contains("1;2;3;4;5;6;7;8;9;21;51;52;53;31;40"));
}
#[test]
fn test_add_with_none() {
let style = Style::parse("red");
let result = style.clone() + None;
assert_eq!(result, style);
}
#[test]
fn test_add_styles() {
let style1 = Style::parse("red");
let style2 = Style::parse("bold");
let result = style1 + style2;
assert_eq!(result.color().unwrap().name(), "red");
assert_eq!(result.bold(), Some(true));
}
#[test]
fn test_add_override_color() {
let style1 = Style::parse("red");
let style2 = Style::parse("blue");
let result = style1 + style2;
assert_eq!(result.color().unwrap().name(), "blue");
}
#[test]
fn test_style_stack_new() {
let stack = StyleStack::new(Style::parse("red"));
assert_eq!(stack.current().color().unwrap().name(), "red");
}
#[test]
fn test_style_stack_push() {
let mut stack = StyleStack::new(Style::parse("red"));
stack.push(Style::parse("bold"));
assert_eq!(stack.current().color().unwrap().name(), "red");
assert_eq!(stack.current().bold(), Some(true));
}
#[test]
fn test_style_stack_pop() {
let mut stack = StyleStack::new(Style::parse("red"));
stack.push(Style::parse("bold"));
stack.pop().unwrap();
assert_eq!(stack.current().color().unwrap().name(), "red");
assert_eq!(stack.current().bold(), None);
}
#[test]
fn test_style_stack_pop_error() {
let mut stack = StyleStack::new(Style::null());
let result = stack.pop();
assert!(result.is_err());
}
#[test]
fn test_get_html_style_complex() {
let style = Style::parse("reverse dim red on blue bold italic underline strike overline");
let html = style.get_html_style(None);
assert!(html.contains("color: #400040"));
assert!(html.contains("text-decoration-color: #400040"));
assert!(html.contains("background-color: #800000"));
assert!(html.contains("font-weight: bold"));
assert!(html.contains("font-style: italic"));
assert!(html.contains("text-decoration: underline line-through overline"));
}
#[test]
fn test_get_html_style_simple() {
let style = Style::parse("bold red");
let html = style.get_html_style(None);
assert!(html.contains("color: #800000"));
assert!(html.contains("font-weight: bold"));
}
#[test]
fn test_without_color() {
let style = Style::parse("bold red on blue");
let without = style.without_color();
assert_eq!(without.bold(), Some(true));
assert!(without.color().is_none());
assert!(without.bgcolor().is_none());
}
#[test]
fn test_background_style() {
let style = Style::parse("bold yellow on red");
let bg = style.background_style();
assert!(bg.color().is_none());
assert_eq!(bg.bgcolor().unwrap().name(), "red");
assert_eq!(bg.bold(), None);
}
#[test]
fn test_clear_meta_and_links() {
let style = Style::parse("bold red link https://example.org");
let cleared = style.clear_meta_and_links();
assert_eq!(cleared.bold(), Some(true));
assert_eq!(cleared.color().unwrap().name(), "red");
assert!(cleared.link().is_none());
}
#[test]
fn test_combine_empty() {
let result = Style::combine(&[]);
assert!(result.is_null());
}
#[test]
fn test_combine_multiple() {
let styles = vec![
Style::parse("red"),
Style::parse("bold"),
Style::parse("on blue"),
];
let result = Style::combine(&styles);
assert_eq!(result.color().unwrap().name(), "red");
assert_eq!(result.bold(), Some(true));
assert_eq!(result.bgcolor().unwrap().name(), "blue");
}
#[test]
fn test_parse_attribute_alias_b() {
let style = Style::parse("b");
assert_eq!(style.bold(), Some(true));
}
#[test]
fn test_parse_attribute_alias_i() {
let style = Style::parse("i");
assert_eq!(style.italic(), Some(true));
}
#[test]
fn test_parse_attribute_alias_u() {
let style = Style::parse("u");
assert_eq!(style.underline(), Some(true));
}
#[test]
fn test_parse_attribute_alias_s() {
let style = Style::parse("s");
assert_eq!(style.strike(), Some(true));
}
#[test]
fn test_parse_attribute_alias_uu() {
let style = Style::parse("uu");
assert_eq!(style.underline2(), Some(true));
}
#[test]
fn test_parse_attribute_alias_o() {
let style = Style::parse("o");
assert_eq!(style.overline(), Some(true));
}
#[test]
fn test_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
let style1 = Style::parse("bold red");
let style2 = Style::parse("bold red");
let style3 = Style::parse("bold blue");
set.insert(style1);
assert!(set.contains(&style2));
set.insert(style3);
assert_eq!(set.len(), 2);
}
#[test]
fn test_from_color() {
let color = Color::parse("red").unwrap();
let bgcolor = Color::parse("blue").unwrap();
let style = Style::from_color(Some(color), Some(bgcolor));
assert_eq!(style.color().unwrap().name(), "red");
assert_eq!(style.bgcolor().unwrap().name(), "blue");
assert!(style.bold().is_none());
}
#[test]
fn test_from_color_none() {
let style = Style::from_color(None, None);
assert!(style.color().is_none());
assert!(style.bgcolor().is_none());
}
#[test]
fn test_with_link() {
let style = Style::with_link("https://example.com");
assert_eq!(style.link(), Some("https://example.com"));
assert!(style.color().is_none());
assert!(style.bold().is_none());
}
#[test]
fn test_with_link_is_not_null() {
let style = Style::with_link("https://example.com");
assert!(!style.is_null());
}
#[test]
fn test_parse_link_equals_syntax() {
let style = Style::parse("link=https://example.com");
assert_eq!(style.link(), Some("https://example.com"));
}
#[test]
fn test_parse_bold_link_equals_syntax() {
let style = Style::parse("bold link=https://example.com");
assert_eq!(style.bold(), Some(true));
assert_eq!(style.link(), Some("https://example.com"));
}
#[test]
fn test_parse_link_equals_empty_error() {
let result = Style::parse_strict("link=");
assert!(result.is_err());
}
#[test]
fn test_render_link_only() {
let style = Style::with_link("https://example.com");
let rendered = style.render("click", Some(ColorSystem::TrueColor));
assert!(rendered.starts_with("\x1b]8;id="));
assert!(rendered.contains(";https://example.com\x1b\\click\x1b]8;;\x1b\\"));
}
#[test]
fn test_pick_first_returns_first_non_null() {
let s1 = Style::parse("bold red");
let s2 = Style::parse("italic");
let null = Style::null();
let picked = Style::pick_first(&[Some(&null), Some(&s1), Some(&s2)]);
assert_eq!(picked.bold(), Some(true));
assert_eq!(
picked.color().map(|c| c.name().into_owned()),
Some("red".to_string())
);
}
#[test]
fn test_pick_first_skips_none_and_null() {
let null = Style::null();
let s = Style::parse("underline");
let picked = Style::pick_first(&[None, Some(&null), None, Some(&s)]);
assert_eq!(picked.underline(), Some(true));
}
#[test]
fn test_pick_first_all_null_returns_null() {
let null = Style::null();
let picked = Style::pick_first(&[None, Some(&null), None]);
assert!(picked.is_null());
}
#[test]
fn test_link_id_is_monotonic() {
let a = next_link_id();
let b = next_link_id();
let c = next_link_id();
assert!(b > a);
assert!(c > b);
}
#[test]
fn test_render_bold_with_link() {
let style = Style::parse("bold link https://example.com");
let rendered = style.render("click", Some(ColorSystem::TrueColor));
assert!(rendered.starts_with("\x1b]8;id="));
assert!(rendered.contains(";https://example.com\x1b\\"));
assert!(rendered.ends_with("\x1b]8;;\x1b\\"));
assert!(rendered.contains("\x1b[1m"));
assert!(rendered.contains("click"));
}
#[test]
fn test_render_link_no_color_system() {
let style = Style::with_link("https://example.com");
let rendered = style.render("click", None);
assert_eq!(rendered, "click");
}
#[test]
fn test_add_link_override() {
let style1 = Style::parse("link https://a.com");
let style2 = Style::parse("link https://b.com");
let result = style1 + style2;
assert_eq!(result.link(), Some("https://b.com"));
}
#[test]
fn test_add_link_preserved() {
let style1 = Style::parse("link https://a.com");
let style2 = Style::parse("bold");
let result = style1 + style2;
assert_eq!(result.link(), Some("https://a.com"));
assert_eq!(result.bold(), Some(true));
}
#[test]
fn test_combine_link() {
let styles = vec![
Style::parse("red"),
Style::with_link("https://example.com"),
Style::parse("bold"),
];
let result = Style::combine(&styles);
assert_eq!(result.link(), Some("https://example.com"));
assert_eq!(result.color().unwrap().name(), "red");
assert_eq!(result.bold(), Some(true));
}
#[test]
fn test_underline_style_setter_getter() {
let mut style = Style::null();
assert!(style.underline_style().is_none());
style.set_underline_style(Some(UnderlineStyle::Curly));
assert_eq!(style.underline_style(), Some(UnderlineStyle::Curly));
}
#[test]
fn test_underline_color_setter_getter() {
let mut style = Style::null();
assert!(style.underline_color().is_none());
let red = Color::parse("red").unwrap();
style.set_underline_color(Some(red));
assert!(style.underline_color().is_some());
assert_eq!(style.underline_color().unwrap().name(), "red");
}
#[test]
fn test_underline_style_is_not_null() {
let mut style = Style::null();
style.set_underline_style(Some(UnderlineStyle::Double));
assert!(!style.is_null());
}
#[test]
fn test_underline_color_is_not_null() {
let mut style = Style::null();
style.set_underline_color(Some(Color::parse("red").unwrap()));
assert!(!style.is_null());
}
#[test]
fn test_underline_style_display() {
let mut style = Style::null();
style.set_underline_style(Some(UnderlineStyle::Curly));
assert!(style.to_string().contains("curly"));
}
#[test]
fn test_underline_color_display() {
let mut style = Style::null();
style.set_underline_color(Some(Color::parse("red").unwrap()));
assert!(style.to_string().contains("underline_color(red)"));
}
#[test]
fn test_underline_style_add() {
let mut s1 = Style::null();
s1.set_underline_style(Some(UnderlineStyle::Curly));
let mut s2 = Style::null();
s2.set_underline_style(Some(UnderlineStyle::Dashed));
let result = s1 + s2;
assert_eq!(result.underline_style(), Some(UnderlineStyle::Dashed));
}
#[test]
fn test_underline_color_add() {
let mut s1 = Style::null();
s1.set_underline_color(Some(Color::parse("red").unwrap()));
let s2 = Style::parse("bold");
let result = s1 + s2;
assert_eq!(result.underline_color().unwrap().name(), "red");
}
#[test]
fn test_underline_style_render_curly() {
let mut style = Style::null();
style.set_underline_style(Some(UnderlineStyle::Curly));
let rendered = style.render("foo", Some(ColorSystem::TrueColor));
assert!(rendered.contains("4:3"));
}
#[test]
fn test_underline_style_render_dashed() {
let mut style = Style::null();
style.set_underline_style(Some(UnderlineStyle::Dashed));
let rendered = style.render("foo", Some(ColorSystem::TrueColor));
assert!(rendered.contains("4:5"));
}
#[test]
fn test_underline_color_render_truecolor() {
let mut style = Style::null();
style.set_underline(Some(true));
style.set_underline_color(Some(Color::from_rgb(255, 0, 0)));
let rendered = style.render("foo", Some(ColorSystem::TrueColor));
assert!(rendered.contains("58;2;255;0;0"), "rendered: {}", rendered);
}
#[test]
fn test_without_color_preserves_underline_color() {
let mut style = Style::parse("bold red on blue");
style.set_underline_color(Some(Color::parse("green").unwrap()));
let without = style.without_color();
assert!(without.color().is_none());
assert!(without.bgcolor().is_none());
assert!(without.underline_color().is_some());
assert_eq!(without.underline_color().unwrap().name(), "green");
}
#[test]
fn test_background_style_clears_underline() {
let mut style = Style::parse("bold red on blue");
style.set_underline_color(Some(Color::parse("green").unwrap()));
style.set_underline_style(Some(UnderlineStyle::Curly));
let bg = style.background_style();
assert!(bg.underline_color().is_none());
assert!(bg.underline_style().is_none());
}
#[test]
fn test_underline_equality() {
let mut s1 = Style::null();
s1.set_underline_style(Some(UnderlineStyle::Curly));
let mut s2 = Style::null();
s2.set_underline_style(Some(UnderlineStyle::Curly));
assert_eq!(s1, s2);
let mut s3 = Style::null();
s3.set_underline_style(Some(UnderlineStyle::Dashed));
assert_ne!(s1, s3);
}
#[test]
fn test_public_setters() {
let mut style = Style::null();
style.set_bold(Some(true));
style.set_dim(Some(true));
style.set_italic(Some(true));
style.set_underline(Some(true));
style.set_blink(Some(true));
style.set_reverse(Some(true));
style.set_conceal(Some(true));
style.set_strike(Some(true));
assert_eq!(style.bold(), Some(true));
assert_eq!(style.dim(), Some(true));
assert_eq!(style.italic(), Some(true));
assert_eq!(style.underline(), Some(true));
assert_eq!(style.blink(), Some(true));
assert_eq!(style.reverse(), Some(true));
assert_eq!(style.conceal(), Some(true));
assert_eq!(style.strike(), Some(true));
}