Files
telegram-tui/tests/search.rs
Mikhail Kilin c5896b7f14 tests
2026-01-31 23:02:53 +03:00

239 lines
7.6 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 search flow
mod helpers;
use helpers::fake_tdclient::FakeTdClient;
use helpers::test_data::{create_test_chat, TestChatBuilder, TestMessageBuilder};
use tele_tui::types::{ChatId, MessageId};
/// Test: Поиск по чатам фильтрует по названию
#[tokio::test]
async fn test_search_chats_by_title() {
let client = FakeTdClient::new();
let chat1 = create_test_chat("Mom", 123);
let chat2 = create_test_chat("Boss", 456);
let chat3 = create_test_chat("Mom's Work", 789);
let client = client.with_chats(vec![chat1, chat2, chat3]);
// Ищем "mom" - должно найти "Mom" и "Mom's Work"
let query = "mom".to_lowercase();
let chats = client.get_chats();
let filtered: Vec<_> = chats
.iter()
.filter(|c| c.title.to_lowercase().contains(&query))
.collect();
assert_eq!(filtered.len(), 2);
assert_eq!(filtered[0].title, "Mom");
assert_eq!(filtered[1].title, "Mom's Work");
}
/// Test: Поиск по чатам фильтрует по @username
#[tokio::test]
async fn test_search_chats_by_username() {
let client = FakeTdClient::new();
let chat1 = TestChatBuilder::new("Alice", 123).username("alice").build();
let chat2 = TestChatBuilder::new("Bob", 456).username("bobby").build();
let chat3 = TestChatBuilder::new("Charlie", 789).build(); // Без username
let client = client.with_chats(vec![chat1, chat2, chat3]);
// Ищем "bob" - должно найти "Bob" (@bobby)
let query = "bob".to_lowercase();
let chats = client.get_chats();
let filtered: Vec<_> = chats
.iter()
.filter(|c| {
c.title.to_lowercase().contains(&query)
|| c.username
.as_ref()
.map(|u| u.to_lowercase().contains(&query))
.unwrap_or(false)
})
.collect();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0].title, "Bob");
}
/// Test: Пустой поисковый запрос возвращает все чаты
#[tokio::test]
async fn test_search_empty_query_returns_all() {
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 query = "";
let chats = client.get_chats();
let filtered: Vec<_> = chats
.iter()
.filter(|c| c.title.to_lowercase().contains(query))
.collect();
// Все чаты проходят фильтр (пустая строка содержится в любой строке)
assert_eq!(filtered.len(), 3);
}
/// Test: Поиск внутри чата по тексту сообщений
#[tokio::test]
async fn test_search_messages_in_chat() {
let client = FakeTdClient::new();
let msg1 = TestMessageBuilder::new("Hello world", 100).build();
let msg2 = TestMessageBuilder::new("How are you?", 101).build();
let msg3 = TestMessageBuilder::new("Hello again", 102).build();
let client = client.with_messages(123, vec![msg1, msg2, msg3]);
// Ищем "hello"
let query = "hello".to_lowercase();
let messages = client.get_messages(123);
let found: Vec<_> = messages
.iter()
.filter(|m| m.text().to_lowercase().contains(&query))
.collect();
assert_eq!(found.len(), 2);
assert_eq!(found[0].text(), "Hello world");
assert_eq!(found[1].text(), "Hello again");
}
/// Test: Навигация по результатам поиска (n/N)
#[tokio::test]
async fn test_navigate_search_results() {
let client = FakeTdClient::new();
let msg1 = TestMessageBuilder::new("First match", 100).build();
let msg2 = TestMessageBuilder::new("Second match", 101).build();
let msg3 = TestMessageBuilder::new("Third match", 102).build();
let client = client.with_messages(123, vec![msg1, msg2, msg3]);
// Ищем "match"
let query = "match".to_lowercase();
let messages = client.get_messages(123);
let results: Vec<_> = messages
.iter()
.enumerate()
.filter(|(_, m)| m.text().to_lowercase().contains(&query))
.collect();
assert_eq!(results.len(), 3);
// Навигация: начинаем с индекса 0
let mut current_index = 0;
// n - следующий результат
current_index = (current_index + 1) % results.len();
assert_eq!(current_index, 1);
assert_eq!(results[current_index].1.text(), "Second match");
// n - ещё один
current_index = (current_index + 1) % results.len();
assert_eq!(current_index, 2);
assert_eq!(results[current_index].1.text(), "Third match");
// n - wrap around к первому
current_index = (current_index + 1) % results.len();
assert_eq!(current_index, 0);
assert_eq!(results[current_index].1.text(), "First match");
// N - предыдущий (wrap to last)
current_index = if current_index == 0 {
results.len() - 1
} else {
current_index - 1
};
assert_eq!(current_index, 2);
assert_eq!(results[current_index].1.text(), "Third match");
}
/// Test: Поиск с учётом регистра (case-insensitive)
#[tokio::test]
async fn test_search_case_insensitive() {
let client = FakeTdClient::new();
let msg1 = TestMessageBuilder::new("HELLO", 100).build();
let msg2 = TestMessageBuilder::new("hello", 101).build();
let msg3 = TestMessageBuilder::new("HeLLo", 102).build();
let client = client.with_messages(123, vec![msg1, msg2, msg3]);
// Ищем "hello" (lowercase)
let query = "hello".to_lowercase();
let messages = client.get_messages(123);
let found: Vec<_> = messages
.iter()
.filter(|m| m.text().to_lowercase().contains(&query))
.collect();
// Все 3 варианта должны найтись
assert_eq!(found.len(), 3);
}
/// Test: Поиск не находит ничего
#[tokio::test]
async fn test_search_no_results() {
let client = FakeTdClient::new();
let msg1 = TestMessageBuilder::new("Hello", 100).build();
let msg2 = TestMessageBuilder::new("World", 101).build();
let client = client.with_messages(123, vec![msg1, msg2]);
// Ищем "xyz" - не должно найтись
let query = "xyz".to_lowercase();
let messages = client.get_messages(123);
let found: Vec<_> = messages
.iter()
.filter(|m| m.text().to_lowercase().contains(&query))
.collect();
assert_eq!(found.len(), 0);
}
/// Test: Отмена поиска (Esc) восстанавливает обычный режим
#[tokio::test]
async fn test_cancel_search_restores_normal_mode() {
let client = FakeTdClient::new();
let chat1 = create_test_chat("Mom", 123);
let chat2 = create_test_chat("Boss", 456);
let client = client.with_chats(vec![chat1, chat2]);
// Симулируем: пользователь начал поиск
let mut is_searching = true;
let mut search_query = "mom".to_string();
// Фильтруем
let query = search_query.to_lowercase();
let chats = client.get_chats();
let filtered: Vec<_> = chats
.iter()
.filter(|c| c.title.to_lowercase().contains(&query))
.collect();
assert_eq!(filtered.len(), 1);
// Пользователь нажал Esc
is_searching = false;
search_query.clear();
// После отмены видим все чаты
let all_chats = client.get_chats();
assert_eq!(all_chats.len(), 2);
assert!(!is_searching);
assert_eq!(search_query, "");
}