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>
131 lines
5.3 KiB
C#
131 lines
5.3 KiB
C#
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);
|
||
}
|
||
}
|