using LehrerApp.Core.Models; using LehrerApp.Desktop.ViewModels.Groups; using Xunit; namespace LehrerApp.Desktop.Tests; public sealed class TeachingModeViewModelTests { private static SeatingPlanTabViewModel BuildSeatingPlan(Guid groupId, FakeSessions? sessions = null, List? students = null, List? memberships = null, List? plans = null) => new(new FakeSeatingPlans(plans ?? [new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 }]), new FakeStudents(students ?? []), new FakeMemberships(memberships ?? []), sessions ?? new FakeSessions([]), new FakeEntries(), new FakeAspects()); /// Dieselben Fakes wie , aber für ParticipationTabViewModel — /// beide brauchen eigene IParticipationSessionRepository/IParticipationRepository-Instanzen /// im Produktivcode (siehe TeachingModeWindow-Kommentar zu ReloadSeatBadgesFromRepository), /// hier reicht für die Tests aber eine gemeinsame FakeSessions-Instanz, damit beide /// ViewModels dieselbe verknüpfte Sitzung sehen. private static ParticipationTabViewModel BuildParticipation(LearningGroup group, FakeSessions? sessions = null) => new(sessions ?? new FakeSessions([]), new FakeEntries(), new FakeAspects(), new FakeStudents([]), new FakeMemberships([]), new FakeGroups([group]), new FakeCompetencyDomains()); [Fact] public void Konstruktor_LaedtVerlaufsplanUndInitialisiertSitzplanFuerDieGruppe() { var group = new LearningGroup { Name = "Q1 Chemie" }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox", Phases = [new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 10, Activity = "Impuls" }], }; var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), new FakeLessons(), seatingPlan, BuildParticipation(group)); Assert.Equal("Q1 Chemie", vm.GroupName); Assert.Equal("Redox", vm.LessonInfo.Topic); Assert.Single(vm.LessonInfo.PhaseGroups.Single().Phases); Assert.True(vm.SeatingPlan.HasSelectedPlan); } [Fact] public void Konstruktor_VerknuepftDieSitzungMitDieserStunde() { var group = new LearningGroup { Name = "Q1 Chemie" }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" }; var sessions = new FakeSessions([]); var seatingPlan = BuildSeatingPlan(group.Id, sessions); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), new FakeLessons(), seatingPlan, BuildParticipation(group, sessions)); var created = Assert.Single(sessions.GetByGroup(group.Id)); Assert.Equal(lesson.Id, created.LessonId); Assert.Equal(vm.SeatingPlan.SelectedSession?.Id, created.Id); } /// Nutzer-Feedback: Schnellbewertungs-Dialoge (Mitarbeit, Anwesenheit/Hausaufgabe) sollen sich /// im Unterrichtsmodus direkt öffnen lassen — das setzt voraus, dass die dafür verwendete /// ParticipationTabViewModel-Instanz von Anfang an auf der zu dieser Stunde gehörenden /// Sitzung steht, nicht auf einer beliebigen anderen Sitzung der Gruppe. [Fact] public void Konstruktor_SelektiertDieselbeSitzungAuchInDerParticipationViewModel() { var group = new LearningGroup { Name = "Q1 Chemie" }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" }; var otherSession = new ParticipationSession { GroupId = group.Id, Date = lesson.Date.AddDays(-1), Comment = "Andere Stunde" }; var sessions = new FakeSessions([otherSession]); var seatingPlan = BuildSeatingPlan(group.Id, sessions); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), new FakeLessons(), seatingPlan, BuildParticipation(group, sessions)); Assert.NotNull(vm.SeatingPlan.SelectedSession); Assert.Equal(vm.SeatingPlan.SelectedSession!.Id, vm.Participation.SelectedSession?.Id); Assert.NotEqual(otherSession.Id, vm.Participation.SelectedSession?.Id); } [Fact] public void Konstruktor_BereitsExistierendeVerknuepfteSitzung_WirdWiederverwendet() { var group = new LearningGroup { Name = "Q1 Chemie" }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" }; var existing = new ParticipationSession { GroupId = group.Id, Date = lesson.Date, LessonId = lesson.Id, Comment = "Redox" }; var sessions = new FakeSessions([existing]); var seatingPlan = BuildSeatingPlan(group.Id, sessions); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), new FakeLessons(), seatingPlan, BuildParticipation(group, sessions)); Assert.Single(sessions.GetByGroup(group.Id)); Assert.Equal(existing.Id, vm.SeatingPlan.SelectedSession?.Id); } /// Eine archivierte Gruppe darf im Unterrichtsmodus nicht bearbeitbar sein - genau wie in der /// normalen Gruppenansicht (GroupDetailViewModel.IsReadOnly). [Fact] public void Konstruktor_ArchivierteGruppe_InitialisiertSitzplanSchreibgeschuetzt() { var group = new LearningGroup { Name = "Q1 Chemie", IsActive = false }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" }; var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), new FakeLessons(), seatingPlan, BuildParticipation(group)); Assert.False(vm.SeatingPlan.IsEditable); } // ── Hausaufgabe: letzte Stunde ansehen/abhaken, aktuelle einsehen/ändern ───── [Fact] public void Konstruktor_FindetHausaufgabeDerVorherigenStunde() { var group = new LearningGroup { Name = "Q1 Chemie" }; var today = DateOnly.FromDateTime(DateTime.Today); var previous = new Lesson { GroupId = group.Id, Date = today.AddDays(-7), Topic = "Säuren", Homework = "S. 42, Aufgabe 3", HomeworkChecked = false, }; var lesson = new Lesson { GroupId = group.Id, Date = today, Topic = "Redox" }; var lessons = new FakeLessons(); lessons.Add(previous); var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), lessons, seatingPlan, BuildParticipation(group)); Assert.True(vm.Homework.HasPreviousHomework); Assert.Equal("S. 42, Aufgabe 3", vm.Homework.PreviousHomeworkText); Assert.Contains("Säuren", vm.Homework.PreviousLessonLabel); Assert.False(vm.Homework.PreviousHomeworkChecked); } [Fact] public void Konstruktor_IgnoriertVorherigeStundeOhneHausaufgabe() { var group = new LearningGroup { Name = "Q1 Chemie" }; var today = DateOnly.FromDateTime(DateTime.Today); var previous = new Lesson { GroupId = group.Id, Date = today.AddDays(-7), Topic = "Säuren" }; var lesson = new Lesson { GroupId = group.Id, Date = today, Topic = "Redox" }; var lessons = new FakeLessons(); lessons.Add(previous); var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), lessons, seatingPlan, BuildParticipation(group)); Assert.False(vm.Homework.HasPreviousHomework); } [Fact] public void PreviousHomeworkChecked_SpeichertSofortAnDerVorherigenStunde() { var group = new LearningGroup { Name = "Q1 Chemie" }; var today = DateOnly.FromDateTime(DateTime.Today); var previous = new Lesson { GroupId = group.Id, Date = today.AddDays(-7), Topic = "Säuren", Homework = "S. 42" }; var lesson = new Lesson { GroupId = group.Id, Date = today, Topic = "Redox" }; var lessons = new FakeLessons(); lessons.Add(previous); var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), lessons, seatingPlan, BuildParticipation(group)); vm.Homework.PreviousHomeworkChecked = true; var saved = Assert.Single(lessons.GetByGroupAndRange(group.Id, today.AddDays(-120), today.AddDays(-1))); Assert.True(saved.HomeworkChecked); } [Fact] public void SaveCurrentHomework_SchreibtAufDieAktuelleStunde() { var group = new LearningGroup { Name = "Q1 Chemie" }; var lesson = new Lesson { GroupId = group.Id, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" }; var lessons = new FakeLessons(); lessons.Add(lesson); var seatingPlan = BuildSeatingPlan(group.Id); var vm = new TeachingModeViewModel(lesson, group, new FakeAlternativeLessonPaths([]), lessons, seatingPlan, BuildParticipation(group)); vm.Homework.CurrentHomework = "AB 7 fertigstellen"; vm.Homework.SaveCurrentHomeworkCommand.Execute(null); var saved = Assert.Single(lessons.GetByGroupAndRange(group.Id, lesson.Date, lesson.Date)); Assert.Equal("AB 7 fertigstellen", saved.Homework); Assert.Equal("Gespeichert.", vm.Homework.SaveStatus); } }