feat: attach calendar metadata to active meetings
PR and Push Build/Test / build-and-test (push) Successful in 15m2s

This commit is contained in:
2026-08-05 11:58:25 +02:00
parent aa42e8edda
commit 1a341f1eaa
11 changed files with 713 additions and 48 deletions
@@ -123,6 +123,49 @@ public sealed class CalendarRecordingPromptSchedulerTests
Assert.Equal(["stop", "start"], harness.Recorder.Commands);
}
[Fact]
public async Task ActiveRecordingPromptAttachesTheSelectedAppointmentMetadataWithoutRestarting()
{
var harness = CreateHarness(isRecording: true, autoAcceptPrompts: false);
var firstMetadata = new MeetingMetadata(
"First planning",
["Ada"],
"First agenda",
DateTimeOffset.Parse("2026-06-03T10:30:00+00:00"));
var secondMetadata = new MeetingMetadata(
"Second planning",
["Grace"],
"Second agenda",
DateTimeOffset.Parse("2026-06-03T10:30:00+00:00"));
var firstMeeting = CreateMeeting(
harness.Clock,
id: "teams-first",
subject: "First planning",
metadata: firstMetadata);
var secondMeeting = CreateMeeting(
harness.Clock,
id: "teams-second",
subject: "Second planning",
metadata: secondMetadata);
harness.Provider.Meetings = [firstMeeting, secondMeeting];
await harness.Scheduler.SyncOnceAsync(CancellationToken.None);
harness.Clock.Now = firstMeeting.Start;
await harness.Scheduler.CheckDuePromptsAsync(CancellationToken.None);
await harness.PromptService.RespondAsync(
secondMeeting,
MeetingStartPromptResponse.AttachMetadataToCurrentMeeting);
Assert.All(
harness.PromptService.PromptRequests,
request => Assert.True(request.CanAttachToCurrentMeeting));
Assert.Equal(["attach-metadata"], harness.Recorder.Commands);
Assert.Same(secondMetadata, harness.Recorder.AttachedMetadata.Single());
Assert.Equal(0, harness.Recorder.StopCount);
Assert.Equal(0, harness.Recorder.StartCount);
Assert.True(harness.Recorder.CurrentStatus.IsRecording);
}
[Fact]
public async Task CanceledCachedMeetingDoesNotPromptRecording()
{
@@ -302,14 +345,17 @@ public sealed class CalendarRecordingPromptSchedulerTests
this.autoAccept = autoAccept;
}
public List<CalendarMeeting> PromptedMeetings { get; } = [];
public List<MeetingStartPromptRequest> PromptRequests { get; } = [];
public IReadOnlyList<CalendarMeeting> PromptedMeetings =>
PromptRequests.Select(request => request.Meeting).ToList();
public async Task ShowPromptAsync(
MeetingStartPromptRequest request,
Func<MeetingStartPromptResponse, CancellationToken, Task> handleResponseAsync,
CancellationToken cancellationToken)
{
PromptedMeetings.Add(request.Meeting);
PromptRequests.Add(request);
pendingPrompts.Add(new PendingPrompt(request.Meeting, handleResponseAsync));
if (autoAccept)
{
@@ -349,6 +395,8 @@ public sealed class CalendarRecordingPromptSchedulerTests
public List<MeetingMetadata?> StartMetadata { get; } = [];
public List<MeetingMetadata> AttachedMetadata { get; } = [];
public Task<RecordingStatus> StartAsync(CancellationToken cancellationToken)
{
return StartRecordingAsync(null);
@@ -380,6 +428,15 @@ public sealed class CalendarRecordingPromptSchedulerTests
return Task.FromResult(CurrentStatus);
}
public Task<RecordingStatus> AttachMetadataToCurrentMeetingAsync(
MeetingMetadata metadata,
CancellationToken cancellationToken)
{
Commands.Add("attach-metadata");
AttachedMetadata.Add(metadata);
return Task.FromResult(CurrentStatus);
}
private static RecordingStatus Status(bool isRecording)
{
return new RecordingStatus(