using System.Text.Json.Nodes; using LehrerApp.Desktop.Services.Mcp; using Xunit; namespace LehrerApp.Desktop.Tests; public sealed class McpClientRegistrationServiceTests : IDisposable { private readonly string _directory = Path.Combine(Path.GetTempPath(), $"lehrerapp-mcpreg-tests-{Guid.NewGuid():N}"); public McpClientRegistrationServiceTests() => Directory.CreateDirectory(_directory); public void Dispose() { if (Directory.Exists(_directory)) Directory.Delete(_directory, true); } private string ConfigPath => Path.Combine(_directory, "claude_desktop_config.json"); private string BuildFakeBridge() { var bridgePath = Path.Combine(_directory, "LehrerApp.McpBridge.exe"); File.WriteAllText(bridgePath, "fake"); return bridgePath; } [Fact] public void Register_OhneBridgeDatei_LiefertFehlerUndSchreibtNichts() { var service = new McpClientRegistrationService(ConfigPath, Path.Combine(_directory, "fehlt.exe")); var result = service.Register(); Assert.False(result.Success); Assert.False(File.Exists(ConfigPath)); } [Fact] public void Register_OhneBestehendeKonfiguration_LegtDateiMitEintragAn() { var bridgePath = BuildFakeBridge(); var service = new McpClientRegistrationService(ConfigPath, bridgePath); var result = service.Register(); Assert.True(result.Success); Assert.True(service.IsRegistered()); var root = JsonNode.Parse(File.ReadAllText(ConfigPath))!; Assert.Equal(bridgePath, root["mcpServers"]!["lehrerapp"]!["command"]!.GetValue()); } [Fact] public void Register_BestehendeKonfigurationMitAnderenServern_BleibtErhalten() { File.WriteAllText(ConfigPath, """{"mcpServers":{"andererServer":{"command":"foo"}},"globalShortcut":"Ctrl+X"}"""); var bridgePath = BuildFakeBridge(); var service = new McpClientRegistrationService(ConfigPath, bridgePath); var result = service.Register(); Assert.True(result.Success); var root = JsonNode.Parse(File.ReadAllText(ConfigPath))!; Assert.Equal("foo", root["mcpServers"]!["andererServer"]!["command"]!.GetValue()); Assert.Equal("Ctrl+X", root["globalShortcut"]!.GetValue()); Assert.Equal(bridgePath, root["mcpServers"]!["lehrerapp"]!["command"]!.GetValue()); } [Fact] public void Register_KaputteBestehendeKonfiguration_WirdNichtUeberschrieben() { File.WriteAllText(ConfigPath, "{ das ist kein json"); var bridgePath = BuildFakeBridge(); var service = new McpClientRegistrationService(ConfigPath, bridgePath); var result = service.Register(); Assert.False(result.Success); Assert.Equal("{ das ist kein json", File.ReadAllText(ConfigPath)); } [Fact] public void Unregister_EntferntNurEigenenEintrag() { File.WriteAllText(ConfigPath, """{"mcpServers":{"andererServer":{"command":"foo"},"lehrerapp":{"command":"bar"}}}"""); var service = new McpClientRegistrationService(ConfigPath, BuildFakeBridge()); var result = service.Unregister(); Assert.True(result.Success); Assert.False(service.IsRegistered()); Assert.Contains("andererServer", File.ReadAllText(ConfigPath)); } [Fact] public void IsRegistered_OhneDatei_IstFalse() { var service = new McpClientRegistrationService(ConfigPath, BuildFakeBridge()); Assert.False(service.IsRegistered()); } }