tests
This commit is contained in:
418
tests/e2e_user_journey.rs
Normal file
418
tests/e2e_user_journey.rs
Normal file
@@ -0,0 +1,418 @@
|
||||
// E2E User Journey tests — многошаговые интеграционные тесты
|
||||
|
||||
mod helpers;
|
||||
|
||||
use helpers::fake_tdclient::{FakeTdClient, TdUpdate};
|
||||
use helpers::test_data::{TestChatBuilder, TestMessageBuilder};
|
||||
use tele_tui::tdlib::NetworkState;
|
||||
use tele_tui::types::{ChatId, MessageId};
|
||||
|
||||
/// Тест 1: App Launch → Auth → Chat List
|
||||
/// Симулирует полный путь пользователя от запуска до загрузки чатов
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_app_launch_to_chat_list() {
|
||||
// 1. Создаем fake client (симуляция авторизации пропущена, клиент уже авторизован)
|
||||
let client = FakeTdClient::new();
|
||||
|
||||
// 2. Проверяем начальное состояние - нет чатов
|
||||
assert_eq!(client.get_chats().len(), 0);
|
||||
assert_eq!(client.get_network_state(), NetworkState::Ready);
|
||||
|
||||
// 3. Создаем чаты
|
||||
let chat1 = TestChatBuilder::new("Mom", 101).build();
|
||||
let chat2 = TestChatBuilder::new("Work Group", 102).build();
|
||||
let chat3 = TestChatBuilder::new("Boss", 103).build();
|
||||
|
||||
let client = client
|
||||
.with_chat(chat1)
|
||||
.with_chat(chat2)
|
||||
.with_chat(chat3);
|
||||
|
||||
// 4. Симулируем загрузку чатов через load_chats
|
||||
let loaded_chats = client.load_chats(50).await.unwrap();
|
||||
|
||||
// 5. Проверяем что чаты загружены
|
||||
assert_eq!(loaded_chats.len(), 3);
|
||||
assert_eq!(loaded_chats[0].title, "Mom");
|
||||
assert_eq!(loaded_chats[1].title, "Work Group");
|
||||
assert_eq!(loaded_chats[2].title, "Boss");
|
||||
|
||||
// 6. Проверяем что нет выбранного чата
|
||||
assert_eq!(client.get_current_chat_id(), None);
|
||||
}
|
||||
|
||||
/// Тест 2: Open Chat → Load History → Send Message
|
||||
/// Симулирует открытие чата, загрузку истории и отправку сообщения
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_open_chat_send_message() {
|
||||
// 1. Подготовка: создаем клиент с чатом
|
||||
let chat = TestChatBuilder::new("Mom", 123).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
// 2. Создаем несколько сообщений в истории
|
||||
let msg1 = TestMessageBuilder::new("Hi, how are you?", 1)
|
||||
.sender("Mom")
|
||||
.build();
|
||||
|
||||
let msg2 = TestMessageBuilder::new("I'm good, thanks!", 2)
|
||||
.outgoing()
|
||||
.build();
|
||||
|
||||
let client = client
|
||||
.with_message(123, msg1)
|
||||
.with_message(123, msg2);
|
||||
|
||||
// 3. Открываем чат
|
||||
client.open_chat(ChatId::new(123)).await.unwrap();
|
||||
|
||||
// 4. Проверяем что чат открыт
|
||||
assert_eq!(client.get_current_chat_id(), Some(123));
|
||||
|
||||
// 5. Загружаем историю сообщений
|
||||
let history = client.get_chat_history(ChatId::new(123), 50).await.unwrap();
|
||||
|
||||
// 6. Проверяем что история загружена
|
||||
assert_eq!(history.len(), 2);
|
||||
assert_eq!(history[0].text(), "Hi, how are you?");
|
||||
assert_eq!(history[1].text(), "I'm good, thanks!");
|
||||
|
||||
// 7. Отправляем новое сообщение
|
||||
let _new_msg = client.send_message(
|
||||
ChatId::new(123),
|
||||
"What's for dinner?".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 8. Проверяем что сообщение отправлено
|
||||
assert_eq!(client.get_sent_messages().len(), 1);
|
||||
assert_eq!(client.get_sent_messages()[0].text, "What's for dinner?");
|
||||
assert_eq!(client.get_sent_messages()[0].chat_id, 123);
|
||||
|
||||
// 9. Проверяем что сообщение добавилось в историю
|
||||
let updated_history = client.get_chat_history(ChatId::new(123), 50).await.unwrap();
|
||||
assert_eq!(updated_history.len(), 3);
|
||||
assert_eq!(updated_history[2].text(), "What's for dinner?");
|
||||
}
|
||||
|
||||
/// Тест 3: Receive Incoming Message While Chat Open
|
||||
/// Симулирует получение входящего сообщения в открытом чате
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_receive_incoming_message() {
|
||||
// 1. Подготовка: создаем клиент с открытым чатом
|
||||
let chat = TestChatBuilder::new("Friend", 456).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
// 2. Открываем чат
|
||||
client.open_chat(ChatId::new(456)).await.unwrap();
|
||||
assert_eq!(client.get_current_chat_id(), Some(456));
|
||||
|
||||
// 3. Создаем update channel для получения событий
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
client.set_update_channel(tx);
|
||||
|
||||
// 4. Проверяем начальное состояние - нет сообщений
|
||||
let initial_history = client.get_chat_history(ChatId::new(456), 50).await.unwrap();
|
||||
assert_eq!(initial_history.len(), 0);
|
||||
|
||||
// 5. Симулируем входящее сообщение от собеседника
|
||||
client.simulate_incoming_message(ChatId::new(456), "Hey! Are you there?".to_string(), "Friend");
|
||||
|
||||
// 6. Получаем update из канала
|
||||
let update = rx.try_recv();
|
||||
assert!(update.is_ok(), "Должен быть получен update о новом сообщении");
|
||||
|
||||
if let Ok(TdUpdate::NewMessage { chat_id, message }) = update {
|
||||
assert_eq!(chat_id.as_i64(), 456);
|
||||
assert_eq!(message.text(), "Hey! Are you there?");
|
||||
assert_eq!(message.sender_name(), "Friend");
|
||||
assert!(!message.is_outgoing());
|
||||
} else {
|
||||
panic!("Неверный тип update");
|
||||
}
|
||||
|
||||
// 7. Проверяем что сообщение появилось в истории
|
||||
let updated_history = client.get_chat_history(ChatId::new(456), 50).await.unwrap();
|
||||
assert_eq!(updated_history.len(), 1);
|
||||
assert_eq!(updated_history[0].text(), "Hey! Are you there?");
|
||||
}
|
||||
|
||||
/// Тест 4: Multi-step conversation flow
|
||||
/// Симулирует полноценную беседу с несколькими сообщениями туда-обратно
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_multi_step_conversation() {
|
||||
// 1. Подготовка
|
||||
let chat = TestChatBuilder::new("Alice", 789).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
// 2. Открываем чат
|
||||
client.open_chat(ChatId::new(789)).await.unwrap();
|
||||
|
||||
// 3. Setup update channel
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
client.set_update_channel(tx);
|
||||
|
||||
// 4. Входящее сообщение от Alice
|
||||
client.simulate_incoming_message(ChatId::new(789), "How's the project going?".to_string(), "Alice");
|
||||
|
||||
// Проверяем update
|
||||
let update = rx.try_recv().ok();
|
||||
assert!(matches!(update, Some(TdUpdate::NewMessage { .. })));
|
||||
|
||||
// 5. Отвечаем
|
||||
client.send_message(
|
||||
ChatId::new(789),
|
||||
"Almost done! Just need to finish tests.".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 6. Проверяем историю после первого обмена
|
||||
let history1 = client.get_chat_history(ChatId::new(789), 50).await.unwrap();
|
||||
assert_eq!(history1.len(), 2);
|
||||
|
||||
// 7. Еще одно входящее сообщение
|
||||
client.simulate_incoming_message(ChatId::new(789), "Great! Let me know if you need help.".to_string(), "Alice");
|
||||
|
||||
// 8. Снова отвечаем
|
||||
client.send_message(
|
||||
ChatId::new(789),
|
||||
"Will do, thanks!".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 9. Финальная проверка истории
|
||||
let final_history = client.get_chat_history(ChatId::new(789), 50).await.unwrap();
|
||||
assert_eq!(final_history.len(), 4);
|
||||
|
||||
// Проверяем порядок сообщений
|
||||
assert_eq!(final_history[0].text(), "How's the project going?");
|
||||
assert!(!final_history[0].is_outgoing());
|
||||
|
||||
assert_eq!(final_history[1].text(), "Almost done! Just need to finish tests.");
|
||||
assert!(final_history[1].is_outgoing());
|
||||
|
||||
assert_eq!(final_history[2].text(), "Great! Let me know if you need help.");
|
||||
assert!(!final_history[2].is_outgoing());
|
||||
|
||||
assert_eq!(final_history[3].text(), "Will do, thanks!");
|
||||
assert!(final_history[3].is_outgoing());
|
||||
}
|
||||
|
||||
/// Тест 5: Switch between chats
|
||||
/// Симулирует переключение между разными чатами
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_switch_chats() {
|
||||
// 1. Создаем несколько чатов
|
||||
let chat1 = TestChatBuilder::new("Chat 1", 111).build();
|
||||
let chat2 = TestChatBuilder::new("Chat 2", 222).build();
|
||||
let chat3 = TestChatBuilder::new("Chat 3", 333).build();
|
||||
|
||||
let client = FakeTdClient::new()
|
||||
.with_chat(chat1)
|
||||
.with_chat(chat2)
|
||||
.with_chat(chat3);
|
||||
|
||||
// 2. Открываем первый чат
|
||||
client.open_chat(ChatId::new(111)).await.unwrap();
|
||||
assert_eq!(client.get_current_chat_id(), Some(111));
|
||||
|
||||
// 3. Отправляем сообщение в первом чате
|
||||
client.send_message(
|
||||
ChatId::new(111),
|
||||
"Message in chat 1".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 4. Переключаемся на второй чат
|
||||
client.open_chat(ChatId::new(222)).await.unwrap();
|
||||
assert_eq!(client.get_current_chat_id(), Some(222));
|
||||
|
||||
// 5. Отправляем сообщение во втором чате
|
||||
client.send_message(
|
||||
ChatId::new(222),
|
||||
"Message in chat 2".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 6. Переключаемся на третий чат
|
||||
client.open_chat(ChatId::new(333)).await.unwrap();
|
||||
assert_eq!(client.get_current_chat_id(), Some(333));
|
||||
|
||||
// 7. Проверяем что сообщения были отправлены в правильные чаты
|
||||
assert_eq!(client.get_sent_messages().len(), 2);
|
||||
assert_eq!(client.get_sent_messages()[0].chat_id, 111);
|
||||
assert_eq!(client.get_sent_messages()[0].text, "Message in chat 1");
|
||||
assert_eq!(client.get_sent_messages()[1].chat_id, 222);
|
||||
assert_eq!(client.get_sent_messages()[1].text, "Message in chat 2");
|
||||
|
||||
// 8. Проверяем истории отдельных чатов
|
||||
let hist1 = client.get_chat_history(ChatId::new(111), 50).await.unwrap();
|
||||
let hist2 = client.get_chat_history(ChatId::new(222), 50).await.unwrap();
|
||||
let hist3 = client.get_chat_history(ChatId::new(333), 50).await.unwrap();
|
||||
|
||||
assert_eq!(hist1.len(), 1);
|
||||
assert_eq!(hist2.len(), 1);
|
||||
assert_eq!(hist3.len(), 0);
|
||||
}
|
||||
|
||||
/// Тест 6: Edit message in conversation flow
|
||||
/// Симулирует редактирование сообщения в процессе беседы
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_edit_during_conversation() {
|
||||
// 1. Подготовка
|
||||
let chat = TestChatBuilder::new("Bob", 555).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
client.open_chat(ChatId::new(555)).await.unwrap();
|
||||
|
||||
// 2. Отправляем сообщение с опечаткой
|
||||
let msg = client.send_message(
|
||||
ChatId::new(555),
|
||||
"I'll be there at 5pm tomorow".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 3. Проверяем что сообщение отправлено
|
||||
let history = client.get_chat_history(ChatId::new(555), 50).await.unwrap();
|
||||
assert_eq!(history.len(), 1);
|
||||
assert_eq!(history[0].text(), "I'll be there at 5pm tomorow");
|
||||
|
||||
// 4. Исправляем опечатку
|
||||
client.edit_message(
|
||||
ChatId::new(555),
|
||||
msg.id(),
|
||||
"I'll be there at 5pm tomorrow".to_string()
|
||||
).await.unwrap();
|
||||
|
||||
// 5. Проверяем что сообщение отредактировано
|
||||
let edited_history = client.get_chat_history(ChatId::new(555), 50).await.unwrap();
|
||||
assert_eq!(edited_history.len(), 1);
|
||||
assert_eq!(edited_history[0].text(), "I'll be there at 5pm tomorrow");
|
||||
assert!(edited_history[0].edit_date() > 0, "Должна быть установлена дата редактирования");
|
||||
|
||||
// 6. Проверяем историю редактирований
|
||||
assert_eq!(client.get_edited_messages().len(), 1);
|
||||
assert_eq!(client.get_edited_messages()[0].new_text, "I'll be there at 5pm tomorrow");
|
||||
}
|
||||
|
||||
/// Тест 7: Reply to message in conversation
|
||||
/// Симулирует ответ на конкретное сообщение
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_reply_in_conversation() {
|
||||
// 1. Подготовка
|
||||
let chat = TestChatBuilder::new("Charlie", 666).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
client.open_chat(ChatId::new(666)).await.unwrap();
|
||||
|
||||
// 2. Setup updates
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
client.set_update_channel(tx);
|
||||
|
||||
// 3. Входящее сообщение с вопросом
|
||||
client.simulate_incoming_message(ChatId::new(666), "Can you send me the report?".to_string(), "Charlie");
|
||||
|
||||
let update = rx.try_recv().ok();
|
||||
assert!(matches!(update, Some(TdUpdate::NewMessage { .. })));
|
||||
|
||||
let history = client.get_chat_history(ChatId::new(666), 50).await.unwrap();
|
||||
let question_msg_id = history[0].id();
|
||||
|
||||
// 4. Отправляем другое сообщение (не связанное)
|
||||
client.send_message(
|
||||
ChatId::new(666),
|
||||
"Working on it now".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 5. Отвечаем на конкретный вопрос (reply)
|
||||
let reply_info = Some(tele_tui::tdlib::ReplyInfo {
|
||||
message_id: question_msg_id,
|
||||
sender_name: "Charlie".to_string(),
|
||||
text: "Can you send me the report?".to_string(),
|
||||
});
|
||||
|
||||
client.send_message(
|
||||
ChatId::new(666),
|
||||
"Sure, sending now!".to_string(),
|
||||
Some(question_msg_id),
|
||||
reply_info
|
||||
).await.unwrap();
|
||||
|
||||
// 6. Проверяем что reply сохранён
|
||||
let final_history = client.get_chat_history(ChatId::new(666), 50).await.unwrap();
|
||||
assert_eq!(final_history.len(), 3);
|
||||
|
||||
// Последнее сообщение должно быть reply
|
||||
let reply_msg = &final_history[2];
|
||||
assert_eq!(reply_msg.text(), "Sure, sending now!");
|
||||
assert!(reply_msg.interactions.reply_to.is_some());
|
||||
|
||||
let reply_to = reply_msg.interactions.reply_to.as_ref().unwrap();
|
||||
assert_eq!(reply_to.message_id, question_msg_id);
|
||||
assert_eq!(reply_to.text, "Can you send me the report?");
|
||||
}
|
||||
|
||||
/// Тест 8: Network state changes during conversation
|
||||
/// Симулирует изменения состояния сети во время работы
|
||||
#[tokio::test]
|
||||
async fn test_user_journey_network_state_changes() {
|
||||
// 1. Подготовка
|
||||
let chat = TestChatBuilder::new("Network Test", 888).build();
|
||||
let client = FakeTdClient::new().with_chat(chat);
|
||||
|
||||
// 2. Setup updates
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
client.set_update_channel(tx);
|
||||
|
||||
// 3. Начальное состояние - Ready
|
||||
assert_eq!(client.get_network_state(), NetworkState::Ready);
|
||||
|
||||
// 4. Открываем чат и отправляем сообщение
|
||||
client.open_chat(ChatId::new(888)).await.unwrap();
|
||||
client.send_message(
|
||||
ChatId::new(888),
|
||||
"Test message".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// Очищаем канал от update NewMessage
|
||||
let _ = rx.try_recv();
|
||||
|
||||
// 5. Симулируем потерю сети
|
||||
client.simulate_network_change(NetworkState::WaitingForNetwork);
|
||||
|
||||
// Проверяем update
|
||||
let update = rx.try_recv().ok();
|
||||
assert!(matches!(update, Some(TdUpdate::ConnectionState { state: NetworkState::WaitingForNetwork })),
|
||||
"Expected ConnectionState update, got: {:?}", update);
|
||||
|
||||
// 6. Проверяем что состояние изменилось
|
||||
assert_eq!(client.get_network_state(), NetworkState::WaitingForNetwork);
|
||||
|
||||
// 7. Симулируем восстановление соединения
|
||||
client.simulate_network_change(NetworkState::Connecting);
|
||||
assert_eq!(client.get_network_state(), NetworkState::Connecting);
|
||||
|
||||
client.simulate_network_change(NetworkState::Ready);
|
||||
assert_eq!(client.get_network_state(), NetworkState::Ready);
|
||||
|
||||
// 8. Отправляем сообщение после восстановления
|
||||
client.send_message(
|
||||
ChatId::new(888),
|
||||
"Connection restored!".to_string(),
|
||||
None,
|
||||
None
|
||||
).await.unwrap();
|
||||
|
||||
// 9. Проверяем что оба сообщения в истории
|
||||
let history = client.get_chat_history(ChatId::new(888), 50).await.unwrap();
|
||||
assert_eq!(history.len(), 2);
|
||||
}
|
||||
Reference in New Issue
Block a user