use crate::{ chat_database::ChatDatabase, models::{ conversation::{Conversation, ConversationBuilder}, participant::Participant, message::Message, } }; // Helper function to compare participants ignoring database IDs fn participants_equal_ignoring_id(a: &Participant, b: &Participant) -> bool { match (a, b) { (Participant::Me, Participant::Me) => true, (Participant::Remote { display_name: name_a, .. }, Participant::Remote { display_name: name_b, .. }) => name_a == name_b, _ => false } } fn participants_vec_equal_ignoring_id(a: &[Participant], b: &[Participant]) -> bool { if a.len() != b.len() { return false; } a.iter().zip(b.iter()).all(|(a, b)| participants_equal_ignoring_id(a, b)) } #[test] fn test_database_init() { let _ = ChatDatabase::new_in_memory().unwrap(); } #[test] fn test_add_conversation() { let mut db = ChatDatabase::new_in_memory().unwrap(); let guid = "test"; let test_conversation = Conversation::builder() .guid(guid) .unread_count(2) .display_name("Test Conversation") .build(); db.insert_conversation(test_conversation.clone()).unwrap(); // Try to fetch with id now let conversation = db.get_conversation_by_guid(guid).unwrap().unwrap(); assert_eq!(conversation.guid, "test"); // Modify the conversation and update it let modified_conversation = test_conversation.into_builder() .display_name("Modified Conversation") .build(); db.insert_conversation(modified_conversation.clone()).unwrap(); // Make sure we still only have one conversation. let all_conversations = db.all_conversations().unwrap(); assert_eq!(all_conversations.len(), 1); // And make sure the display name was updated let conversation = db.get_conversation_by_guid(guid).unwrap().unwrap(); assert_eq!(conversation.display_name.unwrap(), "Modified Conversation"); } #[test] fn test_conversation_participants() { let mut db = ChatDatabase::new_in_memory().unwrap(); let participants: Vec = vec!["one".into(), "two".into()]; let guid = uuid::Uuid::new_v4().to_string(); let conversation = ConversationBuilder::new() .guid(&guid) .display_name("Test") .participants(participants.clone()) .build(); db.insert_conversation(conversation).unwrap(); let read_conversation = db.get_conversation_by_guid(&guid).unwrap().unwrap(); let read_participants = read_conversation.participants; assert!(participants_vec_equal_ignoring_id(&participants, &read_participants)); // Try making another conversation with the same participants let conversation = ConversationBuilder::new() .display_name("A Different Test") .participants(participants.clone()) .build(); db.insert_conversation(conversation).unwrap(); let read_conversation = db.get_conversation_by_guid(&guid).unwrap().unwrap(); let read_participants: Vec = read_conversation.participants; assert!(participants_vec_equal_ignoring_id(&participants, &read_participants)); } #[test] fn test_all_conversations_with_participants() { let mut db = ChatDatabase::new_in_memory().unwrap(); // Create two conversations with different participants let participants1: Vec = vec!["one".into(), "two".into()]; let participants2: Vec = vec!["three".into(), "four".into()]; let guid1 = uuid::Uuid::new_v4().to_string(); let conversation1 = ConversationBuilder::new() .guid(&guid1) .display_name("Test 1") .participants(participants1.clone()) .build(); let guid2 = uuid::Uuid::new_v4().to_string(); let conversation2 = ConversationBuilder::new() .guid(&guid2) .display_name("Test 2") .participants(participants2.clone()) .build(); // Insert both conversations db.insert_conversation(conversation1).unwrap(); db.insert_conversation(conversation2).unwrap(); // Get all conversations and verify the results let all_conversations = db.all_conversations().unwrap(); assert_eq!(all_conversations.len(), 2); // Find and verify each conversation's participants let conv1 = all_conversations.iter().find(|c| c.guid == guid1).unwrap(); let conv2 = all_conversations.iter().find(|c| c.guid == guid2).unwrap(); assert!(participants_vec_equal_ignoring_id(&conv1.participants, &participants1)); assert!(participants_vec_equal_ignoring_id(&conv2.participants, &participants2)); } #[test] fn test_messages() { let mut db = ChatDatabase::new_in_memory().unwrap(); // First create a conversation with participants let participants = vec!["Alice".into(), "Bob".into()]; let conversation = ConversationBuilder::new() .display_name("Test Chat") .participants(participants) .build(); let conversation_id = conversation.guid.clone(); db.insert_conversation(conversation).unwrap(); // Create and insert a message from Me let message1 = Message::builder() .text("Hello everyone!".to_string()) .build(); // Create and insert a message from a remote participant let message2 = Message::builder() .text("Hi there!".to_string()) .sender("Alice".into()) .build(); // Insert both messages db.insert_message(&conversation_id, message1.clone()).unwrap(); db.insert_message(&conversation_id, message2.clone()).unwrap(); // Retrieve messages let messages = db.get_messages_for_conversation(&conversation_id).unwrap(); assert_eq!(messages.len(), 2); // Verify first message (from Me) let retrieved_message1 = messages.iter().find(|m| m.id == message1.id).unwrap(); assert_eq!(retrieved_message1.text, "Hello everyone!"); assert!(matches!(retrieved_message1.sender, Participant::Me)); // Verify second message (from Alice) let retrieved_message2 = messages.iter().find(|m| m.id == message2.id).unwrap(); assert_eq!(retrieved_message2.text, "Hi there!"); if let Participant::Remote { display_name, .. } = &retrieved_message2.sender { assert_eq!(display_name, "Alice"); } else { panic!("Expected Remote participant. Got: {:?}", retrieved_message2.sender); } } #[test] fn test_message_ordering() { let mut db = ChatDatabase::new_in_memory().unwrap(); // Create a conversation let conversation = ConversationBuilder::new() .display_name("Test Chat") .build(); let conversation_id = conversation.guid.clone(); db.insert_conversation(conversation).unwrap(); // Create messages with specific timestamps let now = chrono::Utc::now().naive_utc(); let message1 = Message::builder() .text("First message".to_string()) .date(now) .build(); let message2 = Message::builder() .text("Second message".to_string()) .date(now + chrono::Duration::minutes(1)) .build(); let message3 = Message::builder() .text("Third message".to_string()) .date(now + chrono::Duration::minutes(2)) .build(); // Insert messages db.insert_message(&conversation_id, message1).unwrap(); db.insert_message(&conversation_id, message2).unwrap(); db.insert_message(&conversation_id, message3).unwrap(); // Retrieve messages and verify order let messages = db.get_messages_for_conversation(&conversation_id).unwrap(); assert_eq!(messages.len(), 3); // Messages should be ordered by date for i in 1..messages.len() { assert!(messages[i].date > messages[i-1].date); } }