using LehrerApp.Desktop.Services; using LehrerApp.Desktop.ViewModels.ClassTeacher; using Xunit; namespace LehrerApp.Desktop.Tests; public sealed class ClassTeacherViewModelsTests { [Fact] public void GroupByStudentAndDay_FasstFehlstundenProSchuelerUndTagZusammen() { var entries = new[] { new UntisClassAbsenceEntryDto("Muster Max", 1, "6a", 20260824, 1, 45, "HED", "Che", "Absent", "Krank", 1, "24.08.26", true, null, 3, "nicht entsch.", false), new UntisClassAbsenceEntryDto("Muster Max", 1, "6a", 20260824, 1, 45, "PAN", "Kunst", null, "Krank", 2, "24.08.26", true, null, 5, "nicht entsch.", true), new UntisClassAbsenceEntryDto("Andere Schuelerin", 2, "6a", 20260824, 1, 20, "BEN", "Deu", "Verspätung", null, 3, "24.08.26", false, "Zug verpasst", 1, "entsch.", false), }; var rows = ClassAbsenceDaySummaryRow.GroupByStudentAndDay(entries); Assert.Equal(2, rows.Count); var max = rows[1]; Assert.Equal("Muster Max", max.StudentName); Assert.Equal(2, max.TotalAbsentPeriods); Assert.Equal(90, max.TotalAbsentMinutes); Assert.Equal(["Che", "Kunst"], max.Subjects); Assert.Equal([3, 5], max.PeriodNumbers.Order()); Assert.Equal(["nicht entsch."], max.Statuses); Assert.Equal(["Absent"], max.AbsenceReasons); Assert.Equal("Krank", max.Note); Assert.Null(max.ExcuseNote); Assert.True(max.CountsAsFullDay); var andere = rows[0]; Assert.Equal("Andere Schuelerin", andere.StudentName); Assert.Equal(1, andere.TotalAbsentPeriods); Assert.Equal(20, andere.TotalAbsentMinutes); Assert.Equal(["Deu"], andere.Subjects); Assert.Null(andere.Note); Assert.Equal("Zug verpasst", andere.ExcuseNote); Assert.False(andere.CountsAsFullDay); } [Fact] public void GroupByStudentAndDay_TrenntGleichenNamenAnUnterschiedlichenTagen() { var entries = new[] { new UntisClassAbsenceEntryDto("Muster Max", 1, "6a", 20260824, 1, 45, "HED", "Che", null, null, 1, "24.08.26", true, null, 3, "nicht entsch.", false), new UntisClassAbsenceEntryDto("Muster Max", 1, "6a", 20260825, 1, 45, "HED", "Che", null, null, 2, "25.08.26", true, null, 3, "nicht entsch.", false), }; var rows = ClassAbsenceDaySummaryRow.GroupByStudentAndDay(entries); Assert.Equal(2, rows.Count); Assert.Equal(new DateOnly(2026, 8, 25), rows[0].Date); Assert.Equal(new DateOnly(2026, 8, 24), rows[1].Date); } [Fact] public void RosterBuild_OrdnetFehlzeitPerExternKeyUndKlassenbuchPerNameZu() { var students = new[] { Student(1001, "Ada Müller"), Student(1002, "Ben Schmidt"), Student(1003, "Cem Yilmaz"), }; var todayAbsences = new[] { new ClassAbsenceDaySummaryRow(new DateOnly(2026, 8, 25), "Ada Müller", 1001, 2, 90, ["Che"], [3, 4], ["nicht entsch."], ["Absent"], null, null, false), }; var recentClassRegister = new[] { new UntisForeignClassRegisterEventDto("6a", 20260824, "Deu", "Ben Schmidt", "mueller", "Vergessen", "Organisation", "Buch vergessen"), }; var roster = ClassTeacherRosterRow.Build(students, todayAbsences, recentClassRegister); Assert.Equal(3, roster.Count); var ada = Assert.Single(roster, r => r.StudentName == "Ada Müller"); Assert.True(ada.HasAbsenceToday); Assert.Contains("nicht entsch.", ada.AbsenceTooltip); Assert.False(ada.HasRecentClassRegisterEntry); var ben = Assert.Single(roster, r => r.StudentName == "Ben Schmidt"); Assert.False(ben.HasAbsenceToday); Assert.True(ben.HasRecentClassRegisterEntry); var cem = Assert.Single(roster, r => r.StudentName == "Cem Yilmaz"); Assert.False(cem.HasAbsenceToday); Assert.False(cem.HasRecentClassRegisterEntry); } [Fact] public void RosterBuild_ErkenntNamenAuchInVertauschterReihenfolge() { // WebUntis liefert Namen im Schülerreport als "Vorname Nachname", in Fehlzeiten-/ // Klassenbuchberichten aber typischerweise als "Nachname Vorname" - der Namensabgleich // muss das auch ohne ExternKey erkennen (Regressionstest für genau diesen Bug). var students = new[] { Student(externKey: null, displayName: "Ben Schmidt") }; var todayAbsences = new[] { new ClassAbsenceDaySummaryRow(new DateOnly(2026, 8, 25), "Schmidt Ben", null, 1, 45, ["Che"], [3], ["nicht entsch."], ["Absent"], null, null, false), }; var recentClassRegister = new[] { new UntisForeignClassRegisterEventDto("6a", 20260824, "Deu", "Schmidt Ben", "mueller", "Vergessen", "Organisation", "Buch vergessen"), }; var roster = ClassTeacherRosterRow.Build(students, todayAbsences, recentClassRegister); var ben = Assert.Single(roster); Assert.True(ben.HasAbsenceToday); Assert.True(ben.HasRecentClassRegisterEntry); } private static UntisStudentDto Student(int? externKey, string displayName) => new( UntisId: externKey ?? 0, ExternKey: externKey, ClassName: "6a", Name: displayName, LongName: null, ForeName: null, DisplayName: displayName, Gender: null, BirthDate: null, BirthDateRaw: null, EntryDate: null, EntryDateRaw: null, ExitDate: null, ExitDateRaw: null, Text: null, MedicalReportDuty: null, Schulpflicht: null, Majority: null, Address: new UntisStudentAddressDto(null, null, null, null, null, null), AttributeIL: null); }