//! Integration tests for SqliteEmailRepository. mod common; use chrono::{Duration, Utc}; use goingson_core::{EmailRepository, NewEmail}; use goingson_db_sqlite::SqliteEmailRepository; #[tokio::test] async fn test_create_and_get_email() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: "Test Subject".to_string(), body: "Test email body content".to_string(), is_read: false, received_at: Some(Utc::now()), }; let created = repo.create(user_id, new_email).await.expect("Failed to create email"); assert_eq!(created.subject, "Test Subject"); assert_eq!(created.from, "sender@example.com"); assert!(!created.is_read); assert!(!created.is_archived); let fetched = repo.get_by_id(created.id, user_id).await.expect("Failed to get email"); assert!(fetched.is_some()); assert_eq!(fetched.unwrap().id, created.id); } #[tokio::test] async fn test_email_read_unread() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: "Read/Unread test".to_string(), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now()), }; let email = repo.create(user_id, new_email).await.expect("Failed to create"); assert!(!email.is_read); // Mark as read let marked_read = repo.mark_read(email.id, user_id).await.expect("Failed to mark read"); assert!(marked_read); // Verify it's read let fetched = repo.get_by_id(email.id, user_id).await.expect("Failed to get").unwrap(); assert!(fetched.is_read); // Mark as unread let marked_unread = repo.mark_unread(email.id, user_id).await.expect("Failed to mark unread"); assert!(marked_unread); // Verify it's unread let fetched = repo.get_by_id(email.id, user_id).await.expect("Failed to get").unwrap(); assert!(!fetched.is_read); } #[tokio::test] async fn test_email_archive() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: "Archive test".to_string(), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now()), }; let email = repo.create(user_id, new_email).await.expect("Failed to create"); assert!(!email.is_archived); // Archive let archived = repo.archive(email.id, user_id).await.expect("Failed to archive"); assert!(archived); // Verify it's archived let fetched = repo.get_by_id(email.id, user_id).await.expect("Failed to get").unwrap(); assert!(fetched.is_archived); // Should not appear in non-archived list let emails = repo.list_all(user_id, false).await.expect("Failed to list"); assert!(emails.iter().all(|e| e.id != email.id)); // Should appear in list with archived included let all_emails = repo.list_all(user_id, true).await.expect("Failed to list all"); assert!(all_emails.iter().any(|e| e.id == email.id)); // Unarchive let unarchived = repo.unarchive(email.id, user_id).await.expect("Failed to unarchive"); assert!(unarchived); // Verify it's unarchived let fetched = repo.get_by_id(email.id, user_id).await.expect("Failed to get").unwrap(); assert!(!fetched.is_archived); } #[tokio::test] async fn test_email_snooze() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: "Snooze test".to_string(), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now()), }; let email = repo.create(user_id, new_email).await.expect("Failed to create"); let until = Utc::now() + Duration::hours(4); let snoozed = repo.snooze(email.id, user_id, until).await.expect("Failed to snooze"); assert!(snoozed.is_some()); assert!(snoozed.as_ref().unwrap().snoozed_until.is_some()); // Should appear in snoozed list let snoozed_emails = repo.list_snoozed(user_id).await.expect("Failed to list snoozed"); assert_eq!(snoozed_emails.len(), 1); // Unsnooze let unsnoozed = repo.unsnooze(email.id, user_id).await.expect("Failed to unsnooze"); assert!(unsnoozed.is_some()); assert!(unsnoozed.unwrap().snoozed_until.is_none()); } #[tokio::test] async fn test_email_waiting_for_response() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "me@example.com".to_string(), to_address: "them@example.com".to_string(), subject: "Waiting test".to_string(), body: "Test body".to_string(), is_read: true, received_at: Some(Utc::now()), }; let email = repo.create(user_id, new_email).await.expect("Failed to create"); let expected = Utc::now() + Duration::days(2); let waiting = repo.mark_waiting(email.id, user_id, Some(expected)).await.expect("Failed to mark waiting"); assert!(waiting.is_some()); assert!(waiting.as_ref().unwrap().waiting_for_response); // Should appear in waiting list let waiting_emails = repo.list_waiting(user_id).await.expect("Failed to list waiting"); assert_eq!(waiting_emails.len(), 1); // Clear waiting let cleared = repo.clear_waiting(email.id, user_id).await.expect("Failed to clear"); assert!(cleared.is_some()); assert!(!cleared.unwrap().waiting_for_response); } #[tokio::test] async fn test_delete_email() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: "Delete test".to_string(), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now()), }; let email = repo.create(user_id, new_email).await.expect("Failed to create"); let deleted = repo.delete(email.id, user_id).await.expect("Failed to delete"); assert!(deleted); let fetched = repo.get_by_id(email.id, user_id).await.expect("Failed to get"); assert!(fetched.is_none()); } #[tokio::test] async fn test_email_ordering_by_received_at() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); // Create emails at different times for i in 0..3 { let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: format!("Email {}", i), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now() - Duration::hours(i as i64)), }; repo.create(user_id, new_email).await.expect("Failed to create"); } let emails = repo.list_all(user_id, false).await.expect("Failed to list"); assert_eq!(emails.len(), 3); // Should be ordered by received_at descending (newest first) assert!(emails[0].received_at >= emails[1].received_at); assert!(emails[1].received_at >= emails[2].received_at); } #[tokio::test] async fn test_count_unread() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); // Create 3 emails, mark 1 as read for i in 0..3 { let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: format!("Email {}", i), body: "Test body".to_string(), is_read: i == 0, // First one is read received_at: Some(Utc::now()), }; repo.create(user_id, new_email).await.expect("Failed to create"); } let count = repo.count_unread(user_id).await.expect("Failed to count"); assert_eq!(count, 2); } #[tokio::test] async fn test_mark_all_read() { let pool = common::setup_test_db().await; let user_id = common::create_test_user(&pool).await; let repo = SqliteEmailRepository::new(pool); // Create 3 unread emails for i in 0..3 { let new_email = NewEmail { project_id: None, from_address: "sender@example.com".to_string(), to_address: "recipient@example.com".to_string(), subject: format!("Email {}", i), body: "Test body".to_string(), is_read: false, received_at: Some(Utc::now()), }; repo.create(user_id, new_email).await.expect("Failed to create"); } let marked = repo.mark_all_read(user_id).await.expect("Failed to mark all read"); assert_eq!(marked, 3); let count = repo.count_unread(user_id).await.expect("Failed to count"); assert_eq!(count, 0); }