Files
LehrerApp/LehrerApp.Desktop.Tests/WebUntisTimetableImportTests.cs
T
2026-10-06 13:29:05 +02:00

112 lines
5.0 KiB
C#

using System.Net;
using System.Text;
using LehrerApp.Core.Models;
using LehrerApp.Desktop.Services;
using LehrerApp.Desktop.ViewModels.Planning;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class WebUntisTimetableImportTests
{
[Fact]
public async Task Load_IsReadOnly_AndSaveUpdatesOnlyLessonIdsByDefault()
{
await using var fixture = new Fixture();
await fixture.Vm.LoadCommand.ExecuteAsync(null);
Assert.Null(fixture.Group.WebUntisLessonId);
Assert.Null(fixture.Settings.TeacherUntisId);
Assert.Single(fixture.Slots.GetAll());
Assert.Equal(38926, Assert.Single(fixture.Vm.Rows).LessonId);
fixture.Vm.SaveCommand.Execute(null);
Assert.True(fixture.Vm.Saved);
Assert.Equal(38926, fixture.Group.WebUntisLessonId);
Assert.Equal(DayOfWeek.Friday, Assert.Single(fixture.Slots.GetAll()).Weekday);
}
[Theory]
[InlineData(false, 2)]
[InlineData(true, 1)]
public async Task TimetableUpdates_OnlyRemoveOldSlotsWhenExplicitlySelected(bool replace, int expected)
{
await using var fixture = new Fixture();
await fixture.Vm.LoadCommand.ExecuteAsync(null);
fixture.Vm.UpdateLessonIds = false;
fixture.Vm.UpdateTimetable = true;
fixture.Vm.ReplaceTimetable = replace;
fixture.Vm.SaveCommand.Execute(null);
Assert.True(fixture.Vm.Saved);
Assert.Null(fixture.Group.WebUntisLessonId);
Assert.Equal(expected, fixture.Slots.GetAll().Count);
Assert.Contains(fixture.Slots.GetAll(), slot => slot.Weekday == DayOfWeek.Monday);
}
[Fact]
public async Task ConflictingLessonIds_BlockAllChanges_UntilExcluded()
{
await using var fixture = new Fixture();
await fixture.Vm.LoadCommand.ExecuteAsync(null);
fixture.Vm.Rows.Add(new WebUntisTimetableRow
{
Weekday = DayOfWeek.Tuesday, PeriodNumber = 1, TimeLabel = "07:50", UntisLabel = "7a",
SuggestedGroupName = "7a", LessonId = 999, SelectedGroup = fixture.Vm.Rows[0].SelectedGroup,
});
fixture.Vm.UpdateTimetable = true;
fixture.Vm.SaveCommand.Execute(null);
Assert.False(fixture.Vm.Saved);
Assert.Null(fixture.Group.WebUntisLessonId);
Assert.Single(fixture.Slots.GetAll());
Assert.Contains("Mehrere Unterrichtsnummern", fixture.Vm.Status);
fixture.Vm.Rows[1].ApplyLessonId = false;
fixture.Vm.SaveCommand.Execute(null);
Assert.True(fixture.Vm.Saved);
Assert.Equal(38926, fixture.Group.WebUntisLessonId);
}
[Fact]
public async Task SaveWithoutLoadedWeek_DoesNotClearTimetable()
{
await using var fixture = new Fixture();
fixture.Vm.UpdateTimetable = fixture.Vm.ReplaceTimetable = true;
fixture.Vm.SaveCommand.Execute(null);
Assert.False(fixture.Vm.Saved);
Assert.Single(fixture.Slots.GetAll());
}
private sealed class Fixture : IAsyncDisposable
{
public LearningGroup Group { get; } = new() { Name = "7a" };
public FakeTimetableSlots Slots { get; } = new();
public WebUntisSettingsService Settings { get; } = TestSupport.BuildWebUntisSettingsService();
private readonly WebUntisIntegrationService _service;
public WebUntisTimetableImportViewModel Vm { get; }
public Fixture()
{
Settings.SetApiCredentials(new("school", "example.webuntis.com", "teacher", "password"));
_service = new(new HttpClient(new Handler()), Settings);
Slots.Add(new() { Weekday = DayOfWeek.Friday, PeriodNumber = 4, GroupId = Group.Id });
Vm = new(_service, Settings, Slots, new FakeGroups([Group]))
{
SelectedTeacher = new(89, "Teacher", null, null, null, true, []),
WeekDate = new DateTimeOffset(2026, 10, 5, 0, 0, 0, TimeSpan.Zero),
};
}
public ValueTask DisposeAsync() => _service.DisposeAsync();
}
private sealed class Handler : HttpMessageHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token)
{
var body = request.Content is null ? "" : await request.Content.ReadAsStringAsync(token);
var json = request.RequestUri!.AbsolutePath.Contains("weekly/data")
? """{"data":{"result":{"data":{"elementPeriods":{"89":[{"id":2013854,"lessonId":38926},{"id":2013854,"lessonId":38926}]}}}}}"""
: body.Contains("authenticate") ? """{"result":{"sessionId":"s"}}"""
: body.Contains("getTimetable") ? """{"result":[{"id":2013854,"date":20261005,"startTime":750,"endTime":835,"kl":[{"id":4,"name":"7a"}],"te":[],"su":[],"ro":[]}]}"""
: body.Contains("getTimegridUnits") ? """{"result":[{"day":1,"timeUnits":[{"name":"1","startTime":750,"endTime":835}]}]}"""
: """{"result":{}}""";
return new(HttpStatusCode.OK) { Content = new StringContent(json, Encoding.UTF8, "application/json") };
}
}
}