using LehrerApp.Core.Models; using LehrerApp.Desktop.Services; using Xunit; namespace LehrerApp.Desktop.Tests; public sealed class UntisHubServiceTests { private static readonly DateTime UtcNow = new(2026, 9, 10, 8, 0, 0, DateTimeKind.Utc); private static LearningGroup Group(string name, int? webUntisLessonId, bool isActive = true) => new() { Name = name, WebUntisLessonId = webUntisLessonId, IsActive = isActive }; [Fact] public void BuildRows_ProGruppeMitLessonId_ZweiFehlzeitenzeilenPlusDreiGlobaleZeilen() { var group = Group("9a", 42); var rows = UntisHubService.BuildRows([group], [], UtcNow); Assert.Equal(5, rows.Count); Assert.Equal(2, rows.Count(r => r.GroupId == group.Id)); Assert.Contains(rows, r => r.Kind == UntisHubJobKind.FehlzeitenKurz && r.GroupId == group.Id); Assert.Contains(rows, r => r.Kind == UntisHubJobKind.FehlzeitenLang && r.GroupId == group.Id); Assert.Contains(rows, r => r.Kind == UntisHubJobKind.OffenePeriods && r.GroupId == null); Assert.Contains(rows, r => r.Kind == UntisHubJobKind.Klassenbuchabgleich && r.GroupId == null); Assert.Contains(rows, r => r.Kind == UntisHubJobKind.Hausaufgabenabgleich && r.GroupId == null); } [Fact] public void BuildRows_NieGeprueft_GiltAlsUeberfaellig() { var rows = UntisHubService.BuildRows([], [], UtcNow); Assert.All(rows, r => Assert.Equal(UntisHubDueState.Overdue, r.DueState)); } [Fact] public void BuildRows_FehlzeitenKurzVorSechsTagen_GiltAlsOk() { var group = Group("9a", 42); var state = new UntisHubJobState { Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-6), }; var rows = UntisHubService.BuildRows([group], [state], UtcNow); var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz); Assert.Equal(UntisHubDueState.Ok, row.DueState); } [Fact] public void BuildRows_FehlzeitenKurzVorSechzehnTagen_GiltAlsFaellig() { var group = Group("9a", 42); var state = new UntisHubJobState { Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-16), }; var rows = UntisHubService.BuildRows([group], [state], UtcNow); var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz); Assert.Equal(UntisHubDueState.Due, row.DueState); } [Fact] public void BuildRows_FehlzeitenKurzVorZweiundzwanzigTagen_GiltAlsUeberfaellig() { var group = Group("9a", 42); var state = new UntisHubJobState { Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-22), }; var rows = UntisHubService.BuildRows([group], [state], UtcNow); var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz); Assert.Equal(UntisHubDueState.Overdue, row.DueState); } [Fact] public void BuildRows_FehlzeitenLangHatDeutlichLaengereKadenzAlsKurz() { var group = Group("9a", 42); var lastRunAt = UtcNow.AddDays(-40); var states = new List { new() { Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = lastRunAt }, new() { Kind = UntisHubJobKind.FehlzeitenLang, GroupId = group.Id, LastRunAt = lastRunAt }, }; var rows = UntisHubService.BuildRows([group], states, UtcNow); Assert.Equal(UntisHubDueState.Overdue, rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz).DueState); Assert.Equal(UntisHubDueState.Ok, rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenLang).DueState); } [Fact] public void BuildRows_GruppeOhneWebUntisLessonId_WirdVonAufrufseiteAusgeschlossen() { // GetRows() filtert vorab auf WebUntisLessonId != null (siehe UntisHubService.GetRows) - // BuildRows selbst bekommt bereits nur die eligible-Gruppen übergeben. var eligible = new List { Group("9a", 42) }; var rows = UntisHubService.BuildRows(eligible, [], UtcNow); Assert.Equal(2, rows.Count(r => r.GroupId != null)); } }