KI-Backend: deutsches Datumsformat fixen, Fortschrittsanzeige + Nachfassen im Dialog
Live-Test lieferte JsonException: DateOnly/TimeOnly hatten keinen Converter fürs im Systemprompt dokumentierte deutsche Format (TT.MM.JJJJ/HH:mm), .NET nutzte stattdessen ISO 8601 in beide Richtungen. Neue Converter mit Fallback aufs allgemeine Parsen. AiAssistDialog: indeterminierter ProgressBar statt nur Text während der Anfrage. Neuer Button "Erneut anfragen" erlaubt Nachfassen mit geänderter Anweisung, ohne den Dialog neu zu starten — schickt die aktuell angehakten Vorschläge als Entwurfskontext mit (AiPlanningService.MergeDraft), damit die KI auf dem noch ungespeicherten Stand aufbaut. Side-by-side-Vergleich beider Entwürfe als 4.5.18 zurückgestellt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using LehrerApp.Core.AiPlanning;
|
||||
using LehrerApp.Desktop.Services;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Deckt den Bug ab, der beim ersten echten Test der KI-Unterstützung auftrat: .NETs
|
||||
/// DateOnly/TimeOnly haben standardmäßig ein ISO-JSON-Format ("yyyy-MM-dd"/"HH:mm:ss"), der
|
||||
/// KI-Wire-Vertrag dokumentiert aber deutsches Format ("TT.MM.JJJJ"/"HH:mm") — jede KI-Antwort im
|
||||
/// dokumentierten Format scheiterte deshalb mit einer JsonException beim Deserialisieren.
|
||||
/// </summary>
|
||||
public sealed class GermanDateTimeJsonConverterTests
|
||||
{
|
||||
private static readonly JsonSerializerOptions Options = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Converters = { new GermanDateOnlyJsonConverter(), new GermanTimeOnlyJsonConverter() },
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void DateOnly_SerialisiertAlsDeutschesFormat()
|
||||
{
|
||||
Assert.Equal("\"24.12.2026\"", JsonSerializer.Serialize(new DateOnly(2026, 12, 24), Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DateOnly_ParstDeutschesFormat()
|
||||
{
|
||||
Assert.Equal(new DateOnly(2026, 12, 24), JsonSerializer.Deserialize<DateOnly>("\"24.12.2026\"", Options));
|
||||
}
|
||||
|
||||
/// LLMs weichen erfahrungsgemäß gelegentlich vom im Prompt dokumentierten Format ab —
|
||||
/// ISO 8601 wird deshalb defensiv trotzdem akzeptiert statt hart zu scheitern.
|
||||
[Fact]
|
||||
public void DateOnly_FaelltBeiAbweichendemFormatAufAllgemeinesParsenZurueck()
|
||||
{
|
||||
Assert.Equal(new DateOnly(2026, 12, 24), JsonSerializer.Deserialize<DateOnly>("\"2026-12-24\"", Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TimeOnly_SerialisiertAlsHHmm()
|
||||
{
|
||||
Assert.Equal("\"14:30\"", JsonSerializer.Serialize(new TimeOnly(14, 30), Options));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TimeOnly_ParstHHmm()
|
||||
{
|
||||
Assert.Equal(new TimeOnly(14, 30), JsonSerializer.Deserialize<TimeOnly>("\"14:30\"", Options));
|
||||
}
|
||||
|
||||
/// Der eigentliche Bug betraf DateOnly?/TimeOnly? (nullable) in AiLesson, nicht die
|
||||
/// nicht-nullable Basistypen — dieser Test deckt genau das ab, nicht nur die Converter isoliert.
|
||||
[Fact]
|
||||
public void AiLesson_MitDeutschemDatumUndUhrzeit_DeserialisiertKorrekt()
|
||||
{
|
||||
const string json = """
|
||||
{"id":null,"date":"24.12.2026","lessonNumber":3,"topic":"Test","startTime":"14:30",
|
||||
"phases":[],"homework":null,"reflection":null}
|
||||
""";
|
||||
|
||||
var lesson = JsonSerializer.Deserialize<AiLesson>(json, Options);
|
||||
|
||||
Assert.Equal(new DateOnly(2026, 12, 24), lesson!.Date);
|
||||
Assert.Equal(new TimeOnly(14, 30), lesson.StartTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AiLesson_OhneDatumUndUhrzeit_BleibtNull()
|
||||
{
|
||||
const string json = """{"id":null,"topic":"Test","phases":[]}""";
|
||||
|
||||
var lesson = JsonSerializer.Deserialize<AiLesson>(json, Options);
|
||||
|
||||
Assert.Null(lesson!.Date);
|
||||
Assert.Null(lesson.StartTime);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user