Files
LehrerApp/LehrerApp.Desktop.Tests/QuickInputViewModelTests.cs
adminandClaude Sonnet 5 1215d4ac22
CI / build-and-test (push) Canceled after 0s
Tagesflagge im Sitzplan, Leistungsüberblick mit Zielnoten-Rechner
- Mitarbeit: Tagesflagge (👑 Spitzentag / 😴 Schlaftag /  Schlechter Tag)
  je Schüler und Sitzung. Primär im Sitzplatz-Dialog (⇧1/2/3, ⇧X) mit
  Badge auf der Sitzplatz-Kachel; Fallback in der Schnelleingabe für
  Lerngruppen ohne Sitzplan.
- Noten: neuer Dialog "Überblick" in der Notenübersicht zeigt Klausuren,
  Mitarbeit- und sonstige Noten eines Schülers samt berechneter
  Zeugnisnote. Zielnoten-Rechner (ReportGradeTargetCalculator) beantwortet
  "was brauche ich noch für Note X", ein Was-wäre-wenn-Rechner simuliert
  eine zusätzliche Klausurnote. Bewerter-/Schülermodus per Umschalter im
  selben Fenster — Bewertermodus zeigt zusätzlich Kursdurchschnitt je
  Klausur und erlaubt das Bearbeiten von Mitarbeit-/Sonstige-Noten.
  Klausurverlauf als Balken-Sparkline wie die bestehende Notenentwicklung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 11:43:47 +02:00

166 lines
6.1 KiB
C#

using LehrerApp.Core.Models;
using LehrerApp.Desktop.ViewModels.Groups;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class QuickInputViewModelTests
{
[Theory]
[InlineData(AttendanceStatus.Late, false, "Verspätet", "V")]
[InlineData(AttendanceStatus.SignificantlyLate, false, "Erheblich verspätet", "V!")]
[InlineData(AttendanceStatus.LeftDuringClass, true, "Während des Unterrichts abgängig", "A")]
[InlineData(AttendanceStatus.LearningIsland, true, "Lerninsel", "L")]
[InlineData(AttendanceStatus.Suspended, true, "Suspendiert", "S")]
public void ZusaetzlicheAnwesenheitsstatus_HabenAnzeigeUndPassendeAbwesenheitswertung(
AttendanceStatus status, bool isAbsent, string label, string symbol)
{
var row = new ParticipationStudentRow(Guid.NewGuid(), "Anna",
new ParticipationEntry { Attendance = status }, [], []);
Assert.Equal(isAbsent, row.IsAbsent);
Assert.Equal(label, row.AttendanceTooltip);
Assert.Equal(symbol, row.AttendanceLabel);
Assert.False(string.IsNullOrWhiteSpace(AttendanceDisplay.Color(status)));
}
[Fact]
public void ZurueckZuVorherigemSchueler_ZeigtBereitsGesetzteBewertung()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "mitarbeit", Label = "Mitarbeit" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
new(Guid.NewGuid(), "Ben", new ParticipationEntry(), aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.SetRatingByNumber(4); // Scale5, 4. Stufe -> Rohwert 1 ("+"), Anna bewerten
vm.NextStudent(); // zu Ben
vm.PreviousStudent(); // zurück zu Anna
Assert.Equal(1, vm.AspectRows[0].Value);
}
[Fact]
public void AnwesenderSchueler_CurrentStudentIsAbsent_IstFalse()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "a", Label = "A" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry { Attendance = AttendanceStatus.Present }, aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
Assert.False(vm.CurrentStudentIsAbsent);
Assert.Equal(1.0, vm.CurrentStudentContentOpacity);
}
[Fact]
public void AbwesenderSchueler_CurrentStudentIsAbsent_IstTrueUndGedimmt()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "a", Label = "A" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
new(Guid.NewGuid(), "Ben", new ParticipationEntry { Attendance = AttendanceStatus.Unexcused }, aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.NextStudent(); // zu Ben, unentschuldigt abwesend
Assert.True(vm.CurrentStudentIsAbsent);
Assert.Equal("Krank, unentschuldigt", vm.CurrentStudentAttendanceLabel);
Assert.Equal(0.4, vm.CurrentStudentContentOpacity);
}
[Fact]
public void ClearRating_SetztVersehentlichGesetzteBewertungAufNichtBewertetZurueck()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "quality", Label = "Qualität" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.SetRatingByNumber(4); // aus Versehen eine Note für Qualität vergeben
vm.ClearRating();
Assert.Null(vm.AspectRows[0].Value);
Assert.Null(rows[0].GetRating("quality"));
}
[Fact]
public void SetDayHighlight_SpeichertAufDerZeileUndAktualisiertDieAnzeige()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "quality", Label = "Qualität" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.SetDayHighlight(DayHighlightKind.Standout);
Assert.Equal(DayHighlightKind.Standout, rows[0].DayHighlight);
Assert.Equal("👑", vm.CurrentStudentDayHighlightSymbol);
Assert.Equal("Spitzentag", vm.CurrentStudentDayHighlightLabel);
}
[Fact]
public void ZurueckZuVorherigemSchueler_ZeigtDessenTagesflaggeWiederAn()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "quality", Label = "Qualität" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
new(Guid.NewGuid(), "Ben", new ParticipationEntry(), aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.SetDayHighlight(DayHighlightKind.Sleepy); // Anna
vm.NextStudent(); // zu Ben, keine Flagge
vm.PreviousStudent(); // zurück zu Anna
Assert.Equal(DayHighlightKind.Sleepy, vm.CurrentStudentDayHighlight);
}
[Fact]
public void VorherigerAspekt_SpringtRueckwaertsMitUmlauf()
{
var aspects = new List<AspectColumnDef>
{
new(new ParticipationAspect { Key = "a", Label = "A" }),
new(new ParticipationAspect { Key = "b", Label = "B" }),
};
var rows = new List<ParticipationStudentRow>
{
new(Guid.NewGuid(), "Anna", new ParticipationEntry(), aspects, []),
};
var vm = new QuickInputViewModel(rows, aspects);
vm.PreviousAspect(); // von Index 0 rückwärts -> letzter Aspekt (Umlauf)
Assert.Equal(1, vm.AspectIndex);
}
}