using MeetingAssistant.Speakers; using MeetingAssistant.Transcription; namespace MeetingAssistant.Tests; public sealed class SpeakerSampleSpanSelectorTests { [Fact] public void SelectBestSameSpeakerSpanCombinesLinesAndCapsTheClip() { var span = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpan( [ Segment(0, 4), Segment(7, 13), Segment(20, 70) ], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60)); Assert.Equal(3, span.Count); Assert.Equal(TimeSpan.Zero, span[0].Start); Assert.Equal(TimeSpan.FromSeconds(60), span[^1].End); Assert.Equal(TimeSpan.FromSeconds(60), SpeakerSampleSpanSelector.SpanDuration(span)); } [Fact] public void SelectBestSameSpeakerSpanDoesNotCountProviderPausesAsSpeakerAudio() { var span = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpan( [ Segment(0, 4), Segment(20, 25) ], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60)); Assert.Empty(span); } [Fact] public void SelectBestSameSpeakerSpansReturnsDistinctMinimumLengthSamples() { var segments = Enumerable.Range(0, 6) .Select(index => new TranscriptionSegment( TimeSpan.FromSeconds(index * 10), TimeSpan.FromSeconds((index + 1) * 10), "Guest01", $"segment {index} has enough words")) .ToList(); var spans = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpans( segments, "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), maxSpans: 5); Assert.Equal(5, spans.Count); Assert.All(spans, span => Assert.True(SpeakerSampleSpanSelector.SpanDuration(span) >= TimeSpan.FromSeconds(10))); Assert.All( spans.Zip(spans.Skip(1)), pair => Assert.True(pair.First[^1].End <= pair.Second[0].Start)); } [Fact] public void SelectBestSameSpeakerSpansSkipsSegmentsThatOverlapACompletedSample() { var spans = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpans( [ Segment(0, 10), Segment(9, 19), Segment(20, 30) ], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), maxSpans: 5); Assert.Equal(2, spans.Count); Assert.Equal(TimeSpan.Zero, spans[0][0].Start); Assert.Equal(TimeSpan.FromSeconds(20), spans[1][0].Start); } [Fact] public void SelectBestSameSpeakerSpansCombinesConsecutiveLinesAcrossProviderPauses() { var spans = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpans( [ Segment(0, 4), Segment(7, 13) ], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), maxSpans: 5); var span = Assert.Single(spans); Assert.Equal(TimeSpan.Zero, span[0].Start); Assert.Equal(TimeSpan.FromSeconds(13), span[^1].End); } [Fact] public void SelectBestSameSpeakerSpansDoesNotCountProviderPausesAsSpeakerAudio() { var spans = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpans( [ Segment(0, 4), Segment(20, 25) ], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), maxSpans: 5); Assert.Empty(spans); } [Fact] public void SelectBestSameSpeakerSpansCapsFinalizedSamplesAtConfiguredMaximumDuration() { var spans = SpeakerSampleSpanSelector.SelectBestSameSpeakerSpans( [Segment(0, 70)], "Guest01", TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), maxSpans: 5); var span = Assert.Single(spans); Assert.Equal(TimeSpan.FromSeconds(60), SpeakerSampleSpanSelector.SpanDuration(span)); } private static TranscriptionSegment Segment(double start, double end) { return new TranscriptionSegment( TimeSpan.FromSeconds(start), TimeSpan.FromSeconds(end), "Guest01", "enough words for this segment"); } }