using LehrerApp.Core.Models; using LehrerApp.Desktop.Services; using Xunit; namespace LehrerApp.Desktop.Tests; public sealed class AnnualPlanSyncServiceTests { private static string Calendar(params string[] events) => "BEGIN:VCALENDAR\nVERSION:2.0\n" + string.Join("", events) + "END:VCALENDAR\n"; private static string Event(string uid, string title, string date = "20260823") => $"BEGIN:VEVENT\nUID:{uid}\nDTSTART;VALUE=DATE:{date}\nSUMMARY:{title}\nEND:VEVENT\n"; private static AnnualPlanSyncService Build(FakeAnnualPlanEvents events) => new(new HttpClient(), TestSupport.BuildAnnualPlanSettingsService(), events); [Fact] public void ProcessIcsText_LegtAn_AktualisiertIdempotent_UndEntferntVerschwundeneTermine() { var events = new FakeAnnualPlanEvents(); using var service = Build(events); var first = service.ProcessIcsText(Calendar(Event("1", "Konferenz"), Event("2", "Messe"))); var originalId = events.GetByExternalId("1")!.Id; var unchanged = service.ProcessIcsText(Calendar(Event("1", "Konferenz"), Event("2", "Messe"))); var changed = service.ProcessIcsText(Calendar(Event("1", "Konferenz verschoben", "20260824"))); Assert.Equal((2, 0, 0), (first.Added, first.Updated, first.Deleted)); Assert.Equal(0, unchanged.ChangeCount); Assert.Equal((0, 1, 1), (changed.Added, changed.Updated, changed.Deleted)); Assert.Equal(originalId, events.GetByExternalId("1")!.Id); Assert.Null(events.GetByExternalId("2")); } [Fact] public void ProcessIcsText_DefekterTeilimport_VeraendertBestehendenBestandNicht() { var events = new FakeAnnualPlanEvents(); events.Add(new AnnualPlanEvent { ExternalId = "bestand", Title = "Bestehend", StartDate = new DateOnly(2026, 8, 23), EndDate = new DateOnly(2026, 8, 23), IsAllDay = true, }); using var service = Build(events); var broken = Calendar(Event("neu", "Neu"), "BEGIN:VEVENT\nUID:defekt\nSUMMARY:Ohne Datum\nEND:VEVENT\n"); Assert.Throws(() => service.ProcessIcsText(broken)); var remaining = Assert.Single(events.GetAll()); Assert.Equal("bestand", remaining.ExternalId); } [Fact] public void Clear_EntferntDenLokalenFeedCache() { var events = new FakeAnnualPlanEvents(); events.Add(new AnnualPlanEvent { ExternalId = "1", StartDate = new DateOnly(2026, 8, 23), EndDate = new DateOnly(2026, 8, 23), IsAllDay = true, }); using var service = Build(events); var notified = false; service.DataChanged += () => notified = true; service.Clear(); Assert.Empty(events.GetAll()); Assert.True(notified); } }