Files
telegram-tui/tests/navigation.rs
Mikhail Kilin 3b7ef41cae
Some checks failed
ci/woodpecker/pr/check Pipeline was successful
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
fix: resolve all 40 clippy warnings (dead_code, unused_imports, lints)
- Add #[allow(unused_imports)] on pub re-exports used only by lib/tests
- Add #[allow(dead_code)] on public API items unused in binary target
- Fix collapsible_if, redundant_closure, unnecessary_map_or in main.rs
- Prefix unused test variables with underscore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:50:18 +03:00

231 lines
8.0 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Integration tests for navigation flow
mod helpers;
use helpers::fake_tdclient::FakeTdClient;
use helpers::test_data::{create_test_chat, TestMessageBuilder};
use tele_tui::types::{ChatId, MessageId};
/// Test: Навигация вверх/вниз по списку чатов
#[tokio::test]
async fn test_navigate_chat_list_up_down() {
let client = FakeTdClient::new();
let chat1 = create_test_chat("Mom", 123);
let chat2 = create_test_chat("Boss", 456);
let chat3 = create_test_chat("Friend", 789);
let client = client.with_chats(vec![chat1, chat2, chat3]);
let chats = client.get_chats();
// Начинаем с индекса 0
let mut selected_index = 0;
assert_eq!(chats[selected_index].title, "Mom");
// ↓ - вниз
selected_index = (selected_index + 1).min(chats.len() - 1);
assert_eq!(selected_index, 1);
assert_eq!(chats[selected_index].title, "Boss");
// ↓ - ещё вниз
selected_index = (selected_index + 1).min(chats.len() - 1);
assert_eq!(selected_index, 2);
assert_eq!(chats[selected_index].title, "Friend");
// ↓ - на границе (не должно выйти за пределы)
selected_index = (selected_index + 1).min(chats.len() - 1);
assert_eq!(selected_index, 2); // Остался на последнем
// ↑ - вверх
selected_index = selected_index.saturating_sub(1);
assert_eq!(selected_index, 1);
assert_eq!(chats[selected_index].title, "Boss");
// ↑ - ещё вверх
selected_index = selected_index.saturating_sub(1);
assert_eq!(selected_index, 0);
assert_eq!(chats[selected_index].title, "Mom");
// ↑ - на границе (не должно выйти за пределы)
selected_index = selected_index.saturating_sub(1);
assert_eq!(selected_index, 0); // Остался на первом
}
/// Test: Enter открывает чат
#[tokio::test]
async fn test_enter_opens_chat() {
let client = FakeTdClient::new();
let chat = create_test_chat("Mom", 123);
let _client = client.with_chat(chat);
// Состояние: список чатов, выбран чат 123
let selected_chat_id: Option<i64> = None;
// Пользователь нажал Enter
let new_selected_chat_id = Some(123);
assert_eq!(selected_chat_id, None);
assert_eq!(new_selected_chat_id, Some(123));
}
/// Test: Esc закрывает чат
#[tokio::test]
async fn test_esc_closes_chat() {
// Состояние: открыт чат 123
let _selected_chat_id = Some(123);
// Пользователь нажал Esc
let selected_chat_id: Option<i64> = None;
assert_eq!(selected_chat_id, None);
}
/// Test: Скролл сообщений в чате
#[tokio::test]
async fn test_scroll_messages_in_chat() {
let client = FakeTdClient::new();
let messages = vec![
TestMessageBuilder::new("Msg 1", 1).build(),
TestMessageBuilder::new("Msg 2", 2).build(),
TestMessageBuilder::new("Msg 3", 3).build(),
TestMessageBuilder::new("Msg 4", 4).build(),
TestMessageBuilder::new("Msg 5", 5).build(),
];
let client = client.with_messages(123, messages);
let _msgs = client.get_messages(123);
// Скролл начинается снизу (последнее сообщение видно)
let mut scroll_offset: usize = 0;
// ↑ - скролл вверх (увеличиваем offset)
scroll_offset += 1;
assert_eq!(scroll_offset, 1);
// ↑ - ещё вверх
scroll_offset += 1;
assert_eq!(scroll_offset, 2);
// ↓ - скролл вниз (уменьшаем offset)
scroll_offset = scroll_offset.saturating_sub(1);
assert_eq!(scroll_offset, 1);
// ↓ - к низу
scroll_offset = scroll_offset.saturating_sub(1);
assert_eq!(scroll_offset, 0);
// ↓ - на границе
scroll_offset = scroll_offset.saturating_sub(1);
assert_eq!(scroll_offset, 0); // Не уходим в минус
}
/// Test: Переключение между папками (1-9)
#[tokio::test]
async fn test_switch_folders() {
let client = FakeTdClient::new();
// Добавляем папки (FakeTdClient уже создаёт "All" с id=0)
let client = client.with_folder(1, "Personal").with_folder(2, "Work");
let folders = client.get_folders();
// Проверяем что папки на месте
assert_eq!(folders.len(), 3);
assert_eq!(folders[0].name, "All");
assert_eq!(folders[1].name, "Personal");
assert_eq!(folders[2].name, "Work");
// Начинаем с папки 0 (All)
let mut selected_folder_index = 0;
assert_eq!(folders[selected_folder_index].name, "All");
// Нажали '1' - папка Personal (индекс 1)
selected_folder_index = 1;
assert_eq!(folders[selected_folder_index].name, "Personal");
// Нажали '2' - папка Work (индекс 2)
selected_folder_index = 2;
assert_eq!(folders[selected_folder_index].name, "Work");
// Нажали '0' (или Esc из папки) - обратно в All (индекс 0)
selected_folder_index = 0;
assert_eq!(folders[selected_folder_index].name, "All");
}
/// Test: Русская раскладка для навигации (р/о/л/д)
#[tokio::test]
async fn test_russian_layout_navigation() {
// В реальном App: к/j/h/l маппятся на р/о/л/д для русской раскладки
// Mapping:
// j (down) <-> о
// k (up) <-> л
// h (left) <-> р
// l (right) <-> д
let mut selected_index = 1;
// Симулируем нажатие 'о' (как 'j' - вниз)
selected_index += 1;
assert_eq!(selected_index, 2);
// 'л' (как 'k' - вверх)
selected_index -= 1;
assert_eq!(selected_index, 1);
// Проверяем что логика работает одинаково
assert!(true); // Реальный тест был бы в input handler
}
/// Test: Подгрузка старых сообщений при скролле вверх
#[tokio::test]
async fn test_load_older_messages_on_scroll_up() {
let client = FakeTdClient::new();
// Начальные сообщения (последние 10)
let initial_messages = vec![
TestMessageBuilder::new("Msg 91", 91).build(),
TestMessageBuilder::new("Msg 92", 92).build(),
TestMessageBuilder::new("Msg 93", 93).build(),
TestMessageBuilder::new("Msg 94", 94).build(),
TestMessageBuilder::new("Msg 95", 95).build(),
TestMessageBuilder::new("Msg 96", 96).build(),
TestMessageBuilder::new("Msg 97", 97).build(),
TestMessageBuilder::new("Msg 98", 98).build(),
TestMessageBuilder::new("Msg 99", 99).build(),
TestMessageBuilder::new("Msg 100", 100).build(),
];
let client = client.with_messages(123, initial_messages);
assert_eq!(client.get_messages(123).len(), 10);
// Пользователь скроллит до самого верха (дошёл до Msg 91)
// Триггерим подгрузку старых сообщений
// Симулируем подгрузку (добавляем старые сообщения в начало)
let older_messages = vec![
TestMessageBuilder::new("Msg 81", 81).build(),
TestMessageBuilder::new("Msg 82", 82).build(),
TestMessageBuilder::new("Msg 83", 83).build(),
TestMessageBuilder::new("Msg 84", 84).build(),
TestMessageBuilder::new("Msg 85", 85).build(),
];
// Добавляем к существующим (в реальности - prepend)
let mut all_messages = older_messages;
all_messages.extend(client.get_messages(123));
let client = client.with_messages(123, all_messages);
// Теперь должно быть 15 сообщений
let messages = client.get_messages(123);
assert_eq!(messages.len(), 15);
assert_eq!(messages[0].content.text, "Msg 81");
assert_eq!(messages[14].content.text, "Msg 100");
}