168 lines
9.3 KiB
C#
168 lines
9.3 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Groups;
|
|
using LehrerApp.WebUntis;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Desktop.Tests;
|
|
|
|
public sealed class WebUntisHomeworkComparisonViewModelTests
|
|
{
|
|
[Theory]
|
|
[InlineData("Fehlende HA", "Buch vergessen", "Negativ", true)]
|
|
[InlineData("Sonstiges", "HA nicht dabei", "Negativ", false)]
|
|
[InlineData(null, "HA nicht dabei", "Negativ", true)]
|
|
[InlineData("Hausaufgaben fehlen", null, "Negativ", true)]
|
|
[InlineData("Verhalten", "Schüler war unruhig", "Negativ", false)]
|
|
[InlineData("Hausaufgaben", "HA gemacht", "Positiv", false)]
|
|
[InlineData("Sonstiges", "Schach gespielt", "Negativ", false)]
|
|
public void IsMissingHomeworkEntry_ErkenntAuchDasWebUntisKuerzel(
|
|
string? category, string? entryText, string group, bool expected)
|
|
{
|
|
var entry = new UntisClassRegisterEventDto("10c", 20260925, "Che", "Gerste Amelia",
|
|
category, group, entryText);
|
|
|
|
Assert.Equal(expected, WebUntisHomeworkComparisonViewModel.IsMissingHomeworkEntry(entry));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Load_ZeigtFehlendeHaAuchOhneHausaufgabeImFreitext()
|
|
{
|
|
const string report = "Klasse\tDatum\tFach\tName\tBenutzer\tEintragskategorie\tKategoriegruppe\tText\r\n" +
|
|
"10c\t25.09.26\tChe\tGerste Amelia\tlehrkraft\tFehlende HA\tNegativ\tChe: Buch vergessen\r\n" +
|
|
"10c\t25.09.26\tChe\tGerste Amelia\tlehrkraft\tHausaufgaben\tPositiv\tChe: alles erledigt\r\n";
|
|
var handler = new QueueHandler(
|
|
Json("{\"result\":{\"sessionId\":\"s\"}}"),
|
|
Json("{\"result\":[{\"id\":1,\"name\":\"2026/27\",\"startDate\":20260801,\"endDate\":20270731}]}"),
|
|
Json("{\"data\":{\"finished\":true,\"error\":false," +
|
|
"\"reportParams\":\"get=rpt.tmp&name=ClassregEventPerStudent&format=csv\"}}"),
|
|
new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new ByteArrayContent(Encoding.UTF8.GetBytes(report)),
|
|
});
|
|
var settings = TestSupport.BuildWebUntisSettingsService();
|
|
var credentials = new WebUntisCredentials("schule", "arche.webuntis.com", "lehrkraft", "geheim");
|
|
settings.SetApiCredentials(credentials);
|
|
await using var untis = new WebUntisIntegrationService(new HttpClient(handler), settings);
|
|
await untis.ConnectAsync(credentials);
|
|
var vm = new WebUntisHomeworkComparisonViewModel(untis, new FakeStudents([]),
|
|
new FakeGroups([]), new FakeSubjects([]), new FakeMemberships([]),
|
|
new FakeSessions([]), new FakeEntries(), new SchoolYearService())
|
|
{
|
|
StartDate = new DateTimeOffset(2026, 9, 24, 12, 0, 0, TimeSpan.Zero),
|
|
EndDate = new DateTimeOffset(2026, 9, 26, 12, 0, 0, TimeSpan.Zero),
|
|
};
|
|
|
|
await vm.LoadCommand.ExecuteAsync(null);
|
|
|
|
Assert.Equal("Gerste Amelia", Assert.Single(vm.Rows).UntisStudentName);
|
|
Assert.Contains("1 passende Einträge von 2", vm.Status);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoadUndApply_TrenntBestehendenStatus_ZielstatusUndLokaleEintraege()
|
|
{
|
|
const string report = "Klasse\tDatum\tFach\tName\tBenutzer\tEintragskategorie\tKategoriegruppe\tText\r\n" +
|
|
"10c\t25.09.26\tChe\tGerste Amelia\tlehrkraft\tFehlende HA\tNegativ\tChe: nicht gemacht\r\n" +
|
|
"10c\t25.09.26\tChe\tMuster Ben\tlehrkraft\tFehlende HA\tNegativ\tChe: nicht gemacht\r\n";
|
|
var handler = new QueueHandler(
|
|
Json("{\"result\":{\"sessionId\":\"s\"}}"),
|
|
Json("{\"result\":[{\"id\":1,\"name\":\"2026/27\",\"startDate\":20260801,\"endDate\":20270731}]}"),
|
|
Json("{\"data\":{\"finished\":true,\"error\":false," +
|
|
"\"reportParams\":\"get=rpt.tmp&name=ClassregEventPerStudent&format=csv\"}}"),
|
|
new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new ByteArrayContent(Encoding.UTF8.GetBytes(report)),
|
|
});
|
|
var settings = TestSupport.BuildWebUntisSettingsService();
|
|
var credentials = new WebUntisCredentials("schule", "arche.webuntis.com", "lehrkraft", "geheim");
|
|
settings.SetApiCredentials(credentials);
|
|
await using var untis = new WebUntisIntegrationService(new HttpClient(handler), settings);
|
|
await untis.ConnectAsync(credentials);
|
|
|
|
var date = new DateOnly(2026, 9, 25);
|
|
var schoolYear = new SchoolYearService();
|
|
var chemistry = new Subject { Name = "Chemie", ShortName = "Che" };
|
|
var biology = new Subject { Name = "Biologie", ShortName = "Bio" };
|
|
var classGroup = new LearningGroup { Name = "10c", Type = GroupType.Class,
|
|
SchoolYear = schoolYear.CurrentSchoolYear(date) };
|
|
var chemistryGroup = new LearningGroup { Name = "Chemie 10c", Type = GroupType.Course,
|
|
SubjectId = chemistry.Id, SchoolYear = classGroup.SchoolYear };
|
|
var biologyGroup = new LearningGroup { Name = "Biologie 10c", Type = GroupType.Course,
|
|
SubjectId = biology.Id, SchoolYear = classGroup.SchoolYear };
|
|
var amelia = new Student { FirstName = "Amelia", LastName = "Gerste" };
|
|
var ben = new Student { FirstName = "Ben", LastName = "Muster" };
|
|
var carl = new Student { FirstName = "Carl", LastName = "Beispiel" };
|
|
var chemistrySession = new ParticipationSession { GroupId = chemistryGroup.Id, Date = date };
|
|
var biologySession = new ParticipationSession { GroupId = biologyGroup.Id, Date = date };
|
|
var memberships = new FakeMemberships([
|
|
new GroupMembership { StudentId = amelia.Id, GroupId = chemistryGroup.Id },
|
|
new GroupMembership { StudentId = amelia.Id, GroupId = biologyGroup.Id },
|
|
new GroupMembership { StudentId = ben.Id, GroupId = chemistryGroup.Id },
|
|
new GroupMembership { StudentId = carl.Id, GroupId = chemistryGroup.Id },
|
|
]);
|
|
var participation = new FakeEntries();
|
|
participation.Add(new ParticipationEntry { SessionId = chemistrySession.Id, StudentId = amelia.Id,
|
|
Homework = HomeworkStatus.MissingOpen, HomeworkMissing = true });
|
|
participation.Add(new ParticipationEntry { SessionId = biologySession.Id, StudentId = amelia.Id,
|
|
Homework = HomeworkStatus.PartiallyCompleted, HomeworkMissing = true });
|
|
participation.Add(new ParticipationEntry { SessionId = chemistrySession.Id, StudentId = carl.Id,
|
|
Homework = HomeworkStatus.MissingOverdue, HomeworkMissing = true });
|
|
|
|
var vm = new WebUntisHomeworkComparisonViewModel(untis,
|
|
new FakeStudents([amelia, ben, carl]),
|
|
new FakeGroups([classGroup, chemistryGroup, biologyGroup]),
|
|
new FakeSubjects([chemistry, biology]), memberships,
|
|
new FakeSessions([chemistrySession, biologySession]), participation, schoolYear)
|
|
{
|
|
StartDate = new DateTimeOffset(2026, 9, 24, 12, 0, 0, TimeSpan.Zero),
|
|
EndDate = new DateTimeOffset(2026, 9, 26, 12, 0, 0, TimeSpan.Zero),
|
|
};
|
|
|
|
await vm.LoadCommand.ExecuteAsync(null);
|
|
|
|
var existing = Assert.Single(vm.Rows, r => r.AssignedStudent?.Id == amelia.Id);
|
|
Assert.False(existing.Selected);
|
|
Assert.Equal(HomeworkDisplay.Label(HomeworkStatus.MissingOpen), existing.LocalStatus);
|
|
Assert.Equal(HomeworkDisplay.Label(HomeworkStatus.MissingOpen), existing.SelectedStatusName);
|
|
var newRow = Assert.Single(vm.Rows, r => r.AssignedStudent?.Id == ben.Id);
|
|
Assert.True(newRow.Selected);
|
|
Assert.Equal("Noch kein Status erfasst", newRow.LocalStatus);
|
|
Assert.Equal(2, vm.LocalOnlyRows.Count);
|
|
Assert.Contains(vm.LocalOnlyRows, r => r.StudentName == amelia.FullName && r.GroupName == biologyGroup.Name);
|
|
Assert.Contains(vm.LocalOnlyRows, r => r.StudentName == carl.FullName && r.GroupName == chemistryGroup.Name);
|
|
|
|
newRow.AssignedStudent = carl;
|
|
Assert.Single(vm.LocalOnlyRows);
|
|
Assert.False(newRow.Selected);
|
|
newRow.AssignedStudent = ben;
|
|
Assert.Equal(2, vm.LocalOnlyRows.Count);
|
|
newRow.SelectedStatusName = HomeworkDisplay.Label(HomeworkStatus.SubmittedLate);
|
|
vm.ApplyCommand.Execute(null);
|
|
|
|
var saved = participation.GetBySessionAndStudent(chemistrySession.Id, ben.Id);
|
|
Assert.Equal(HomeworkStatus.SubmittedLate, saved?.Homework);
|
|
Assert.False(saved?.HomeworkMissing);
|
|
Assert.Equal(HomeworkDisplay.Label(HomeworkStatus.SubmittedLate), newRow.LocalStatus);
|
|
Assert.False(newRow.Selected);
|
|
Assert.Equal(HomeworkStatus.MissingOpen,
|
|
participation.GetBySessionAndStudent(chemistrySession.Id, amelia.Id)?.Homework);
|
|
}
|
|
|
|
private static HttpResponseMessage Json(string json) => new(HttpStatusCode.OK)
|
|
{
|
|
Content = new StringContent(json, Encoding.UTF8, "application/json"),
|
|
};
|
|
|
|
private sealed class QueueHandler(params HttpResponseMessage[] responses) : HttpMessageHandler
|
|
{
|
|
private readonly Queue<HttpResponseMessage> _responses = new(responses);
|
|
|
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
|
|
CancellationToken cancellationToken) => Task.FromResult(_responses.Dequeue());
|
|
}
|
|
}
|