Files
meeting-assistant/MeetingAssistant.Tests/LaunchProfileOptionsProviderTests.cs
T
codex f86af983e8
PR and Push Build/Test / build-and-test (push) Successful in 12m37s
feat: add local Resemblyzer speaker recognition
2026-09-11 13:49:27 +02:00

232 lines
9.5 KiB
C#

using MeetingAssistant.LaunchProfiles;
using Microsoft.Extensions.Configuration;
namespace MeetingAssistant.Tests;
public sealed class LaunchProfileOptionsProviderTests
{
[Fact]
public void DefaultProfileUsesRootMeetingAssistantConfiguration()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:Recording:TranscriptionProvider"] = "azure-speech",
["MeetingAssistant:AzureSpeech:Language"] = "de-DE"
});
var profile = provider.GetRequiredProfile(null);
Assert.Equal("default", profile.Name);
Assert.Equal("Ctrl+Alt+M", profile.Options.Hotkey.Toggle);
Assert.Equal("azure-speech", profile.Options.Recording.TranscriptionProvider);
Assert.Equal("de-DE", profile.Options.AzureSpeech.Language);
}
[Fact]
public void NamedProfileMergesOverrideOntoDefaultConfiguration()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:Recording:TranscriptionProvider"] = "azure-speech",
["MeetingAssistant:AzureSpeech:Region"] = "germanywestcentral",
["MeetingAssistant:AzureSpeech:Language"] = "de-DE",
["MeetingAssistant:AzureSpeech:AutoDetectLanguages:0"] = "de-DE",
["MeetingAssistant:LaunchProfiles:english:Hotkey:Toggle"] = "Ctrl+Alt+L",
["MeetingAssistant:LaunchProfiles:english:AzureSpeech:Language"] = "en-US",
["MeetingAssistant:LaunchProfiles:english:AzureSpeech:AutoDetectLanguages:0"] = "en-US"
});
var profile = provider.GetRequiredProfile("english");
Assert.Equal("english", profile.Name);
Assert.Equal("Ctrl+Alt+L", profile.Options.Hotkey.Toggle);
Assert.Equal("azure-speech", profile.Options.Recording.TranscriptionProvider);
Assert.Equal("germanywestcentral", profile.Options.AzureSpeech.Region);
Assert.Equal("en-US", profile.Options.AzureSpeech.Language);
Assert.Equal(["en-US"], profile.Options.AzureSpeech.AutoDetectLanguages);
}
[Fact]
public void CheckedInEnglishProfileUsesLanguageHotkey()
{
var provider = CreateProviderFromAppsettings();
var profile = provider.GetRequiredProfile("english");
Assert.Equal("Ctrl+Alt+L", profile.Options.Hotkey.Toggle);
}
[Fact]
public void CheckedInConfigurationKeepsResemblyzerOptInWithDocumentedDefaults()
{
var profile = CreateProviderFromAppsettings().GetRequiredProfile(null);
Assert.False(profile.Options.SpeakerIdentification.Resemblyzer.Enabled);
Assert.Equal(5, profile.Options.SpeakerIdentification.Resemblyzer.RequiredVectorsPerSpeaker);
Assert.Equal(1000, profile.Options.SpeakerIdentification.Resemblyzer.MaxVectorsPerIdentity);
Assert.Equal(20, profile.Options.SpeakerIdentification.Resemblyzer.OutlierPruningMinimumVectors);
Assert.Equal(0.75, profile.Options.SpeakerIdentification.Resemblyzer.OutlierPruningNeighborSimilarity);
Assert.Equal(3, profile.Options.SpeakerIdentification.Resemblyzer.OutlierPruningMinimumNeighbors);
Assert.Equal(0.60, profile.Options.SpeakerIdentification.Resemblyzer.OutlierPruningMinimumClusterRatio);
}
[Fact]
public void InvalidResemblyzerOutlierPruningSettingsAreRejected()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:SpeakerIdentification:Resemblyzer:OutlierPruningMinimumClusterRatio"] = "1.1"
});
var exception = Assert.Throws<InvalidOperationException>(
() => provider.GetRequiredProfile(null));
Assert.Contains("OutlierPruningMinimumClusterRatio", exception.Message);
}
[Fact]
public void NonFiniteResemblyzerSimilaritySettingsAreRejected()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:SpeakerIdentification:Resemblyzer:MinimumIdentitySimilarity"] = "NaN"
});
var exception = Assert.Throws<InvalidOperationException>(
() => provider.GetRequiredProfile(null));
Assert.Contains("MinimumIdentitySimilarity", exception.Message);
}
[Fact]
public void ContradictorySpeakerSampleDurationsAreRejected()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:SpeakerIdentification:MinimumSampleSpeechDuration"] = "00:01:01",
["MeetingAssistant:SpeakerIdentification:MaximumSampleDuration"] = "00:01:00"
});
var exception = Assert.Throws<InvalidOperationException>(
() => provider.GetRequiredProfile(null));
Assert.Contains("MinimumSampleSpeechDuration", exception.Message);
Assert.Contains("MaximumSampleDuration", exception.Message);
}
[Fact]
public void DuplicateProfileHotkeysAreRejected()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:LaunchProfiles:english:Hotkey:Toggle"] = "Ctrl+Alt+M"
});
var exception = Assert.Throws<InvalidOperationException>(() => provider.GetHotkeys());
Assert.Contains("Ctrl+Alt+M", exception.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void ScreenshotHotkeysAreRegisteredForDefaultAndExplicitProfileOverrides()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:Hotkey:Abort"] = "Ctrl+Alt+Z",
["MeetingAssistant:Screenshots:Hotkey"] = "Ctrl+Alt+S",
["MeetingAssistant:LaunchProfiles:english:Hotkey:Toggle"] = "Ctrl+Alt+L",
["MeetingAssistant:LaunchProfiles:english:Hotkey:Abort"] = "Ctrl+Alt+Shift+D",
["MeetingAssistant:LaunchProfiles:english:Screenshots:Hotkey"] = "Ctrl+Alt+Shift+S"
});
var hotkeys = provider.GetHotkeys();
Assert.Contains(hotkeys, hotkey =>
hotkey.ProfileName == "default" &&
hotkey.Hotkey == "Ctrl+Alt+S" &&
hotkey.Action == LaunchProfileHotkeyAction.CaptureScreenshot);
Assert.Contains(hotkeys, hotkey =>
hotkey.ProfileName == "english" &&
hotkey.Hotkey == "Ctrl+Alt+Shift+S" &&
hotkey.Action == LaunchProfileHotkeyAction.CaptureScreenshot);
Assert.Contains(hotkeys, hotkey =>
hotkey.ProfileName == "default" &&
hotkey.Hotkey == "Ctrl+Alt+Z" &&
hotkey.Action == LaunchProfileHotkeyAction.AbortRecording);
Assert.Contains(hotkeys, hotkey =>
hotkey.ProfileName == "english" &&
hotkey.Hotkey == "Ctrl+Alt+Shift+D" &&
hotkey.Action == LaunchProfileHotkeyAction.AbortRecording);
}
[Fact]
public void NamedProfilesDoNotInheritDefaultHotkeysForRegistration()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:Hotkey:Abort"] = "Ctrl+Alt+Z",
["MeetingAssistant:Screenshots:Hotkey"] = "Ctrl+Alt+S",
["MeetingAssistant:LaunchProfiles:english:AzureSpeech:Language"] = "en-US"
});
var hotkeys = provider.GetHotkeys();
Assert.Equal(3, hotkeys.Count);
Assert.DoesNotContain(hotkeys, hotkey => hotkey.ProfileName == "english");
}
[Fact]
public void GetProfilesReturnsDefaultAndConfiguredNamedProfiles()
{
var provider = CreateProvider(new Dictionary<string, string?>
{
["MeetingAssistant:Hotkey:Toggle"] = "Ctrl+Alt+M",
["MeetingAssistant:Recording:TranscriptionProvider"] = "azure-speech",
["MeetingAssistant:LaunchProfiles:english:AzureSpeech:Language"] = "en-US"
});
var profiles = provider.GetProfiles();
Assert.Equal(["default", "english"], profiles.Select(profile => profile.Name));
Assert.Equal("azure-speech", profiles.Single(profile => profile.Name == "english").Options.Recording.TranscriptionProvider);
Assert.Equal("en-US", profiles.Single(profile => profile.Name == "english").Options.AzureSpeech.Language);
}
private static ConfigurationLaunchProfileOptionsProvider CreateProvider(
IReadOnlyDictionary<string, string?> values)
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(values)
.Build();
return new ConfigurationLaunchProfileOptionsProvider(configuration);
}
private static ConfigurationLaunchProfileOptionsProvider CreateProviderFromAppsettings()
{
var root = FindRepositoryRoot();
var configuration = new ConfigurationBuilder()
.AddJsonFile(Path.Combine(root, "MeetingAssistant", "appsettings.json"), optional: false)
.Build();
return new ConfigurationLaunchProfileOptionsProvider(configuration);
}
private static string FindRepositoryRoot()
{
for (var directory = new DirectoryInfo(AppContext.BaseDirectory);
directory is not null;
directory = directory.Parent)
{
if (File.Exists(Path.Combine(directory.FullName, "MeetingAssistant.slnx")))
{
return directory.FullName;
}
}
throw new InvalidOperationException("Could not locate MeetingAssistant.slnx from the test output folder.");
}
}