Files
telegram-tui/tests/edit_message.rs
Mikhail Kilin 9df8138a46 fix: handle UpdateMessageSendSucceeded to prevent edit errors
Fixes "Message not found" error when editing immediately after sending.

**Problem**:
When sending a message, TDLib may return a temporary ID, then send
UpdateMessageSendSucceeded with the real server ID. We weren't handling
this update, so the cache kept the old ID while the server had a different
one, causing "Message not found" errors during edits.

**Solution**:
1. Added UpdateMessageSendSucceeded handler (client.rs:801-830)
   - Finds message with temporary ID
   - Replaces it with new message containing real server ID
   - Preserves reply_info if present

2. Added validation before editing (main_input.rs:574-589)
   - Checks message exists in cache
   - Better error messages with chat_id and message_id

3. Added positive ID check in start_editing_selected (mod.rs:240)
   - Blocks editing messages with temporary IDs (negative)

**Test**:
- Added test_edit_immediately_after_send (edit_message.rs:156-181)
- Verifies editing works right after send_message
- All 22 edit_message tests pass

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 01:47:12 +03:00

184 lines
8.0 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 edit message flow
mod helpers;
use helpers::fake_tdclient::FakeTdClient;
use helpers::test_data::TestMessageBuilder;
use tele_tui::types::{ChatId, MessageId};
/// Test: Редактирование сообщения изменяет текст
#[tokio::test]
async fn test_edit_message_changes_text() {
let client = FakeTdClient::new();
// Отправляем сообщение
let msg = client.send_message(ChatId::new(123), "Original text".to_string(), None, None).await.unwrap();
// Редактируем сообщение
client.edit_message(ChatId::new(123), msg.id(), "Edited text".to_string()).await.unwrap();
// Проверяем что редактирование записалось
assert_eq!(client.get_edited_messages().len(), 1);
assert_eq!(client.get_edited_messages()[0].message_id, msg.id());
assert_eq!(client.get_edited_messages()[0].new_text, "Edited text");
// Проверяем что текст сообщения изменился
let messages = client.get_messages(123);
assert_eq!(messages.len(), 1);
assert_eq!(messages[0].text(), "Edited text");
}
/// Test: Редактирование устанавливает edit_date
#[tokio::test]
async fn test_edit_message_sets_edit_date() {
let client = FakeTdClient::new();
// Отправляем сообщение
let msg = client.send_message(ChatId::new(123), "Original".to_string(), None, None).await.unwrap();
// Получаем дату до редактирования
let messages_before = client.get_messages(123);
let date_before = messages_before[0].date();
assert_eq!(messages_before[0].edit_date(), 0); // Не редактировалось
// Редактируем сообщение
client.edit_message(ChatId::new(123), msg.id(), "Edited".to_string()).await.unwrap();
// Проверяем что edit_date установлена
let messages_after = client.get_messages(123);
assert!(messages_after[0].edit_date() > 0);
assert!(messages_after[0].edit_date() > date_before); // edit_date после date
}
/// Test: Редактирование только своих сообщений (проверка через can_be_edited)
#[tokio::test]
async fn test_can_only_edit_own_messages() {
let client = FakeTdClient::new();
// Наше исходящее сообщение (можно редактировать)
let outgoing_msg = TestMessageBuilder::new("My message", 1).outgoing().build();
let client = client.with_message(123, outgoing_msg);
// Входящее сообщение от собеседника (нельзя редактировать)
let incoming_msg = TestMessageBuilder::new("Their message", 2)
.sender("Alice")
.build();
let client = client.with_message(123, incoming_msg);
// Проверяем флаги
let messages = client.get_messages(123);
assert_eq!(messages[0].can_be_edited(), true); // Наше сообщение
assert_eq!(messages[1].can_be_edited(), false); // Чужое сообщение
}
/// Test: Множественные редактирования одного сообщения
#[tokio::test]
async fn test_multiple_edits_of_same_message() {
let client = FakeTdClient::new();
let msg = client.send_message(ChatId::new(123), "Version 1".to_string(), None, None).await.unwrap();
// Первое редактирование
client.edit_message(ChatId::new(123), msg.id(), "Version 2".to_string()).await.unwrap();
// Второе редактирование
client.edit_message(ChatId::new(123), msg.id(), "Version 3".to_string()).await.unwrap();
// Третье редактирование
client.edit_message(ChatId::new(123), msg.id(), "Final version".to_string()).await.unwrap();
// Проверяем что все 3 редактирования записаны
assert_eq!(client.get_edited_messages().len(), 3);
assert_eq!(client.get_edited_messages()[0].new_text, "Version 2");
assert_eq!(client.get_edited_messages()[1].new_text, "Version 3");
assert_eq!(client.get_edited_messages()[2].new_text, "Final version");
// Проверяем что сообщение содержит последнюю версию
let messages = client.get_messages(123);
assert_eq!(messages.len(), 1);
assert_eq!(messages[0].text(), "Final version");
}
/// Test: Редактирование несуществующего сообщения (возвращает ошибку)
#[tokio::test]
async fn test_edit_nonexistent_message() {
let client = FakeTdClient::new();
// Пытаемся отредактировать несуществующее сообщение
let result = client.edit_message(ChatId::new(123), MessageId::new(999), "New text".to_string()).await;
// Должна вернуться ошибка
assert!(result.is_err());
assert_eq!(result.unwrap_err(), "Message not found");
// В списке сообщений ничего нет
let messages = client.get_messages(123);
assert_eq!(messages.len(), 0);
}
/// Test: Отмена редактирования (Esc) - тестируем что можно восстановить original
/// В данном случае проверяем что FakeTdClient сохраняет историю edits
#[tokio::test]
async fn test_edit_history_tracking() {
let client = FakeTdClient::new();
let msg = client.send_message(ChatId::new(123), "Original".to_string(), None, None).await.unwrap();
// Симулируем начало редактирования -> изменение -> отмена
// Отменять на уровне FakeTdClient нельзя, но можно проверить что original сохранён
// Сохраняем original
let messages_before = client.get_messages(123);
let original = messages_before[0].text().to_string();
// Редактируем
client.edit_message(ChatId::new(123), msg.id(), "Edited".to_string()).await.unwrap();
// Проверяем что изменилось
let messages_edited = client.get_messages(123);
assert_eq!(messages_edited[0].text(), "Edited");
// Можем "отменить" редактирование вернув original
client.edit_message(ChatId::new(123), msg.id(), original).await.unwrap();
// Проверяем что вернулось
let messages_restored = client.get_messages(123);
assert_eq!(messages_restored[0].text(), "Original");
// История показывает 2 редактирования
assert_eq!(client.get_edited_messages().len(), 2);
}
/// Test: Редактирование сразу после отправки (симуляция UpdateMessageSendSucceeded)
/// Проверяет что после send_message можно сразу edit_message с тем же ID
#[tokio::test]
async fn test_edit_immediately_after_send() {
let client = FakeTdClient::new();
// Отправляем сообщение
let sent_msg = client
.send_message(ChatId::new(123), "Just sent".to_string(), None, None)
.await
.unwrap();
// Сразу редактируем (не должно быть ошибки "Message not found")
let result = client
.edit_message(ChatId::new(123), sent_msg.id(), "Immediately edited".to_string())
.await;
// Редактирование должно пройти успешно
assert!(result.is_ok(), "Should be able to edit message immediately after sending");
// Проверяем что текст изменился
let messages = client.get_messages(123);
assert_eq!(messages.len(), 1);
assert_eq!(messages[0].text(), "Immediately edited");
// История редактирований содержит это изменение
assert_eq!(client.get_edited_messages().len(), 1);
assert_eq!(client.get_edited_messages()[0].message_id, sent_msg.id());
assert_eq!(client.get_edited_messages()[0].new_text, "Immediately edited");
}