using MeetingAssistant.MeetingNotes; namespace MeetingAssistant.Tests; public sealed class OutlookMeetingCandidateSelectorTests { [Fact] public void SelectIgnoresOverlappingMeetingThatEndsInLessThanFiveMinutes() { var now = new DateTime(2026, 5, 20, 10, 0, 0); var selected = OutlookMeetingCandidateSelector.Select( [ new Candidate(now.AddMinutes(-25), now.AddMinutes(4)) ], now, candidate => candidate.Start, candidate => candidate.End); Assert.Null(selected); } [Fact] public void SelectPrefersSingleGoodOverlappingMeetingOverUpcomingMeeting() { var now = new DateTime(2026, 5, 20, 10, 0, 0); var overlap = new Candidate(now.AddMinutes(-10), now.AddMinutes(30)); var upcoming = new Candidate(now.AddMinutes(3), now.AddMinutes(33)); var selected = OutlookMeetingCandidateSelector.Select( [upcoming, overlap], now, candidate => candidate.Start, candidate => candidate.End); Assert.Same(overlap, selected); } [Fact] public void SelectUsesSingleTeamsMeetingStartingWithinFiveMinutesWhenNoGoodOverlapExists() { var now = new DateTime(2026, 5, 20, 10, 0, 0); var endingOverlap = new Candidate(now.AddMinutes(-25), now.AddMinutes(2)); var upcoming = new Candidate(now.AddMinutes(5), now.AddMinutes(35)); var selected = OutlookMeetingCandidateSelector.Select( [endingOverlap, upcoming], now, candidate => candidate.Start, candidate => candidate.End); Assert.Same(upcoming, selected); } [Fact] public void SelectRejectsAmbiguousUpcomingMeetings() { var now = new DateTime(2026, 5, 20, 10, 0, 0); var selected = OutlookMeetingCandidateSelector.Select( [ new Candidate(now.AddMinutes(2), now.AddMinutes(32)), new Candidate(now.AddMinutes(4), now.AddMinutes(34)) ], now, candidate => candidate.Start, candidate => candidate.End); Assert.Null(selected); } private sealed record Candidate(DateTime Start, DateTime End); }