-
Notifications
You must be signed in to change notification settings - Fork 2
test(channels): add injectable test transport to TelegramChannel for unit testing without Telegram API #2121
Description
Problem
TelegramChannel::start() creates the internal mpsc::Sender<IncomingMessage> in-place and never exposes it. This makes it impossible to write integration tests for the channel's core logic — recv(), send_chunk(), flush_chunks(), confirm() timeout behavior, allowed_users enforcement — without a real Telegram bot token and live API access.
Currently the only unit tests cover trivial pure functions (is_command, should_send_update, state accumulation). The critical behavioral paths are untested.
Proposed Solution
Add a #[cfg(test)] constructor that injects the mpsc::Sender<IncomingMessage> from outside:
#[cfg(test)]
pub fn new_test(allowed_users: Vec<String>) -> (Self, mpsc::Sender<IncomingMessage>) {
let (tx, rx) = mpsc::channel(64);
let channel = Self {
bot: Bot::new("test_token"),
chat_id: Some(ChatId(1)),
rx,
allowed_users,
accumulated: String::new(),
last_edit: None,
message_id: None,
};
(channel, tx)
}The Bot::new("test_token") instance must never make real HTTP calls in tests — all send_message / edit_message_text paths must be gated behind self.chat_id.is_some() checks (already true for send_or_edit) or mocked at the HTTP layer (e.g., wiremock).
Test Cases to Add
recv()returnsChannelMessagewhenIncomingMessageis injected viatx/resetand/skillscommands are routed correctly viarecv()/startis consumed internally without returning to callerallowed_usersfilter: messages from non-listed usernames are dropped (requires exposing username inIncomingMessageor rethinking the guard location)send_chunk()accumulates and respects 10s throttle (should_send_update)flush_chunks()sends final edit whenmessage_idis set, then clears stateconfirm()returnsfalseon 30s timeout (usetokio::time::pause())confirm()returnstruewhenyesinjected within timeoutconfirm()returnsfalseon channel close
Acceptance Criteria
-
new_test()constructor added under#[cfg(test)] - All behavioral scenarios above covered by
#[tokio::test]tests intelegram.rs - No real HTTP calls in tests (either mock HTTP or avoid paths that call bot API)
-
cargo nextest run -p zeph-channelspasses with all new tests - No changes to production code paths (only additive
#[cfg(test)]additions)
Priority
Medium — the channel works in production but test coverage is a blind spot that will cause regressions to go undetected as the channel evolves.
Related
- Playbook:
.local/testing/playbooks/telegram-channel.md(Approach 3) - Issue fix(tui): remove duplicate ToolStart/ToolOutput events in TUI bridge (#2116) #2118 (Telethon E2E testing) for the live end-to-end layer