Zeigt die Fälligkeit der vier bestehenden, manuell ausgelösten WebUntis-Abgleiche (Fehlzeiten je Lerngruppe, offene Stunden, Klassenbuch-, Hausaufgabenabgleich) in einem neuen Hub-Fenster, ohne selbst WebUntis anzufragen - nur gespeicherte Zeitstempel werden ausgewertet. Konsolidiert die bisher verstreuten Einstiegspunkte (Sidebar-Button, Dashboard-Buttons) in ein neues WebUntis-Menü plus einen kompakten Gesundheits-Indikator auf dem Dashboard. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,7 +74,8 @@ public sealed class DashboardViewModelTests
|
||||
slots ?? new FakeTimetableSlots(), periodSchedule ?? NewPeriodSchedule(),
|
||||
new AttendanceBalanceService(), new SchoolYearService(), dashboardSettings ?? NewDashboardSettings(),
|
||||
schoolHolidays ?? new FakeSchoolHolidays(), new PublicHolidayService(), NewCalendarSettings(),
|
||||
substitutions ?? new FakeSubstitutionEntries(), timeEntries ?? new FakeTimeEntries(), annualPlanEvents);
|
||||
substitutions ?? new FakeSubstitutionEntries(), timeEntries ?? new FakeTimeEntries(),
|
||||
TestSupport.BuildUntisHubService(), TestSupport.BuildWebUntisIntegrationService(), annualPlanEvents);
|
||||
}
|
||||
|
||||
/// Montag einer Woche, die garantiert in der Zukunft liegt und innerhalb der
|
||||
|
||||
@@ -39,6 +39,14 @@ public static class TestSupport
|
||||
return new WebUntisSettingsService(tempPath);
|
||||
}
|
||||
|
||||
/// Nicht konfiguriert (kein API-Login hinterlegt) - genügt für Tests, die nur den Konstruktor
|
||||
/// bedienen müssen und keinen echten WebUntis-Zugriff auslösen.
|
||||
public static WebUntisIntegrationService BuildWebUntisIntegrationService() =>
|
||||
new(new HttpClient(), BuildWebUntisSettingsService());
|
||||
|
||||
public static UntisHubService BuildUntisHubService(List<LearningGroup>? groups = null) =>
|
||||
new(new FakeGroups(groups ?? []), new FakeUntisHubJobStates(), new SchoolYearService());
|
||||
|
||||
/// Analog zu den übrigen dateibasierten Feed-Einstellungen: eigenes Temp-Verzeichnis.
|
||||
public static AnnualPlanSettingsService BuildAnnualPlanSettingsService()
|
||||
{
|
||||
@@ -525,6 +533,19 @@ public class FakeUntisCacheFetchStates : IUntisCacheFetchStateRepository
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeUntisHubJobStates : IUntisHubJobStateRepository
|
||||
{
|
||||
private readonly List<UntisHubJobState> _all = [];
|
||||
public UntisHubJobState? Get(UntisHubJobKind kind, Guid? groupId) =>
|
||||
_all.FirstOrDefault(s => s.Kind == kind && s.GroupId == groupId);
|
||||
public List<UntisHubJobState> GetAll() => _all.ToList();
|
||||
public void Save(UntisHubJobState state)
|
||||
{
|
||||
_all.RemoveAll(s => s.Kind == state.Kind && s.GroupId == state.GroupId);
|
||||
_all.Add(state);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeWorkTasks : IWorkTaskRepository
|
||||
{
|
||||
private readonly List<WorkTask> _all = [];
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
public sealed class UntisHubServiceTests
|
||||
{
|
||||
private static readonly DateTime UtcNow = new(2026, 9, 10, 8, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private static LearningGroup Group(string name, int? webUntisLessonId, bool isActive = true) =>
|
||||
new() { Name = name, WebUntisLessonId = webUntisLessonId, IsActive = isActive };
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_ProGruppeMitLessonId_ZweiFehlzeitenzeilenPlusDreiGlobaleZeilen()
|
||||
{
|
||||
var group = Group("9a", 42);
|
||||
|
||||
var rows = UntisHubService.BuildRows([group], [], UtcNow);
|
||||
|
||||
Assert.Equal(5, rows.Count);
|
||||
Assert.Equal(2, rows.Count(r => r.GroupId == group.Id));
|
||||
Assert.Contains(rows, r => r.Kind == UntisHubJobKind.FehlzeitenKurz && r.GroupId == group.Id);
|
||||
Assert.Contains(rows, r => r.Kind == UntisHubJobKind.FehlzeitenLang && r.GroupId == group.Id);
|
||||
Assert.Contains(rows, r => r.Kind == UntisHubJobKind.OffenePeriods && r.GroupId == null);
|
||||
Assert.Contains(rows, r => r.Kind == UntisHubJobKind.Klassenbuchabgleich && r.GroupId == null);
|
||||
Assert.Contains(rows, r => r.Kind == UntisHubJobKind.Hausaufgabenabgleich && r.GroupId == null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_NieGeprueft_GiltAlsUeberfaellig()
|
||||
{
|
||||
var rows = UntisHubService.BuildRows([], [], UtcNow);
|
||||
|
||||
Assert.All(rows, r => Assert.Equal(UntisHubDueState.Overdue, r.DueState));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_FehlzeitenKurzVorSechsTagen_GiltAlsOk()
|
||||
{
|
||||
var group = Group("9a", 42);
|
||||
var state = new UntisHubJobState
|
||||
{
|
||||
Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-6),
|
||||
};
|
||||
|
||||
var rows = UntisHubService.BuildRows([group], [state], UtcNow);
|
||||
|
||||
var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz);
|
||||
Assert.Equal(UntisHubDueState.Ok, row.DueState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_FehlzeitenKurzVorSechzehnTagen_GiltAlsFaellig()
|
||||
{
|
||||
var group = Group("9a", 42);
|
||||
var state = new UntisHubJobState
|
||||
{
|
||||
Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-16),
|
||||
};
|
||||
|
||||
var rows = UntisHubService.BuildRows([group], [state], UtcNow);
|
||||
|
||||
var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz);
|
||||
Assert.Equal(UntisHubDueState.Due, row.DueState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_FehlzeitenKurzVorZweiundzwanzigTagen_GiltAlsUeberfaellig()
|
||||
{
|
||||
var group = Group("9a", 42);
|
||||
var state = new UntisHubJobState
|
||||
{
|
||||
Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = UtcNow.AddDays(-22),
|
||||
};
|
||||
|
||||
var rows = UntisHubService.BuildRows([group], [state], UtcNow);
|
||||
|
||||
var row = rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz);
|
||||
Assert.Equal(UntisHubDueState.Overdue, row.DueState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_FehlzeitenLangHatDeutlichLaengereKadenzAlsKurz()
|
||||
{
|
||||
var group = Group("9a", 42);
|
||||
var lastRunAt = UtcNow.AddDays(-40);
|
||||
var states = new List<UntisHubJobState>
|
||||
{
|
||||
new() { Kind = UntisHubJobKind.FehlzeitenKurz, GroupId = group.Id, LastRunAt = lastRunAt },
|
||||
new() { Kind = UntisHubJobKind.FehlzeitenLang, GroupId = group.Id, LastRunAt = lastRunAt },
|
||||
};
|
||||
|
||||
var rows = UntisHubService.BuildRows([group], states, UtcNow);
|
||||
|
||||
Assert.Equal(UntisHubDueState.Overdue, rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenKurz).DueState);
|
||||
Assert.Equal(UntisHubDueState.Ok, rows.Single(r => r.Kind == UntisHubJobKind.FehlzeitenLang).DueState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildRows_GruppeOhneWebUntisLessonId_WirdVonAufrufseiteAusgeschlossen()
|
||||
{
|
||||
// GetRows() filtert vorab auf WebUntisLessonId != null (siehe UntisHubService.GetRows) -
|
||||
// BuildRows selbst bekommt bereits nur die eligible-Gruppen übergeben.
|
||||
var eligible = new List<LearningGroup> { Group("9a", 42) };
|
||||
|
||||
var rows = UntisHubService.BuildRows(eligible, [], UtcNow);
|
||||
|
||||
Assert.Equal(2, rows.Count(r => r.GroupId != null));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user