This commit is contained in:
Mikhail Kilin
2026-01-30 15:07:13 +03:00
parent 126c7482af
commit 4deb0fbe00
32 changed files with 1049 additions and 697 deletions

View File

@@ -2,9 +2,9 @@
mod helpers;
use helpers::test_data::{TestChatBuilder, create_test_chat};
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::{create_test_chat, TestChatBuilder};
use insta::assert_snapshot;
#[test]
@@ -44,9 +44,7 @@ fn snapshot_chat_with_unread_count() {
.last_message("Привет, как дела?")
.build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::chat_list::render(f, f.area(), &mut app);
@@ -63,9 +61,7 @@ fn snapshot_chat_with_pinned() {
.last_message("Pinned message")
.build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::chat_list::render(f, f.area(), &mut app);
@@ -83,9 +79,7 @@ fn snapshot_chat_with_muted() {
.last_message("Too many messages")
.build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::chat_list::render(f, f.area(), &mut app);
@@ -103,9 +97,7 @@ fn snapshot_chat_with_mentions() {
.last_message("@me check this out")
.build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::chat_list::render(f, f.area(), &mut app);
@@ -139,9 +131,7 @@ fn snapshot_chat_long_title() {
.last_message("Test message")
.build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::chat_list::render(f, f.area(), &mut app);

View File

@@ -61,9 +61,7 @@ fn test_can_only_delete_own_messages_for_all() {
let mut client = FakeTdClient::new();
// Наше исходящее сообщение (можно удалить для всех)
let outgoing_msg = TestMessageBuilder::new("My message", 1)
.outgoing()
.build();
let outgoing_msg = TestMessageBuilder::new("My message", 1).outgoing().build();
client = client.with_message(123, outgoing_msg);
@@ -76,7 +74,7 @@ fn test_can_only_delete_own_messages_for_all() {
// Проверяем флаги удаления
let messages = client.get_messages(123);
assert_eq!(messages[0].can_be_deleted_for_all_users, true); // Наше
assert_eq!(messages[0].can_be_deleted_for_all_users, true); // Наше
assert_eq!(messages[1].can_be_deleted_for_all_users, false); // Чужое
// Оба можно удалить для себя

View File

@@ -12,9 +12,7 @@ struct DraftManager {
impl DraftManager {
fn new() -> Self {
Self {
drafts: HashMap::new(),
}
Self { drafts: HashMap::new() }
}
/// Сохранить черновик для чата

View File

@@ -55,9 +55,7 @@ fn test_can_only_edit_own_messages() {
let mut client = FakeTdClient::new();
// Наше исходящее сообщение (можно редактировать)
let outgoing_msg = TestMessageBuilder::new("My message", 1)
.outgoing()
.build();
let outgoing_msg = TestMessageBuilder::new("My message", 1).outgoing().build();
client = client.with_message(123, outgoing_msg);
@@ -70,7 +68,7 @@ fn test_can_only_edit_own_messages() {
// Проверяем флаги
let messages = client.get_messages(123);
assert_eq!(messages[0].can_be_edited, true); // Наше сообщение
assert_eq!(messages[0].can_be_edited, true); // Наше сообщение
assert_eq!(messages[1].can_be_edited, false); // Чужое сообщение
}

View File

@@ -2,9 +2,9 @@
mod helpers;
use helpers::test_data::create_test_chat;
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::create_test_chat;
use insta::assert_snapshot;
use tele_tui::tdlib::NetworkState;
@@ -12,9 +12,7 @@ use tele_tui::tdlib::NetworkState;
fn snapshot_footer_chat_list() {
let chat = create_test_chat("Mom", 123);
let app = TestAppBuilder::new()
.with_chat(chat)
.build();
let app = TestAppBuilder::new().with_chat(chat).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::footer::render(f, f.area(), &app);
@@ -45,9 +43,7 @@ fn snapshot_footer_open_chat() {
fn snapshot_footer_network_waiting() {
let chat = create_test_chat("Mom", 123);
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
// Set network state to WaitingForNetwork
app.td_client.network_state = NetworkState::WaitingForNetwork;
@@ -64,9 +60,7 @@ fn snapshot_footer_network_waiting() {
fn snapshot_footer_network_connecting_proxy() {
let chat = create_test_chat("Mom", 123);
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
// Set network state to ConnectingToProxy
app.td_client.network_state = NetworkState::ConnectingToProxy;
@@ -83,9 +77,7 @@ fn snapshot_footer_network_connecting_proxy() {
fn snapshot_footer_network_connecting() {
let chat = create_test_chat("Mom", 123);
let mut app = TestAppBuilder::new()
.with_chat(chat)
.build();
let mut app = TestAppBuilder::new().with_chat(chat).build();
// Set network state to Connecting
app.td_client.network_state = NetworkState::Connecting;

View File

@@ -1,11 +1,11 @@
// Test App builder
use tele_tui::app::{App, AppScreen};
use tele_tui::config::Config;
use tele_tui::tdlib::{ChatInfo, MessageInfo};
use tele_tui::tdlib::client::AuthState;
use ratatui::widgets::ListState;
use std::collections::HashMap;
use tele_tui::app::{App, AppScreen};
use tele_tui::config::Config;
use tele_tui::tdlib::client::AuthState;
use tele_tui::tdlib::{ChatInfo, MessageInfo};
/// Builder для создания тестового App
///
@@ -149,13 +149,19 @@ impl TestAppBuilder {
/// Добавить сообщение для чата
pub fn with_message(mut self, chat_id: i64, message: MessageInfo) -> Self {
self.messages.entry(chat_id).or_insert_with(Vec::new).push(message);
self.messages
.entry(chat_id)
.or_insert_with(Vec::new)
.push(message);
self
}
/// Добавить несколько сообщений для чата
pub fn with_messages(mut self, chat_id: i64, messages: Vec<MessageInfo>) -> Self {
self.messages.entry(chat_id).or_insert_with(Vec::new).extend(messages);
self.messages
.entry(chat_id)
.or_insert_with(Vec::new)
.extend(messages);
self
}
@@ -329,9 +335,7 @@ mod tests {
#[test]
fn test_builder_search_mode() {
let app = TestAppBuilder::new()
.searching("test query")
.build();
let app = TestAppBuilder::new().searching("test query").build();
assert!(app.is_searching);
assert_eq!(app.search_query, "test query");

View File

@@ -1,7 +1,7 @@
// Fake TDLib client for testing
use std::collections::HashMap;
use tele_tui::tdlib::{ChatInfo, MessageInfo, FolderInfo, NetworkState};
use tele_tui::tdlib::{ChatInfo, FolderInfo, MessageInfo, NetworkState};
/// Упрощённый mock TDLib клиента для тестов
#[derive(Clone)]
@@ -42,12 +42,7 @@ impl FakeTdClient {
Self {
chats: vec![],
messages: HashMap::new(),
folders: vec![
FolderInfo {
id: 0,
name: "All".to_string(),
},
],
folders: vec![FolderInfo { id: 0, name: "All".to_string() }],
user_names: HashMap::new(),
network_state: NetworkState::Ready,
typing_chat_id: None,
@@ -90,10 +85,7 @@ impl FakeTdClient {
/// Добавить папку
pub fn with_folder(mut self, id: i32, name: &str) -> Self {
self.folders.push(FolderInfo {
id,
name: name.to_string(),
});
self.folders.push(FolderInfo { id, name: name.to_string() });
self
}
@@ -116,10 +108,7 @@ impl FakeTdClient {
/// Получить сообщения для чата
pub fn get_messages(&self, chat_id: i64) -> Vec<MessageInfo> {
self.messages
.get(&chat_id)
.cloned()
.unwrap_or_default()
self.messages.get(&chat_id).cloned().unwrap_or_default()
}
/// Получить папки
@@ -131,11 +120,8 @@ impl FakeTdClient {
pub fn send_message(&mut self, chat_id: i64, text: String, reply_to: Option<i64>) -> i64 {
let message_id = (self.sent_messages.len() as i64) + 1000;
self.sent_messages.push(SentMessage {
chat_id,
text: text.clone(),
reply_to,
});
self.sent_messages
.push(SentMessage { chat_id, text: text.clone(), reply_to });
// Добавляем сообщение в список сообщений чата
let message = MessageInfo {
@@ -165,10 +151,8 @@ impl FakeTdClient {
/// Редактировать сообщение (мок)
pub fn edit_message(&mut self, chat_id: i64, message_id: i64, new_text: String) {
self.edited_messages.push(EditedMessage {
message_id,
new_text: new_text.clone(),
});
self.edited_messages
.push(EditedMessage { message_id, new_text: new_text.clone() });
// Обновляем сообщение в списке
if let Some(messages) = self.messages.get_mut(&chat_id) {

View File

@@ -1,9 +1,9 @@
// Snapshot testing utilities
use ratatui::backend::TestBackend;
use ratatui::Terminal;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::Terminal;
/// Конвертирует Buffer в читаемую строку для snapshot тестов
pub fn buffer_to_string(buffer: &Buffer) -> String {
@@ -33,9 +33,7 @@ where
let backend = TestBackend::new(width, height);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(render_fn)
.unwrap();
terminal.draw(render_fn).unwrap();
terminal.backend().buffer().clone()
}
@@ -44,7 +42,7 @@ where
#[macro_export]
macro_rules! assert_ui_snapshot {
($name:expr, $width:expr, $height:expr, $render_fn:expr) => {{
use $crate::helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use $crate::helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
let buffer = render_to_buffer($width, $height, $render_fn);
let output = buffer_to_string(&buffer);
insta::assert_snapshot!($name, output);
@@ -59,9 +57,7 @@ mod tests {
#[test]
fn test_buffer_to_string_simple() {
let buffer = render_to_buffer(10, 3, |f| {
let block = Block::default()
.borders(Borders::ALL)
.title("Hi");
let block = Block::default().borders(Borders::ALL).title("Hi");
f.render_widget(block, f.area());
});

View File

@@ -1,6 +1,6 @@
// Test data builders and fixtures
use tele_tui::tdlib::{ChatInfo, MessageInfo, ReactionInfo, ReplyInfo, ForwardInfo, ProfileInfo};
use tele_tui::tdlib::{ChatInfo, ForwardInfo, MessageInfo, ProfileInfo, ReactionInfo, ReplyInfo};
/// Builder для создания тестового чата
pub struct TestChatBuilder {
@@ -181,11 +181,8 @@ impl TestMessageBuilder {
}
pub fn reaction(mut self, emoji: &str, count: i32, chosen: bool) -> Self {
self.reactions.push(ReactionInfo {
emoji: emoji.to_string(),
count,
is_chosen: chosen,
});
self.reactions
.push(ReactionInfo { emoji: emoji.to_string(), count, is_chosen: chosen });
self
}

View File

@@ -2,9 +2,9 @@
mod helpers;
use helpers::test_data::{TestMessageBuilder, create_test_chat};
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::{create_test_chat, TestMessageBuilder};
use insta::assert_snapshot;
#[test]

View File

@@ -2,9 +2,9 @@
mod helpers;
use helpers::test_data::{TestChatBuilder, TestMessageBuilder, create_test_chat};
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::{create_test_chat, TestChatBuilder, TestMessageBuilder};
use insta::assert_snapshot;
#[test]
@@ -48,9 +48,7 @@ fn snapshot_single_incoming_message() {
#[test]
fn snapshot_single_outgoing_message() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Hi mom!", 1)
.outgoing()
.build();
let message = TestMessageBuilder::new("Hi mom!", 1).outgoing().build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -122,9 +120,7 @@ fn snapshot_sender_grouping() {
#[test]
fn snapshot_outgoing_sent() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Just sent", 1)
.outgoing()
.build();
let message = TestMessageBuilder::new("Just sent", 1).outgoing().build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -173,9 +169,7 @@ fn snapshot_outgoing_read() {
#[test]
fn snapshot_edited_message() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Edited text", 1)
.edited()
.build();
let message = TestMessageBuilder::new("Edited text", 1).edited().build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -195,8 +189,7 @@ fn snapshot_edited_message() {
fn snapshot_long_message_wrap() {
let chat = create_test_chat("Mom", 123);
let long_text = "This is a very long message that should wrap across multiple lines when rendered in the terminal UI. Let's make it even longer to ensure we test the wrapping behavior properly.";
let message = TestMessageBuilder::new(long_text, 1)
.build();
let message = TestMessageBuilder::new(long_text, 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -215,8 +208,7 @@ fn snapshot_long_message_wrap() {
#[test]
fn snapshot_markdown_bold_italic_code() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("**bold** *italic* `code`", 1)
.build();
let message = TestMessageBuilder::new("**bold** *italic* `code`", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -235,8 +227,8 @@ fn snapshot_markdown_bold_italic_code() {
#[test]
fn snapshot_markdown_link_mention() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Check [this](https://example.com) and @username", 1)
.build();
let message =
TestMessageBuilder::new("Check [this](https://example.com) and @username", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -255,8 +247,7 @@ fn snapshot_markdown_link_mention() {
#[test]
fn snapshot_markdown_spoiler() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Spoiler: ||hidden text||", 1)
.build();
let message = TestMessageBuilder::new("Spoiler: ||hidden text||", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -275,8 +266,7 @@ fn snapshot_markdown_spoiler() {
#[test]
fn snapshot_media_placeholder() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("[Фото]", 1)
.build();
let message = TestMessageBuilder::new("[Фото]", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -380,8 +370,7 @@ fn snapshot_multiple_reactions() {
#[test]
fn snapshot_selected_message() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Selected message", 1)
.build();
let message = TestMessageBuilder::new("Selected message", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)

View File

@@ -2,17 +2,17 @@
mod helpers;
use helpers::test_data::{TestChatBuilder, TestMessageBuilder, create_test_chat, create_test_profile};
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::{
create_test_chat, create_test_profile, TestChatBuilder, TestMessageBuilder,
};
use insta::assert_snapshot;
#[test]
fn snapshot_delete_confirmation_modal() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("Delete me", 1)
.outgoing()
.build();
let message = TestMessageBuilder::new("Delete me", 1).outgoing().build();
let app = TestAppBuilder::new()
.with_chat(chat)
@@ -32,8 +32,7 @@ fn snapshot_delete_confirmation_modal() {
#[test]
fn snapshot_emoji_picker_default() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("React to this", 1)
.build();
let message = TestMessageBuilder::new("React to this", 1).build();
let app = TestAppBuilder::new()
.with_chat(chat)
@@ -53,8 +52,7 @@ fn snapshot_emoji_picker_default() {
#[test]
fn snapshot_emoji_picker_with_selection() {
let chat = create_test_chat("Mom", 123);
let message = TestMessageBuilder::new("React to this", 1)
.build();
let message = TestMessageBuilder::new("React to this", 1).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -97,8 +95,7 @@ fn snapshot_profile_personal_chat() {
#[test]
fn snapshot_profile_group_chat() {
let chat = TestChatBuilder::new("Work Group", 456)
.build();
let chat = TestChatBuilder::new("Work Group", 456).build();
let mut profile = create_test_profile("Work Group", 456);
profile.is_group = true;
@@ -125,10 +122,8 @@ fn snapshot_profile_group_chat() {
#[test]
fn snapshot_pinned_message() {
let chat = create_test_chat("Mom", 123);
let message1 = TestMessageBuilder::new("Regular message", 1)
.build();
let pinned_msg = TestMessageBuilder::new("Important pinned message!", 2)
.build();
let message1 = TestMessageBuilder::new("Regular message", 1).build();
let pinned_msg = TestMessageBuilder::new("Important pinned message!", 2).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -150,12 +145,9 @@ fn snapshot_pinned_message() {
#[test]
fn snapshot_search_in_chat() {
let chat = create_test_chat("Mom", 123);
let msg1 = TestMessageBuilder::new("Hello world", 1)
.build();
let msg2 = TestMessageBuilder::new("World is beautiful", 2)
.build();
let msg3 = TestMessageBuilder::new("Beautiful day", 3)
.build();
let msg1 = TestMessageBuilder::new("Hello world", 1).build();
let msg2 = TestMessageBuilder::new("World is beautiful", 2).build();
let msg3 = TestMessageBuilder::new("Beautiful day", 3).build();
let mut app = TestAppBuilder::new()
.with_chat(chat)
@@ -182,8 +174,7 @@ fn snapshot_forward_mode() {
let chat2 = create_test_chat("Dad", 456);
let chat3 = create_test_chat("Work Group", 789);
let message = TestMessageBuilder::new("Forward this message", 1)
.build();
let message = TestMessageBuilder::new("Forward this message", 1).build();
let mut app = TestAppBuilder::new()
.with_chats(vec![chat1.clone(), chat2, chat3])

View File

@@ -128,9 +128,7 @@ fn test_switch_folders() {
let mut client = FakeTdClient::new();
// Добавляем папки (FakeTdClient уже создаёт "All" с id=0)
client = client
.with_folder(1, "Personal")
.with_folder(2, "Work");
client = client.with_folder(1, "Personal").with_folder(2, "Work");
let folders = client.get_folders();

View File

@@ -3,7 +3,7 @@
mod helpers;
use helpers::app_builder::TestAppBuilder;
use helpers::snapshot_utils::{render_to_buffer, buffer_to_string};
use helpers::snapshot_utils::{buffer_to_string, render_to_buffer};
use helpers::test_data::create_test_chat;
use insta::assert_snapshot;
use tele_tui::app::AppScreen;
@@ -11,9 +11,7 @@ use tele_tui::tdlib::client::AuthState;
#[test]
fn snapshot_loading_screen_default() {
let mut app = TestAppBuilder::new()
.screen(AppScreen::Loading)
.build();
let mut app = TestAppBuilder::new().screen(AppScreen::Loading).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::render(f, &mut app);
@@ -88,9 +86,7 @@ fn snapshot_auth_screen_password() {
#[test]
fn snapshot_main_screen_empty() {
let mut app = TestAppBuilder::new()
.screen(AppScreen::Main)
.build();
let mut app = TestAppBuilder::new().screen(AppScreen::Main).build();
let buffer = render_to_buffer(80, 24, |f| {
tele_tui::ui::render(f, &mut app);
@@ -103,7 +99,7 @@ fn snapshot_main_screen_empty() {
#[test]
fn snapshot_main_screen_terminal_too_small() {
let chat = create_test_chat("Mom", 123);
let mut app = TestAppBuilder::new()
.screen(AppScreen::Main)
.with_chat(chat)

View File

@@ -34,13 +34,9 @@ fn test_search_chats_by_title() {
fn test_search_chats_by_username() {
let mut client = FakeTdClient::new();
let chat1 = TestChatBuilder::new("Alice", 123)
.username("alice")
.build();
let chat1 = TestChatBuilder::new("Alice", 123).username("alice").build();
let chat2 = TestChatBuilder::new("Bob", 456)
.username("bobby")
.build();
let chat2 = TestChatBuilder::new("Bob", 456).username("bobby").build();
let chat3 = TestChatBuilder::new("Charlie", 789).build(); // Без username

View File

@@ -139,7 +139,7 @@ fn test_receive_incoming_message() {
// Проверяем что в списке 2 сообщения
let messages = client.get_messages(123);
assert_eq!(messages.len(), 2);
assert_eq!(messages[0].is_outgoing, true); // Наше сообщение
assert_eq!(messages[0].is_outgoing, true); // Наше сообщение
assert_eq!(messages[1].is_outgoing, false); // Входящее
assert_eq!(messages[1].content, "Hey there!");
assert_eq!(messages[1].sender_name, "Alice");