use whispassist_lib::models::{AttendeeInfo, CalendarEvent, ImportedEvent}; use whispassist_lib::storage::{NewMeeting, SqliteStore, Store}; fn fresh_store_env() { std::env::set_var( "LOCALAPPDATA", std::env::temp_dir().join(format!("wa-linktest-{}", uuid::Uuid::new_v4())), ); } #[tokio::test] async fn attach_meeting_to_event_and_map_speaker_to_participant_round_trip() { fresh_store_env(); let store = SqliteStore::connect().await.unwrap(); // Import one event with one attendee (Alice). let imported = store .import_calendar_events(vec![ImportedEvent { event: CalendarEvent { id: uuid::Uuid::new_v4().to_string(), source: "pst".to_string(), subject: Some("Sprint planning".to_string()), organizer: Some("Jordan Lee".to_string()), starts_at: Some(1_782_896_400), ends_at: Some(1_782_900_000), description: None, raw_uid: Some("evt-1".to_string()), }, attendees: vec![AttendeeInfo { name: "Alice".to_string(), email: Some("alice@example.com".to_string()), role: Some("required".to_string()), }], }]) .await .unwrap(); assert_eq!(imported, 1); // list_calendar_events surfaces it. let events = store.list_calendar_events(None, None).await.unwrap(); assert_eq!(events.len(), 1); let event_id = events[0].id.clone(); assert_eq!(events[0].subject.as_deref(), Some("Sprint planning")); // get_calendar_event returns the attendee. let detail = store.get_calendar_event(&event_id).await.unwrap(); assert_eq!(detail.participants.len(), 1); assert_eq!(detail.participants[0].name, "Alice"); let alice_id = detail.participants[0].id.clone(); // attach_meeting_to_event errs on an unknown event id. let meeting_id = store .create_meeting(NewMeeting { title: "Test meeting".to_string(), calendar_event_id: None, }) .await .unwrap(); assert!(store .attach_meeting_to_event(&meeting_id, "no-such-event") .await .is_err()); // ... and succeeds + is reflected in get_meeting for a real one. store .attach_meeting_to_event(&meeting_id, &event_id) .await .unwrap(); let meeting = store.get_meeting(&meeting_id).await.unwrap(); assert_eq!( meeting.calendar_event_id.as_deref(), Some(event_id.as_str()) ); // map_speaker_to_participant sets both display_name and participant_id. store .map_speaker_to_participant(&meeting_id, "S1", &alice_id) .await .unwrap(); let meeting = store.get_meeting(&meeting_id).await.unwrap(); let s1 = meeting.speakers.iter().find(|s| s.label == "S1").unwrap(); assert_eq!(s1.display_name.as_deref(), Some("Alice")); assert_eq!(s1.participant_id.as_deref(), Some(alice_id.as_str())); // A later free-text rename must NOT silently unlink the participant. store .rename_speaker(&meeting_id, "S1", "Bob") .await .unwrap(); let meeting = store.get_meeting(&meeting_id).await.unwrap(); let s1 = meeting.speakers.iter().find(|s| s.label == "S1").unwrap(); assert_eq!(s1.display_name.as_deref(), Some("Bob")); assert_eq!( s1.participant_id.as_deref(), Some(alice_id.as_str()), "rename_speaker must preserve an existing participant_id link" ); }