TimetableSlotDialogViewModel baute die Gruppenauswahl als Dictionary,
geschlüsselt nach LearningGroup.Name. Bei zwei Lerngruppen mit demselben
Namen (dieselbe Klasse in zwei Fächern unterrichtet, z.B. zwei "10c") warf
ToDictionary eine ArgumentException, der Zuweisen-Dialog ließ sich gar
nicht mehr öffnen.
Behoben durch eindeutige Anzeige-Labels statt des rohen Namens: bei einem
Namenskonflikt wird das Fach angehängt ("10c (Chemie)" vs. "10c
(Mathematik)"), mit nummeriertem Fallback für den Restfall gleicher Name
und gleiches Fach.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
128 lines
5.2 KiB
C#
128 lines
5.2 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Desktop.ViewModels.Planning;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Desktop.Tests;
|
|
|
|
public sealed class TimetableSlotDialogViewModelTests
|
|
{
|
|
private static SchoolYearService SchoolYear() => new();
|
|
|
|
[Fact]
|
|
public void Save_OhneAusgewaehlteGruppe_SetztFehlerUndSpeichertNicht()
|
|
{
|
|
var slots = new FakeTimetableSlots();
|
|
var groups = new FakeGroups([]);
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, new FakeSubjects([]), SchoolYear(), DayOfWeek.Monday, 1, null);
|
|
|
|
vm.SaveCommand.Execute(null);
|
|
|
|
Assert.Null(vm.Result);
|
|
Assert.NotEqual("", vm.GroupError);
|
|
}
|
|
|
|
[Fact]
|
|
public void Save_MitAusgewaehlterGruppe_LegtNeuenSlotAn()
|
|
{
|
|
var group = new LearningGroup { Name = "Q1 Chemie" };
|
|
var slots = new FakeTimetableSlots();
|
|
var groups = new FakeGroups([group]);
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, new FakeSubjects([]), SchoolYear(), DayOfWeek.Monday, 1, null)
|
|
{
|
|
SelectedGroupName = "Q1 Chemie", Room = "R204",
|
|
};
|
|
|
|
vm.SaveCommand.Execute(null);
|
|
|
|
Assert.NotNull(vm.Result);
|
|
Assert.Equal(group.Id, vm.Result!.GroupId);
|
|
Assert.Equal("R204", vm.Result.Room);
|
|
Assert.Single(slots.GetAll());
|
|
}
|
|
|
|
[Fact]
|
|
public void Save_BelegteStunde_ZeigtFreundlicheFehlermeldungStattAbsturz()
|
|
{
|
|
var groupA = new LearningGroup { Name = "Q1 Chemie" };
|
|
var groupB = new LearningGroup { Name = "Q1 Physik" };
|
|
var slots = new FakeTimetableSlots();
|
|
slots.Add(new TimetableSlot { GroupId = groupA.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 });
|
|
var groups = new FakeGroups([groupA, groupB]);
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, new FakeSubjects([]), SchoolYear(), DayOfWeek.Monday, 1, null)
|
|
{
|
|
SelectedGroupName = "Q1 Physik",
|
|
};
|
|
|
|
vm.SaveCommand.Execute(null);
|
|
|
|
Assert.Null(vm.Result);
|
|
Assert.Equal("Diese Stunde ist bereits belegt.", vm.GroupError);
|
|
}
|
|
|
|
[Fact]
|
|
public void Delete_BeimBearbeitenEinesVorhandenenSlots_EntferntIhn()
|
|
{
|
|
var group = new LearningGroup { Name = "Q1 Chemie" };
|
|
var slot = new TimetableSlot { GroupId = group.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 };
|
|
var slots = new FakeTimetableSlots();
|
|
slots.Add(slot);
|
|
var groups = new FakeGroups([group]);
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, new FakeSubjects([]), SchoolYear(), DayOfWeek.Monday, 1, slot);
|
|
|
|
vm.DeleteCommand.Execute(null);
|
|
|
|
Assert.True(vm.Deleted);
|
|
Assert.Empty(slots.GetAll());
|
|
}
|
|
|
|
/// Regressionstest für den vom Nutzer gemeldeten Absturz: dieselbe Klasse ("10c") wird in
|
|
/// zwei Fächern unterrichtet und hat deshalb zwei LearningGroup-Datensätze mit demselben
|
|
/// Namen — das Anlegen der Gruppenliste darf dabei nicht mehr mit einer ArgumentException
|
|
/// abstürzen, und beide Gruppen müssen über eindeutige, unterscheidbare Labels wählbar bleiben.
|
|
[Fact]
|
|
public void KonstruktorMitGleichnamigenGruppenInVerschiedenenFaechern_StuerztNichtAbUndBleibtUnterscheidbar()
|
|
{
|
|
var chemie = new Subject { Name = "Chemie" };
|
|
var mathe = new Subject { Name = "Mathematik" };
|
|
var groupChemie = new LearningGroup { Name = "10c", SubjectId = chemie.Id };
|
|
var groupMathe = new LearningGroup { Name = "10c", SubjectId = mathe.Id };
|
|
var groups = new FakeGroups([groupChemie, groupMathe]);
|
|
var subjects = new FakeSubjects([chemie, mathe]);
|
|
var slots = new FakeTimetableSlots();
|
|
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, subjects, SchoolYear(), DayOfWeek.Monday, 1, null);
|
|
|
|
Assert.Equal(2, vm.GroupOptions.Length);
|
|
Assert.Equal(vm.GroupOptions.Distinct().Count(), vm.GroupOptions.Length);
|
|
Assert.Contains("10c (Chemie)", vm.GroupOptions);
|
|
Assert.Contains("10c (Mathematik)", vm.GroupOptions);
|
|
|
|
vm.SelectedGroupName = "10c (Mathematik)";
|
|
vm.SaveCommand.Execute(null);
|
|
|
|
Assert.NotNull(vm.Result);
|
|
Assert.Equal(groupMathe.Id, vm.Result!.GroupId);
|
|
}
|
|
|
|
/// Beim Bearbeiten eines bestehenden Slots muss das vorausgewählte Label zur tatsächlich
|
|
/// zugewiesenen Gruppe passen, auch wenn deren Name mehrdeutig ist.
|
|
[Fact]
|
|
public void KonstruktorBeimBearbeiten_WaehltDasLabelDerTatsaechlichZugewiesenenGruppeVor()
|
|
{
|
|
var chemie = new Subject { Name = "Chemie" };
|
|
var mathe = new Subject { Name = "Mathematik" };
|
|
var groupChemie = new LearningGroup { Name = "10c", SubjectId = chemie.Id };
|
|
var groupMathe = new LearningGroup { Name = "10c", SubjectId = mathe.Id };
|
|
var groups = new FakeGroups([groupChemie, groupMathe]);
|
|
var subjects = new FakeSubjects([chemie, mathe]);
|
|
var slot = new TimetableSlot { GroupId = groupChemie.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 };
|
|
var slots = new FakeTimetableSlots();
|
|
slots.Add(slot);
|
|
|
|
var vm = new TimetableSlotDialogViewModel(slots, groups, subjects, SchoolYear(), DayOfWeek.Monday, 1, slot);
|
|
|
|
Assert.Equal("10c (Chemie)", vm.SelectedGroupName);
|
|
}
|
|
}
|