Files
LehrerApp/LehrerApp.Desktop.Tests/LessonViewerViewModelTests.cs
adminandClaude Sonnet 5 391628ae36 Vernetzung Stundenplan ↔ Unterrichtsplanung: Terminvorschlag, Lesson-Viewer-Sprung, Verzweigung (4.5.1–4.5.3)
4.5.1: Terminvorschlag für neue Stunden schlägt jetzt auch die Stundennummer
vor (bei Doppelstunden die erste Periode), nicht nur den Wochentag —
zieht über den bestehenden LessonNumber-Changed-Hook automatisch auch den
Stundenbeginn nach.

4.5.2 (teilweise): Klick auf eine Stunde im Stundenplan ("Heute"-Liste und
read-only Wochenraster) springt bei bereits vorhandener Lesson direkt in
den Verlaufsplan-Viewer statt nur grob zum Planung-Tab. Das Anlegen einer
neuen Lesson direkt aus dem Stundenplan bleibt bewusst offen (ungeklärte
Unit-Zuordnung, siehe TODO.md).

4.5.3: Der Lesson-Viewer hat jetzt Buttons "Zur Mitarbeit"/"Zu den Noten"
zum Weiterverzweigen in die Lerngruppe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-19 23:39:27 +02:00

131 lines
5.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using LehrerApp.Core.Models;
using LehrerApp.Desktop.ViewModels.Groups;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class LessonViewerViewModelTests
{
[Fact]
public void OhneAlternativenGibtEsGenauEineHauptwegGruppe()
{
var lesson = new Lesson
{
Topic = "Brechung", Date = new DateOnly(2025, 9, 1), StartTime = new TimeOnly(11, 45),
Phases =
[
new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 5, Activity = "Begrüßung" },
new LessonPhaseStep { Name = "Erarbeitung", DurationMinutes = 15, Activity = "AB01 bearbeiten" },
],
};
var vm = new LessonViewerViewModel(lesson, new FakeAlternativeLessonPaths([]));
Assert.False(vm.HasAlternatives);
var group = Assert.Single(vm.PhaseGroups);
Assert.Equal("Hauptweg", group.Label);
Assert.True(group.IsMainPath);
Assert.Equal(2, group.Phases.Count);
Assert.Equal("ab 11:45", group.Phases[0].TimeDisplay);
Assert.Equal("ab 11:50", group.Phases[1].TimeDisplay);
}
[Fact]
public void OhneBeginnBleibtDieUhrzeitanzeigeLeer()
{
var lesson = new Lesson
{
Topic = "Brechung", Date = new DateOnly(2025, 9, 1),
Phases = [new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 5 }],
};
var vm = new LessonViewerViewModel(lesson, new FakeAlternativeLessonPaths([]));
Assert.Equal("", vm.PhaseGroups[0].Phases[0].TimeDisplay);
Assert.Equal("", vm.StartTimeDisplay);
}
[Fact]
public void GruppiertPhasenNachAlternativePathUndHauptwegStehtImmerZuerst()
{
var kurzversion = new AlternativeLessonPath { Name = "Kurzversion", Description = "Bei Zeitmangel." };
var alternativePaths = new FakeAlternativeLessonPaths([kurzversion]);
var lesson = new Lesson
{
Topic = "Brechung", Date = new DateOnly(2025, 9, 1), StartTime = new TimeOnly(12, 0),
Phases =
[
new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 5, AlternativePathId = kurzversion.Id },
new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 5 }, // Hauptweg, aber nach der Alternative angelegt
new LessonPhaseStep { Name = "Sicherung (kurz)", DurationMinutes = 5, AlternativePathId = kurzversion.Id },
new LessonPhaseStep { Name = "Erarbeitung", DurationMinutes = 20 },
],
};
var vm = new LessonViewerViewModel(lesson, alternativePaths);
Assert.True(vm.HasAlternatives);
Assert.Equal(2, vm.PhaseGroups.Count);
Assert.Equal("Hauptweg", vm.PhaseGroups[0].Label); // steht zuerst trotz Reihenfolge im Modell
Assert.True(vm.PhaseGroups[0].IsMainPath);
Assert.Null(vm.PhaseGroups[0].Description);
Assert.Equal(2, vm.PhaseGroups[0].Phases.Count);
Assert.Equal("Kurzversion", vm.PhaseGroups[1].Label);
Assert.False(vm.PhaseGroups[1].IsMainPath);
Assert.Equal("Bei Zeitmangel.", vm.PhaseGroups[1].Description);
Assert.Equal(2, vm.PhaseGroups[1].Phases.Count);
}
[Fact]
public void JedeGruppeBerechnetIhreEigeneUhrzeitAbStundenbeginn()
{
var planB = new AlternativeLessonPath { Name = "Plan B" };
var alternativePaths = new FakeAlternativeLessonPaths([planB]);
var lesson = new Lesson
{
Topic = "Brechung", Date = new DateOnly(2025, 9, 1), StartTime = new TimeOnly(12, 0),
Phases =
[
new LessonPhaseStep { Name = "Einstieg", DurationMinutes = 5 },
new LessonPhaseStep { Name = "Vertiefung", DurationMinutes = 30, AlternativePathId = planB.Id },
],
};
var vm = new LessonViewerViewModel(lesson, alternativePaths);
// Beide Gruppen starten unabhängig voneinander bei Stundenbeginn, nicht hintereinander.
Assert.Equal("ab 12:00", vm.PhaseGroups[0].Phases[0].TimeDisplay);
Assert.Equal("ab 12:00", vm.PhaseGroups[1].Phases[0].TimeDisplay);
}
// ── Verzweigung aus dem Viewer (4.5.3) ────────────────────────────────────────
[Fact]
public void NavigateToParticipation_RuftDelegatMitTabIndexDreiAuf()
{
var groupId = Guid.NewGuid();
var lesson = new Lesson { GroupId = groupId, Topic = "Brechung", Date = new DateOnly(2025, 9, 1) };
var vm = new LessonViewerViewModel(lesson, new FakeAlternativeLessonPaths([]));
int? navigatedTab = null;
vm.OnNavigateToTab = idx => navigatedTab = idx;
vm.NavigateToParticipationCommand.Execute(null);
Assert.Equal(groupId, vm.GroupId);
Assert.Equal(3, navigatedTab);
}
[Fact]
public void NavigateToGrades_RuftDelegatMitTabIndexFuenfAuf()
{
var lesson = new Lesson { GroupId = Guid.NewGuid(), Topic = "Brechung", Date = new DateOnly(2025, 9, 1) };
var vm = new LessonViewerViewModel(lesson, new FakeAlternativeLessonPaths([]));
int? navigatedTab = null;
vm.OnNavigateToTab = idx => navigatedTab = idx;
vm.NavigateToGradesCommand.Execute(null);
Assert.Equal(5, navigatedTab);
}
}