Files
telegram-tui/tests/navigation.rs
Mikhail Kilin 43960332d9 refactor: restructure MessageInfo with logical field grouping (P2.6)
Сгруппированы 16 плоских полей MessageInfo в 4 логические структуры
для улучшения организации кода и maintainability.

Новые структуры:
- MessageMetadata: id, sender_name, date, edit_date
- MessageContent: text, entities
- MessageState: is_outgoing, is_read, can_be_edited, can_be_deleted_*
- MessageInteractions: reply_to, forward_from, reactions

Изменения:
- Добавлены 4 новые структуры в tdlib/types.rs
- Обновлена MessageInfo для использования новых структур
- Добавлен конструктор MessageInfo::new() для удобного создания
- Добавлены getter методы (id(), text(), sender_name() и др.) для удобного доступа
- Обновлены все места создания MessageInfo (convert_message)
- Обновлены все места использования (~200+ обращений):
  * ui/messages.rs: рендеринг сообщений
  * app/mod.rs: логика приложения
  * input/main_input.rs: обработка ввода и копирование
  * tdlib/client.rs: обработка updates
  * Все тестовые файлы (14 файлов)

Преимущества:
- Логическая группировка данных
- Проще понимать структуру сообщения
- Легче добавлять новые поля в будущем
- Улучшенная читаемость кода

Статус: Priority 2 теперь 80% (4/5 задач)
-  Error enum
-  Config validation
-  Newtype для ID
-  MessageInfo реструктуризация
-  MessageBuilder pattern

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 01:45:54 +03:00

229 lines
7.8 KiB
Rust
Raw 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};
/// Test: Навигация вверх/вниз по списку чатов
#[test]
fn test_navigate_chat_list_up_down() {
let mut client = FakeTdClient::new();
let chat1 = create_test_chat("Mom", 123);
let chat2 = create_test_chat("Boss", 456);
let chat3 = create_test_chat("Friend", 789);
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 открывает чат
#[test]
fn test_enter_opens_chat() {
let mut 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 закрывает чат
#[test]
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: Скролл сообщений в чате
#[test]
fn test_scroll_messages_in_chat() {
let mut 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(),
];
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)
#[test]
fn test_switch_folders() {
let mut client = FakeTdClient::new();
// Добавляем папки (FakeTdClient уже создаёт "All" с id=0)
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: Русская раскладка для навигации (р/о/л/д)
#[test]
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: Подгрузка старых сообщений при скролле вверх
#[test]
fn test_load_older_messages_on_scroll_up() {
let mut 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(),
];
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));
client.messages.insert(123, all_messages);
// Теперь должно быть 15 сообщений
assert_eq!(client.get_messages(123).len(), 15);
assert_eq!(client.get_messages(123)[0].content.text(), "Msg 81");
assert_eq!(client.get_messages(123)[14].content.text(), "Msg 100");
}