Verlaufsplan und Sitzplan bisher über mehrere Tabs verteilt, obwohl im Unterricht selbst beides gleichzeitig gebraucht wird. Neuer Button "▶ Unterricht" in der "Heute"-Tagesliste des Stundenplans (nur bei vorhandener Lesson) öffnet ein maximiertes Fenster: links der schreibgeschützte Verlaufsplan als kompakte Kartenliste, rechts der volle, unverändert wiederverwendete SeatingPlanTabView (Drag&Drop, Schnellbewertung, Situations-Tags, PDF-Export). TeachingModeViewModel baut auf dem bestehenden LessonViewerViewModel auf, dadurch kommen "Zur Mitarbeit"/"Zu den Noten" ohne Duplizierung mit. Neue SeatingPlanTabViewModel.SelectOrCreateSessionForLesson verknüpft die Mitarbeitssitzung automatisch mit der konkreten Stunde - anders als die bestehende EnsureTodaySession darf das hier sofort beim Start passieren, da durch den expliziten Klick für genau diese Stunde eindeutig feststeht, worum es geht (keine Geistersitzungs-Gefahr wie beim bloßen Tab-Öffnen). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
546 lines
23 KiB
C#
546 lines
23 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Desktop.ViewModels.Groups;
|
|
using LehrerApp.Desktop.Views.Groups;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Desktop.Tests;
|
|
|
|
public sealed class SeatingPlanViewModelTests
|
|
{
|
|
[Fact]
|
|
public void TafelpositionWirdAusPlanGeladenUndBeimBearbeitenGespeichert()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId,
|
|
Name = "Standard",
|
|
Rows = 1,
|
|
Columns = 1,
|
|
IsBoardAtBottom = true,
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var tabVm = new SeatingPlanTabViewModel(
|
|
plans, new FakeStudents([]), new FakeMemberships([]),
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
|
|
tabVm.Initialize(groupId, isReadOnly: false);
|
|
|
|
Assert.True(tabVm.IsBoardAtBottom);
|
|
Assert.False(tabVm.IsBoardAtTop);
|
|
|
|
var dialogVm = tabVm.CreateDialogViewModel(plan);
|
|
dialogVm.IsBoardAtBottom = false;
|
|
dialogVm.SaveCommand.Execute(null);
|
|
|
|
Assert.False(plans.GetById(plan.Id)!.IsBoardAtBottom);
|
|
}
|
|
|
|
[Fact]
|
|
public void AuswahlEinesBereitsZugeordnetenSchuelers_VerschiebtIhnAufDenNeuenPlatz()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
|
var students = new FakeStudents([student]);
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId,
|
|
Name = "Standard",
|
|
Rows = 1,
|
|
Columns = 2,
|
|
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanTabViewModel(plans, students, memberships,
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.Seats[1].SelectedOption = vm.StudentOptions.Single(o => o.StudentId == student.Id);
|
|
|
|
Assert.Null(vm.Seats[0].SelectedOption.StudentId);
|
|
var assignment = Assert.Single(plans.GetById(plan.Id)!.Assignments);
|
|
Assert.Equal((0, 1, student.Id), (assignment.Row, assignment.Column, assignment.StudentId));
|
|
}
|
|
|
|
[Fact]
|
|
public void ArchivierteGruppe_DeaktiviertSitzplatzbearbeitung()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
|
|
var vm = new SeatingPlanTabViewModel(
|
|
new FakeSeatingPlans([plan]), new FakeStudents([]), new FakeMemberships([]),
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
|
|
vm.Initialize(groupId, isReadOnly: true);
|
|
|
|
Assert.False(vm.IsEditable);
|
|
Assert.False(vm.Seats.Single().CanEdit);
|
|
Assert.False(vm.AddPlanCommand.CanExecute(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void DragDrop_ZwischenBelegtenPlaetzen_TauschtDieSchueler()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var anna = new Student { FirstName = "Anna", LastName = "A" };
|
|
var ben = new Student { FirstName = "Ben", LastName = "B" };
|
|
var students = new FakeStudents([anna, ben]);
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = anna.Id },
|
|
new GroupMembership { GroupId = groupId, StudentId = ben.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
|
Assignments =
|
|
[
|
|
new SeatAssignment { Row = 0, Column = 0, StudentId = anna.Id },
|
|
new SeatAssignment { Row = 0, Column = 1, StudentId = ben.Id },
|
|
],
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanTabViewModel(plans, students, memberships,
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.MoveSeat(vm.Seats[0], vm.Seats[1]);
|
|
|
|
Assert.Equal(ben.Id, vm.Seats[0].SelectedOption.StudentId);
|
|
Assert.Equal(anna.Id, vm.Seats[1].SelectedOption.StudentId);
|
|
Assert.Equal(2, plans.GetById(plan.Id)!.Assignments.Count);
|
|
}
|
|
|
|
// ── Ausgeblendete Plätze (fehlender Tisch in einer Reihe) ─────────────────────────────
|
|
|
|
[Fact]
|
|
public void LoadPlan_LaedtAusgeblendetePlaetzeAusDemPlan()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
|
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(
|
|
new FakeSeatingPlans([plan]), new FakeStudents([]), new FakeMemberships([]),
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
Assert.False(vm.Seats[0].IsHidden);
|
|
Assert.True(vm.Seats[1].IsHidden);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToggleSeatHidden_LeererPlatz_BlendetAusUndSpeichertUndKannWiederEingeblendetWerden()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2 };
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([]), new FakeMemberships([]),
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.ToggleSeatHidden(vm.Seats[1]);
|
|
|
|
Assert.True(vm.Seats[1].IsHidden);
|
|
var hidden = Assert.Single(plans.GetById(plan.Id)!.HiddenSeats);
|
|
Assert.Equal((0, 1), (hidden.Row, hidden.Column));
|
|
|
|
vm.ToggleSeatHidden(vm.Seats[1]);
|
|
|
|
Assert.False(vm.Seats[1].IsHidden);
|
|
Assert.Empty(plans.GetById(plan.Id)!.HiddenSeats);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToggleSeatHidden_BelegterPlatz_TutNichts()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
|
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
memberships, new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.ToggleSeatHidden(vm.Seats[0]);
|
|
|
|
Assert.False(vm.Seats[0].IsHidden);
|
|
}
|
|
|
|
/// Ein ausgeblendeter Platz darf nie ein Ziel für Drag&Drop/Zuordnung sein - sonst hätte man
|
|
/// gleichzeitig "kein Tisch hier" und einen dort sitzenden Schüler.
|
|
[Fact]
|
|
public void AssignStudent_AufAusgeblendetenPlatz_WirdIgnoriert()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
|
HiddenSeats = [new HiddenSeat { Row = 0, Column = 0 }],
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([student]), memberships,
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.AssignStudent(vm.StudentOptions.Single(o => o.StudentId == student.Id), vm.Seats[0]);
|
|
|
|
Assert.False(vm.Seats[0].IsOccupied);
|
|
Assert.Empty(plans.GetById(plan.Id)!.Assignments);
|
|
}
|
|
|
|
[Fact]
|
|
public void MoveSeat_AufAusgeblendetenPlatz_WirdIgnoriert()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
|
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
|
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([student]), memberships,
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.IsEditMode = true;
|
|
|
|
vm.MoveSeat(vm.Seats[0], vm.Seats[1]);
|
|
|
|
Assert.Equal(student.Id, vm.Seats[0].SelectedOption.StudentId);
|
|
Assert.False(vm.Seats[1].IsOccupied);
|
|
}
|
|
|
|
// ── Unterrichtsmodus (14.x): Sitzung mit einer konkreten Stunde verknüpfen ────────────────
|
|
|
|
[Fact]
|
|
public void SelectOrCreateSessionForLesson_BereitsVerknuepfteSitzungVorhanden_WaehltSieAus()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var lesson = new Lesson { GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" };
|
|
var existingSession = new ParticipationSession
|
|
{ GroupId = groupId, Date = lesson.Date, LessonId = lesson.Id, Comment = "Redox" };
|
|
var sessions = new FakeSessions([existingSession]);
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([]),
|
|
new FakeMemberships([]), sessions, new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
vm.SelectOrCreateSessionForLesson(lesson);
|
|
|
|
Assert.Equal(existingSession.Id, vm.SelectedSession?.Id);
|
|
Assert.Single(sessions.GetByGroup(groupId));
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectOrCreateSessionForLesson_KeineSitzungVorhanden_LegtVerknuepfteAnUndWaehltSieAus()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var lesson = new Lesson
|
|
{ GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" };
|
|
var sessions = new FakeSessions([]);
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([]),
|
|
new FakeMemberships([]), sessions, new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
vm.SelectOrCreateSessionForLesson(lesson);
|
|
|
|
var created = Assert.Single(sessions.GetByGroup(groupId));
|
|
Assert.Equal(lesson.Id, created.LessonId);
|
|
Assert.Equal(lesson.Topic, created.Comment);
|
|
Assert.Equal(vm.SelectedSession?.Id, created.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectOrCreateSessionForLesson_ArchivierteGruppe_LegtKeineSitzungAn()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var lesson = new Lesson
|
|
{ GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today), Topic = "Redox" };
|
|
var sessions = new FakeSessions([]);
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([]),
|
|
new FakeMemberships([]), sessions, new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: true);
|
|
|
|
vm.SelectOrCreateSessionForLesson(lesson);
|
|
|
|
Assert.Empty(sessions.GetByGroup(groupId));
|
|
Assert.Null(vm.SelectedSession);
|
|
}
|
|
|
|
[Fact]
|
|
public void ShowSeatUndCanToggleHidden_HaengenVonBearbeitungsmodusUndBelegungAb()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
|
]);
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
|
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
|
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
memberships, new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
// Ansichtsmodus: der ausgeblendete Platz wird nicht gerendert, belegte Plätze können
|
|
// ohnehin nicht ausgeblendet werden.
|
|
Assert.False(vm.Seats[1].ShowSeat);
|
|
Assert.False(vm.Seats[0].CanToggleHidden);
|
|
Assert.False(vm.Seats[1].CanToggleHidden);
|
|
|
|
vm.IsEditMode = true;
|
|
|
|
// Bearbeitungsmodus: der ausgeblendete Platz bleibt sichtbar (abgeblendet), um ihn wieder
|
|
// einblenden zu können - der belegte Platz kann weiterhin nicht ausgeblendet werden.
|
|
Assert.True(vm.Seats[1].ShowSeat);
|
|
Assert.False(vm.Seats[0].CanToggleHidden);
|
|
Assert.True(vm.Seats[1].CanToggleHidden);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ansichtsmodus_VerhindertVerschiebenUndBlendetBearbeitungsbefehleAus()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
|
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(
|
|
new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]),
|
|
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
vm.MoveSeat(vm.Seats[0], vm.Seats[1]);
|
|
|
|
Assert.False(vm.IsEditMode);
|
|
Assert.False(vm.CanEditLayout);
|
|
Assert.False(vm.EditPlanCommand.CanExecute(null));
|
|
Assert.Equal(student.Id, vm.Seats[0].SelectedOption.StudentId);
|
|
Assert.Null(vm.Seats[1].SelectedOption.StudentId);
|
|
|
|
vm.IsEditMode = true;
|
|
|
|
Assert.True(vm.CanEditLayout);
|
|
Assert.True(vm.EditPlanCommand.CanExecute(null));
|
|
Assert.All(vm.Seats, seat => Assert.True(seat.CanEdit));
|
|
}
|
|
|
|
[Fact]
|
|
public void Ansichtsmodus_ZeigtAnwesenheitUndHausaufgabeUndBlendetAbwesendeAb()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var session = new ParticipationSession { GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today) };
|
|
var entries = new FakeEntries();
|
|
entries.Add(new ParticipationEntry
|
|
{
|
|
SessionId = session.Id, StudentId = student.Id,
|
|
Attendance = AttendanceStatus.Excused, Homework = HomeworkStatus.MissingOpen,
|
|
});
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
|
Assignments = [new SeatAssignment { StudentId = student.Id }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]),
|
|
new FakeSessions([session]), entries, new FakeAspects());
|
|
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
var seat = Assert.Single(vm.Seats);
|
|
Assert.True(seat.HasAttendanceBadge);
|
|
Assert.True(seat.HasHomeworkBadge);
|
|
Assert.Equal(0.42, seat.LessonOpacity);
|
|
}
|
|
|
|
[Fact]
|
|
public void SituationsTags_WerdenProSchuelerUndSitzungInEinemEntwurfZusammengefuehrt()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var session = new ParticipationSession
|
|
{
|
|
GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today), LessonId = Guid.NewGuid(),
|
|
};
|
|
var docs = new FakeDocumentation();
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
|
Assignments = [new SeatAssignment { StudentId = student.Id }],
|
|
};
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]),
|
|
new FakeSessions([session]), new FakeEntries(), new FakeAspects(), docs);
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
var seat = Assert.Single(vm.Seats);
|
|
|
|
seat.SituationTags.Single(t => t.Text == "Mitarbeit verweigert").ToggleCommand.Execute(null);
|
|
seat.SituationTags.Single(t => t.Text == "Material vergessen").ToggleCommand.Execute(null);
|
|
|
|
var draft = Assert.Single(docs.GetByStudent(student.Id));
|
|
Assert.True(draft.IsDraft);
|
|
Assert.Equal(session.Id, draft.ParticipationSessionId);
|
|
Assert.Equal(session.LessonId, draft.LessonId);
|
|
Assert.Equal(["Mitarbeit verweigert", "Material vergessen"], draft.Tags);
|
|
}
|
|
|
|
[Fact]
|
|
public void Tischabstaende_WerdenBeimBearbeitenProSpaltengrenzeGespeichert()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 2, Columns = 4,
|
|
ColumnGapWidths = [0, 80, 20],
|
|
};
|
|
var plans = new FakeSeatingPlans([plan]);
|
|
var vm = new SeatingPlanDialogViewModel(plans, groupId, plan);
|
|
|
|
Assert.Equal([0m, 80m, 20m], vm.ColumnGaps.Select(g => g.Width));
|
|
vm.ColumnGaps[0].Width = 40;
|
|
vm.SaveCommand.Execute(null);
|
|
|
|
Assert.Equal([40d, 80d, 20d], plans.GetById(plan.Id)!.ColumnGapWidths);
|
|
}
|
|
|
|
[Fact]
|
|
public void SitzplanPanel_FuegtAbstandNurAnKonfigurierterSpaltengrenzeEin()
|
|
{
|
|
var panel = new SeatingPlanPanel
|
|
{
|
|
Columns = 3,
|
|
ColumnGapWidths = [0, 70],
|
|
};
|
|
for (var i = 0; i < 6; i++)
|
|
panel.Children.Add(new Avalonia.Controls.Border { Width = 100, Height = 50 });
|
|
|
|
panel.Measure(Avalonia.Size.Infinity);
|
|
panel.Arrange(new Avalonia.Rect(panel.DesiredSize));
|
|
|
|
Assert.Equal(370, panel.DesiredSize.Width);
|
|
Assert.Equal(100, panel.DesiredSize.Height);
|
|
Assert.Equal(0, panel.Children[0].Bounds.X);
|
|
Assert.Equal(100, panel.Children[1].Bounds.X);
|
|
Assert.Equal(270, panel.Children[2].Bounds.X);
|
|
Assert.Equal(270, panel.Children[5].Bounds.X);
|
|
}
|
|
|
|
[Fact]
|
|
public void SitzplatzBewertung_ErstelltHeutigeSitzungUndSpeichertAlleDreiBereiche()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var studentId = Guid.NewGuid();
|
|
var sessions = new FakeSessions([]);
|
|
var entries = new FakeEntries();
|
|
var vm = new SeatAssessmentViewModel(sessions, entries, new FakeAspects(),
|
|
groupId, studentId, "Beispiel, Anna", canEdit: true);
|
|
|
|
vm.SetRatingByNumber(5);
|
|
vm.ApplyAttendanceShortcut(1, clear: false);
|
|
vm.ApplyHomeworkShortcut(7, clear: false);
|
|
|
|
var session = Assert.Single(sessions.GetByGroup(groupId));
|
|
Assert.Equal(DateOnly.FromDateTime(DateTime.Today), session.Date);
|
|
Assert.Equal("Sitzplan", session.Comment);
|
|
var entry = entries.GetBySessionAndStudent(session.Id, studentId)!;
|
|
Assert.Equal(2, entry.Ratings.Single(r => r.Key == "quality").Value);
|
|
Assert.Equal(AttendanceStatus.Present, entry.Attendance);
|
|
Assert.Equal(HomeworkStatus.MissingOpen, entry.Homework);
|
|
Assert.True(entry.HomeworkMissing);
|
|
}
|
|
|
|
[Fact]
|
|
public void SitzplatzBewertung_ArchiviertOhneSitzung_LegtKeineNeueSitzungAn()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var sessions = new FakeSessions([]);
|
|
|
|
var vm = new SeatAssessmentViewModel(sessions, new FakeEntries(), new FakeAspects(),
|
|
groupId, Guid.NewGuid(), "Beispiel, Anna", canEdit: false);
|
|
vm.SetRatingByNumber(5);
|
|
|
|
Assert.False(vm.CanEdit);
|
|
Assert.Empty(sessions.GetByGroup(groupId));
|
|
}
|
|
|
|
[Fact]
|
|
public void Initialize_LegtOhneVorhandeneSitzungKeineGeistersitzungAn()
|
|
{
|
|
// Regressionstest: Initialize() läuft schon beim bloßen Navigieren zur Kursübersicht
|
|
// (GroupDetailViewModel.LoadGroup ruft SeatingPlanTab.Initialize für jede Gruppe auf),
|
|
// unabhängig davon, ob der Sitzplan-Tab überhaupt angesehen wird. Vorher legte
|
|
// LoadTodaySessions() dabei sofort eine "Sitzplan"-Sitzung für heute an.
|
|
var groupId = Guid.NewGuid();
|
|
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
|
|
var sessions = new FakeSessions([]);
|
|
var vm = new SeatingPlanTabViewModel(
|
|
new FakeSeatingPlans([plan]), new FakeStudents([]), new FakeMemberships([]),
|
|
sessions, new FakeEntries(), new FakeAspects());
|
|
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
|
|
Assert.Empty(sessions.GetByGroup(groupId));
|
|
Assert.Null(vm.SelectedSession);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AssessStudent_LegtErstBeiTatsaechlicherBewertungEineSitzungAn()
|
|
{
|
|
var groupId = Guid.NewGuid();
|
|
var student = new Student { FirstName = "Anna", LastName = "A" };
|
|
var plan = new SeatingPlan
|
|
{
|
|
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
|
Assignments = [new SeatAssignment { StudentId = student.Id }],
|
|
};
|
|
var sessions = new FakeSessions([]);
|
|
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
|
new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]),
|
|
sessions, new FakeEntries(), new FakeAspects());
|
|
vm.Initialize(groupId, isReadOnly: false);
|
|
vm.OnAssessStudent = _ => Task.CompletedTask;
|
|
Assert.Empty(sessions.GetByGroup(groupId));
|
|
|
|
await vm.AssessStudent(vm.Seats.Single());
|
|
|
|
var session = Assert.Single(sessions.GetByGroup(groupId));
|
|
Assert.Equal(DateOnly.FromDateTime(DateTime.Today), session.Date);
|
|
Assert.Equal("Sitzplan", session.Comment);
|
|
Assert.Equal(session.Id, vm.SelectedSession?.Id);
|
|
}
|
|
}
|