This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using LehrerApp.Core.AiPlanning;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
@@ -15,6 +18,106 @@ public sealed class AiPlanningServiceTests
|
||||
FakeCompetencyDomains competencyDomains, FakeAlternativeLessonPaths altPaths) =>
|
||||
new(new HttpClient(), lessons, groups, subjects, competencyDomains, altPaths);
|
||||
|
||||
[Fact]
|
||||
public void ParsePlanningLessons_AkzeptiertNormaleAntwortUndDeutschesDatum()
|
||||
{
|
||||
const string json = """
|
||||
{"lessons":[{"id":null,"date":"15.09.2026","lessonNumber":2,"topic":"Redox","startTime":"08:35","phases":[]}],"summary":"ok"}
|
||||
""";
|
||||
|
||||
var lesson = Assert.Single(AiPlanningService.ParsePlanningLessons(json));
|
||||
|
||||
Assert.Equal("Redox", lesson.Topic);
|
||||
Assert.Equal(new DateOnly(2026, 9, 15), lesson.Date);
|
||||
Assert.Equal(new TimeOnly(8, 35), lesson.StartTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParsePlanningLessons_AkzeptiertEinzelneMarkierteStunde()
|
||||
{
|
||||
const string json = """
|
||||
{"topic":"Nur diese Stunde","phases":[{"name":"Einstieg","durationMinutes":5,"activity":"Impuls","material":"Bild","shorthand":"UG"}]}
|
||||
""";
|
||||
|
||||
var lesson = Assert.Single(AiPlanningService.ParsePlanningLessons(json));
|
||||
|
||||
Assert.Equal("Nur diese Stunde", lesson.Topic);
|
||||
Assert.Single(lesson.Phases);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParsePlanningLessons_UngueltigeMarkierung_LiefertVerstaendlichenFehler()
|
||||
{
|
||||
var error = Assert.Throws<AiBackendException>(() =>
|
||||
AiPlanningService.ParsePlanningLessons("Hier kommt das JSON: { kaputt }"));
|
||||
|
||||
Assert.Contains("noch kein gültiges Stunden-JSON", error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequestPlanAsync_Backendfehler_BewahrtOriginalantwortFuerRettung()
|
||||
{
|
||||
const string body = """
|
||||
{"error":"Kein gültiges JSON.","rawResponse":"Vorspann\n{kaputt}"}
|
||||
""";
|
||||
var service = BuildWithResponse(HttpStatusCode.BadGateway, body);
|
||||
|
||||
var error = await Assert.ThrowsAsync<AiBackendException>(() =>
|
||||
service.RequestPlanAsync(new Unit(), "", "token"));
|
||||
|
||||
Assert.Equal("Vorspann\n{kaputt}", error.RawResponse);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequestPlanAsync_Typfehler_BewahrtEingebetteteOriginalantwortFuerRettung()
|
||||
{
|
||||
const string body = """
|
||||
{"lessons":[{"topic":"Test","date":"kein Datum"}],"rawResponse":"DIE ORIGINALANTWORT"}
|
||||
""";
|
||||
var service = BuildWithResponse(HttpStatusCode.OK, body);
|
||||
|
||||
var error = await Assert.ThrowsAsync<AiBackendException>(() =>
|
||||
service.RequestPlanAsync(new Unit(), "", "token"));
|
||||
|
||||
Assert.Equal("DIE ORIGINALANTWORT", error.RawResponse);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rettungsdialog_ImportiertMarkierteStundeAlsNeu()
|
||||
{
|
||||
var group = new LearningGroup();
|
||||
var unit = new Unit { GroupId = group.Id, Title = "T" };
|
||||
var lessons = new FakeLessons();
|
||||
var service = Build(lessons, new FakeGroups([group]), new FakeSubjects([]),
|
||||
new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
|
||||
var vm = new AiResponseRescueDialogViewModel(service, lessons, unit, "Rohantwort");
|
||||
|
||||
vm.ParseSelection("""{"topic":"Gerettete Stunde","phases":[]}""");
|
||||
vm.ImportAsNewCommand.Execute(null);
|
||||
|
||||
Assert.True(vm.Result);
|
||||
Assert.Equal("Gerettete Stunde", Assert.Single(lessons.GetByUnit(unit.Id)).Topic);
|
||||
}
|
||||
|
||||
private static AiPlanningService BuildWithResponse(HttpStatusCode status, string body)
|
||||
{
|
||||
var http = new HttpClient(new StaticResponseHandler(status, body))
|
||||
{
|
||||
BaseAddress = new Uri("https://example.invalid/"),
|
||||
};
|
||||
return new AiPlanningService(http, new FakeLessons(), new FakeGroups([]), new FakeSubjects([]),
|
||||
new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
|
||||
}
|
||||
|
||||
private sealed class StaticResponseHandler(HttpStatusCode status, string body) : HttpMessageHandler
|
||||
{
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
|
||||
CancellationToken cancellationToken) => Task.FromResult(new HttpResponseMessage(status)
|
||||
{
|
||||
Content = new StringContent(body, Encoding.UTF8, "application/json"),
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildContext_FuelltGruppenUndFachKontext()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user