use crate::channels::telegram::TelegramState;
use crate::channels::telegram::handler::is_split_candidate;
const LIMIT: usize = 4096;
fn text_of(len: usize) -> String {
"a".repeat(len)
}
#[test]
fn an_ordinary_message_is_never_held() {
for len in [0usize, 1, 50, 500, 2000, 3900] {
assert!(
!is_split_candidate(&text_of(len)),
"a {len}-char message must dispatch immediately"
);
}
}
#[test]
fn a_message_at_the_send_limit_is_held() {
assert!(is_split_candidate(&text_of(LIMIT)));
}
#[test]
fn a_fragment_just_short_of_the_limit_is_held() {
assert!(is_split_candidate(&text_of(LIMIT - 1)));
assert!(is_split_candidate(&text_of(LIMIT - 100)));
}
#[test]
fn the_threshold_is_measured_in_utf16_like_telegram_counts_it() {
let emoji = "🦀".repeat(LIMIT / 2); assert_eq!(emoji.chars().count(), LIMIT / 2, "half as many chars");
assert!(
is_split_candidate(&emoji),
"a message at the limit in UTF-16 must be held even though it is half the char count"
);
assert!(!is_split_candidate(&text_of(LIMIT / 2)));
}
#[tokio::test]
async fn fragments_are_returned_in_arrival_order() {
let state = TelegramState::new();
for part in ["first", "second", "third"] {
state.buffer_text(-100, 42, part.to_string()).await;
}
assert_eq!(
state.drain_text_buffer(-100, 42).await,
vec!["first", "second", "third"]
);
}
#[tokio::test]
async fn draining_empties_the_buffer() {
let state = TelegramState::new();
state.buffer_text(-100, 42, "one".into()).await;
assert_eq!(state.drain_text_buffer(-100, 42).await, vec!["one"]);
assert!(
state.drain_text_buffer(-100, 42).await.is_empty(),
"the second drain must find nothing"
);
}
#[tokio::test]
async fn two_senders_in_one_chat_do_not_merge() {
let state = TelegramState::new();
state.buffer_text(-100, 1, "from-one".into()).await;
state.buffer_text(-100, 2, "from-two".into()).await;
assert_eq!(state.drain_text_buffer(-100, 1).await, vec!["from-one"]);
assert_eq!(state.drain_text_buffer(-100, 2).await, vec!["from-two"]);
}
#[tokio::test]
async fn one_sender_in_two_chats_does_not_merge() {
let state = TelegramState::new();
state.buffer_text(-100, 42, "in-a".into()).await;
state.buffer_text(-200, 42, "in-b".into()).await;
assert_eq!(state.drain_text_buffer(-100, 42).await, vec!["in-a"]);
assert_eq!(state.drain_text_buffer(-200, 42).await, vec!["in-b"]);
}
#[tokio::test]
async fn a_new_fragment_cancels_the_previous_wait() {
let state = TelegramState::new();
let first = state.reset_text_debounce(-100, 42).await;
assert!(!first.is_cancelled());
let second = state.reset_text_debounce(-100, 42).await;
assert!(first.is_cancelled(), "the earlier fragment must stand down");
assert!(!second.is_cancelled(), "the latest one owns the buffer");
}
#[tokio::test]
async fn a_cancelled_wait_reports_that_it_did_not_expire() {
let state = TelegramState::new();
let token = state.reset_text_debounce(-100, 42).await;
token.cancel();
assert!(!state.wait_text_debounce(token).await);
}
#[tokio::test]
async fn debounce_tokens_are_scoped_per_sender() {
let state = TelegramState::new();
let a = state.reset_text_debounce(-100, 1).await;
let _b = state.reset_text_debounce(-100, 2).await;
assert!(
!a.is_cancelled(),
"another sender's fragment must not cut this one's wait short"
);
}