Verify PST import dedups events and participants by source and raw_uid
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
use whispassist_lib::models::{AttendeeInfo, CalendarEvent, ImportedEvent};
|
||||
use whispassist_lib::storage::{SqliteStore, Store};
|
||||
|
||||
fn event(uid: &str, subject: &str) -> ImportedEvent {
|
||||
ImportedEvent {
|
||||
event: CalendarEvent {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
source: "pst".to_string(),
|
||||
subject: Some(subject.to_string()),
|
||||
organizer: Some("Jordan Lee".to_string()),
|
||||
starts_at: Some(1_782_896_400),
|
||||
ends_at: Some(1_782_900_000),
|
||||
description: Some("Agenda".to_string()),
|
||||
raw_uid: Some(uid.to_string()),
|
||||
},
|
||||
attendees: vec![
|
||||
AttendeeInfo {
|
||||
name: "Alex Kim".to_string(),
|
||||
email: Some("alex@example.com".to_string()),
|
||||
role: Some("required".to_string()),
|
||||
},
|
||||
AttendeeInfo {
|
||||
name: "No Email Person".to_string(),
|
||||
email: None,
|
||||
role: None,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn import_calendar_events_dedups_by_source_and_raw_uid() {
|
||||
std::env::set_var(
|
||||
"LOCALAPPDATA",
|
||||
std::env::temp_dir().join(format!("wa-caltest-{}", uuid::Uuid::new_v4())),
|
||||
);
|
||||
let store = SqliteStore::connect().await.unwrap();
|
||||
|
||||
let n1 = store
|
||||
.import_calendar_events(vec![event("uid-1", "Sprint planning")])
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(n1, 1);
|
||||
|
||||
let n2 = store
|
||||
.import_calendar_events(vec![
|
||||
event("uid-1", "Sprint planning (rescheduled)"),
|
||||
event("uid-2", "Retro"),
|
||||
])
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(n2, 2);
|
||||
|
||||
let n3 = store
|
||||
.import_calendar_events(vec![event("uid-1", "Sprint planning (rescheduled)")])
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(n3, 1);
|
||||
|
||||
// Verify actual row-level dedup, not just the returned counts.
|
||||
let pool = sqlx::sqlite::SqlitePool::connect(&format!(
|
||||
"sqlite:{}",
|
||||
whispassist_lib::paths::db_path().display()
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event_count: i64 =
|
||||
sqlx::query_scalar("SELECT COUNT(*) FROM calendar_events WHERE raw_uid = 'uid-1'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
event_count, 1,
|
||||
"re-importing uid-1 must update in place, not duplicate"
|
||||
);
|
||||
|
||||
let subject: String =
|
||||
sqlx::query_scalar("SELECT subject FROM calendar_events WHERE raw_uid = 'uid-1'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(subject, "Sprint planning (rescheduled)");
|
||||
|
||||
let total_events: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM calendar_events")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(total_events, 2, "uid-1 and uid-2 only");
|
||||
|
||||
let no_email_rows: i64 =
|
||||
sqlx::query_scalar("SELECT COUNT(*) FROM participants WHERE name = 'No Email Person'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
no_email_rows, 1,
|
||||
"repeat no-email attendee must not duplicate the participant row"
|
||||
);
|
||||
|
||||
let alex_rows: i64 =
|
||||
sqlx::query_scalar("SELECT COUNT(*) FROM participants WHERE email = 'alex@example.com'")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(alex_rows, 1);
|
||||
|
||||
let links: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM calendar_event_participants")
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(links, 4, "2 events x 2 attendees each");
|
||||
}
|
||||
Reference in New Issue
Block a user