use crate::channels::telegram::handler::{format_reply_context, format_reply_sender};
#[test]
fn no_quote_falls_back_to_full_text() {
let result = format_reply_context("Alice", "Hello, world!", "");
assert_eq!(
result,
Some(r#"[Replying to Alice: "Hello, world!"]"#.into())
);
}
#[test]
fn quote_alone_surfaces_only_quote() {
let result = format_reply_context("Bob", "", "selected text");
assert_eq!(result, Some(r#"[Replying to Bob: "selected text"]"#.into()));
}
#[test]
fn quote_differs_from_full_text_shows_both() {
let result = format_reply_context(
"Carol",
"The roof needs urgent repair. The walls are stable.",
"The roof needs urgent repair.",
);
assert_eq!(
result,
Some(
r#"[Replying to Carol, user highlighted: "The roof needs urgent repair."
Full message: "The roof needs urgent repair. The walls are stable."]"#
.into()
)
);
}
#[test]
fn quote_equals_full_text_shows_once() {
let result = format_reply_context("Dave", "hi there", "hi there");
assert_eq!(result, Some(r#"[Replying to Dave: "hi there"]"#.into()));
}
#[test]
fn whitespace_around_quote_is_trimmed() {
let result = format_reply_context("Eve", "full body of the message", " highlighted ");
assert_eq!(
result,
Some(
r#"[Replying to Eve, user highlighted: "highlighted"
Full message: "full body of the message"]"#
.into()
)
);
}
#[test]
fn whitespace_around_full_text_is_trimmed() {
let result = format_reply_context("Frank", " spaced text ", "");
assert_eq!(result, Some(r#"[Replying to Frank: "spaced text"]"#.into()));
}
#[test]
fn empty_both_returns_none() {
assert_eq!(format_reply_context("Grace", "", ""), None);
assert_eq!(format_reply_context("Grace", " ", " "), None);
}
#[test]
fn quote_matches_full_text_after_trim() {
let result = format_reply_context("Henry", "exact text", "exact text ");
assert_eq!(result, Some(r#"[Replying to Henry: "exact text"]"#.into()));
}
#[test]
fn assistant_sender_format_is_preserved() {
let result = format_reply_context("assistant", "I think we should refactor", "");
assert_eq!(
result,
Some(r#"[Replying to assistant: "I think we should refactor"]"#.into())
);
}
#[test]
fn multiline_full_message_with_short_quote() {
let full = "Here is paragraph one.\nHere is paragraph two.\nHere is paragraph three.";
let quote = "paragraph two";
let result = format_reply_context("Iris", full, quote);
let expected =
format!("[Replying to Iris, user highlighted: \"{quote}\"\nFull message: \"{full}\"]");
assert_eq!(result, Some(expected));
}
#[test]
fn unicode_quote_is_preserved() {
let result = format_reply_context(
"Jules",
"Le toit nécessite des réparations urgentes.",
"réparations urgentes",
);
assert_eq!(
result,
Some(
r#"[Replying to Jules, user highlighted: "réparations urgentes"
Full message: "Le toit nécessite des réparations urgentes."]"#
.into()
)
);
}
#[test]
fn reply_sender_includes_username_and_id() {
let label = format_reply_sender(false, "Alice", None, Some("alice_w"), 12345);
assert_eq!(label, "Alice (@alice_w), ID 12345");
}
#[test]
fn reply_sender_includes_last_name() {
let label = format_reply_sender(false, "Alice", Some("Wong"), Some("aw"), 42);
assert_eq!(label, "Alice Wong (@aw), ID 42");
}
#[test]
fn reply_sender_without_username_still_has_id() {
let label = format_reply_sender(false, "Bob", None, None, 999);
assert_eq!(label, "Bob, ID 999");
}
#[test]
fn reply_sender_for_bot_is_assistant() {
let label = format_reply_sender(true, "OpenCrabs", None, Some("opencrabs_bot"), 7);
assert_eq!(label, "assistant");
}
#[test]
fn reply_context_carries_full_sender_identity() {
let sender = format_reply_sender(false, "Carol", None, Some("carol"), 555);
let ctx = format_reply_context(&sender, "the original message", "");
assert_eq!(
ctx,
Some(r#"[Replying to Carol (@carol), ID 555: "the original message"]"#.into())
);
}
use crate::channels::telegram::handler::resolve_reply_context;
#[test]
fn unrecoverable_bot_reply_emits_explicit_marker_not_none() {
let ctx = resolve_reply_context("assistant", "", "", true);
let text = ctx.expect("must emit a marker, not None");
assert!(text.contains("could not be retrieved"), "got: {text}");
assert!(
text.contains("Do NOT guess"),
"must forbid fabrication: {text}"
);
}
#[test]
fn recoverable_content_ignores_the_unavailable_flag() {
let ctx = resolve_reply_context("assistant", "the real message", "", true);
assert_eq!(
ctx,
Some(r#"[Replying to assistant: "the real message"]"#.into())
);
}
#[test]
fn empty_non_bot_reply_stays_none() {
assert_eq!(resolve_reply_context("Alice", "", "", false), None);
}