mod common;
use common::init_test_logging;
use rich_rust::color::ColorSystem;
use rich_rust::prelude::*;
#[test]
fn test_style_link_stores_url() {
init_test_logging();
let style = Style::new().link("https://example.com");
assert_eq!(style.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_link_complex_url() {
init_test_logging();
let url = "https://example.com/path?query=value&other=123#anchor";
let style = Style::new().link(url);
assert_eq!(style.link, Some(url.to_string()));
}
#[test]
fn test_style_link_with_attributes() {
init_test_logging();
let style = Style::new()
.bold()
.italic()
.color(Color::parse("red").unwrap())
.link("https://example.com");
assert!(style.attributes.contains(Attributes::BOLD));
assert!(style.attributes.contains(Attributes::ITALIC));
assert!(style.color.is_some());
assert_eq!(style.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_parse_link_space_syntax() {
init_test_logging();
let style = Style::parse("link https://example.com").unwrap();
assert_eq!(style.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_parse_link_with_attributes() {
init_test_logging();
let style = Style::parse("bold red link https://example.com").unwrap();
assert!(style.attributes.contains(Attributes::BOLD));
assert!(style.color.is_some());
assert_eq!(style.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_parse_link_only() {
init_test_logging();
let style = Style::parse("link https://rust-lang.org").unwrap();
assert!(style.attributes.is_empty());
assert!(style.color.is_none());
assert_eq!(style.link, Some("https://rust-lang.org".to_string()));
}
#[test]
fn test_style_link_renders_osc8() {
init_test_logging();
let style = Style::new().link("https://example.com");
let rendered = style.render("click me", ColorSystem::TrueColor);
assert!(
rendered.contains("\x1b]8;;https://example.com\x1b\\"),
"Should contain OSC 8 open sequence, got: {:?}",
rendered
);
assert!(
rendered.contains("\x1b]8;;\x1b\\"),
"Should contain OSC 8 close sequence, got: {:?}",
rendered
);
assert!(rendered.contains("click me"), "Should contain the text");
}
#[test]
fn test_style_link_with_bold_renders_both() {
init_test_logging();
let style = Style::new().bold().link("https://example.com");
let rendered = style.render("bold link", ColorSystem::TrueColor);
assert!(rendered.contains("\x1b]8;;https://example.com\x1b\\"));
assert!(rendered.contains("\x1b]8;;\x1b\\"));
assert!(rendered.contains("\x1b[1m"), "Should contain bold SGR code");
}
#[test]
fn test_style_render_ansi_link_prefix_suffix() {
init_test_logging();
let style = Style::new().bold().link("https://example.com");
let ansi = style.render_ansi(ColorSystem::TrueColor);
let (prefix, suffix) = &*ansi;
assert!(prefix.contains("\x1b]8;;https://example.com"));
assert!(suffix.contains("\x1b]8;;\x1b\\"));
}
#[test]
fn test_markup_link_tag() {
init_test_logging();
let text = rich_rust::markup::render("[link=https://example.com]click here[/link]").unwrap();
assert_eq!(text.plain(), "click here");
let spans = text.spans();
assert!(!spans.is_empty(), "Should have at least one span");
assert!(
spans.iter().any(|s| s.style.link.is_some()),
"At least one span should have a link"
);
}
#[test]
fn test_markup_link_with_nested_styles() {
init_test_logging();
let text = rich_rust::markup::render("[bold][link=https://example.com]bold link[/link][/bold]")
.unwrap();
assert_eq!(text.plain(), "bold link");
}
#[test]
fn test_markup_link_special_chars() {
init_test_logging();
let text =
rich_rust::markup::render("[link=https://example.com/path?a=1&b=2]url[/link]").unwrap();
assert_eq!(text.plain(), "url");
let spans = text.spans();
assert!(!spans.is_empty());
let link_span = spans.iter().find(|s| s.style.link.is_some()).unwrap();
assert_eq!(
link_span.style.link.as_deref(),
Some("https://example.com/path?a=1&b=2")
);
}
#[test]
fn test_markup_styled_link() {
init_test_logging();
let text = rich_rust::markup::render(
"[red]before [link=https://example.com]linked[/link] after[/red]",
)
.unwrap();
assert_eq!(text.plain(), "before linked after");
}
#[test]
fn test_style_combine_preserves_link() {
init_test_logging();
let style1 = Style::new().bold();
let style2 = Style::new().link("https://example.com");
let combined = style1.combine(&style2);
assert!(combined.attributes.contains(Attributes::BOLD));
assert_eq!(combined.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_combine_link_override() {
init_test_logging();
let style1 = Style::new().link("https://first.com");
let style2 = Style::new().link("https://second.com");
let combined = style1.combine(&style2);
assert_eq!(combined.link, Some("https://second.com".to_string()));
}
#[test]
fn test_style_combine_null_preserves_link() {
init_test_logging();
let style = Style::new().link("https://example.com");
let null = Style::null();
let combined = style.combine(&null);
assert_eq!(combined.link, Some("https://example.com".to_string()));
}
#[test]
fn test_style_display_with_link() {
init_test_logging();
let style = Style::new().bold().link("https://example.com");
let display = style.to_string();
assert!(display.contains("bold"), "Display should contain 'bold'");
assert!(display.contains("link"), "Display should contain 'link'");
assert!(
display.contains("https://example.com"),
"Display should contain URL"
);
}
#[test]
fn test_style_link_empty_url() {
init_test_logging();
let style = Style::new().link("");
assert_eq!(style.link, Some("".to_string()));
}
#[test]
fn test_style_link_unicode_url() {
init_test_logging();
let url = "https://example.com/日本語";
let style = Style::new().link(url);
assert_eq!(style.link, Some(url.to_string()));
}
#[test]
fn test_style_link_long_url() {
init_test_logging();
let long_path = "a".repeat(1000);
let url = format!("https://example.com/{}", long_path);
let style = Style::new().link(&url);
assert_eq!(style.link, Some(url));
}
#[test]
fn test_style_link_relative_url() {
init_test_logging();
let style = Style::new().link("/path/to/resource");
assert_eq!(style.link, Some("/path/to/resource".to_string()));
}
#[test]
fn test_style_link_file_url() {
init_test_logging();
let style = Style::new().link("file:///home/user/doc.txt");
assert_eq!(style.link, Some("file:///home/user/doc.txt".to_string()));
}
#[test]
fn test_style_link_mailto_url() {
init_test_logging();
let style = Style::new().link("mailto:user@example.com");
assert_eq!(style.link, Some("mailto:user@example.com".to_string()));
}