86 lines
3.2 KiB
C#
86 lines
3.2 KiB
C#
using LehrerApp.Core.Services;
|
||
using Xunit;
|
||
|
||
namespace LehrerApp.Tests;
|
||
|
||
/// <summary>Synthetische Fixtures nach dem am 23.08.2026 geprüften ClassyPlan-Export.</summary>
|
||
public sealed class AnnualPlanIcsParserTests
|
||
{
|
||
private static string Calendar(params string[] events) =>
|
||
"BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:ClassyPlan\n" +
|
||
string.Join("", events) + "END:VCALENDAR\n";
|
||
|
||
[Fact]
|
||
public void Parse_Ganztagstermin_NutztExklusivesDtendAlsInklusivesEnddatum()
|
||
{
|
||
var ics = Calendar(
|
||
"BEGIN:VEVENT\nUID:100-ClassyPlan.app\n" +
|
||
"DTSTART;VALUE=DATE:20260615\nDTEND;VALUE=DATE:20260620\n" +
|
||
"SUMMARY:Klassenfahrt 6a 6b 6d\nX-GROUPNAME:Lehrkräfte\nX-COLOR:#4B9FD8\n" +
|
||
"END:VEVENT\n");
|
||
|
||
var entry = Assert.Single(AnnualPlanIcsParser.Parse(ics));
|
||
|
||
Assert.True(entry.IsAllDay);
|
||
Assert.Equal(new DateOnly(2026, 6, 15), entry.StartDate);
|
||
Assert.Equal(new DateOnly(2026, 6, 19), entry.EndDate);
|
||
Assert.Null(entry.StartTime);
|
||
Assert.Equal("Lehrkräfte", entry.CalendarGroup);
|
||
}
|
||
|
||
[Fact]
|
||
public void Parse_UtcTermin_WirdUnterBeruecksichtigungDerSommerzeitNachBerlinKonvertiert()
|
||
{
|
||
var ics = Calendar(
|
||
"BEGIN:VEVENT\nUID:200-ClassyPlan.app\n" +
|
||
"DTSTART:20260929T113000Z\nDTEND:20260929T130000Z\n" +
|
||
"LAST-MODIFIED:20260814T095236Z\nSEQUENCE:2\nSTATUS:CONFIRMED\n" +
|
||
"SUMMARY:Teams 5–10\nLOCATION:R 101\nX-GROUPNAME:Öffentlich\nEND:VEVENT\n");
|
||
|
||
var entry = Assert.Single(AnnualPlanIcsParser.Parse(ics));
|
||
|
||
Assert.False(entry.IsAllDay);
|
||
Assert.Equal(new TimeOnly(13, 30), entry.StartTime);
|
||
Assert.Equal(new TimeOnly(15, 0), entry.EndTime);
|
||
Assert.Equal(2, entry.Sequence);
|
||
Assert.Equal(new DateTime(2026, 8, 14, 9, 52, 36, DateTimeKind.Utc),
|
||
entry.SourceLastModifiedUtc);
|
||
}
|
||
|
||
[Fact]
|
||
public void Parse_EscapingUndZeilenfaltung_WerdenAufgeloest()
|
||
{
|
||
var ics = Calendar(
|
||
"BEGIN:VEVENT\nUID:300-ClassyPlan.app\nDTSTART;VALUE=DATE:20260823\n" +
|
||
"DESCRIPTION:Erste Zeile\\nZweite Zeile mit sehr langem \n Text\\, Komma\\; Semikolon\n" +
|
||
"SUMMARY:Fortbildung\nEND:VEVENT\n");
|
||
|
||
var entry = Assert.Single(AnnualPlanIcsParser.Parse(ics));
|
||
|
||
Assert.Equal("Erste Zeile\nZweite Zeile mit sehr langem Text, Komma; Semikolon",
|
||
entry.Description);
|
||
}
|
||
|
||
[Fact]
|
||
public void Parse_EinDefektesVevent_LaesstNichtUnbemerktEinenTeilimportZu()
|
||
{
|
||
var ics = Calendar(
|
||
"BEGIN:VEVENT\nUID:gueltig\nDTSTART;VALUE=DATE:20260823\nEND:VEVENT\n",
|
||
"BEGIN:VEVENT\nUID:defekt\nSUMMARY:Ohne Datum\nEND:VEVENT\n");
|
||
|
||
var error = Assert.Throws<FormatException>(() => AnnualPlanIcsParser.Parse(ics));
|
||
|
||
Assert.Contains("DTSTART fehlt", error.Message);
|
||
}
|
||
|
||
[Fact]
|
||
public void Parse_DoppelteUid_WirdAbgelehnt()
|
||
{
|
||
var ics = Calendar(
|
||
"BEGIN:VEVENT\nUID:doppelt\nDTSTART;VALUE=DATE:20260823\nEND:VEVENT\n",
|
||
"BEGIN:VEVENT\nUID:doppelt\nDTSTART;VALUE=DATE:20260824\nEND:VEVENT\n");
|
||
|
||
Assert.Throws<FormatException>(() => AnnualPlanIcsParser.Parse(ics));
|
||
}
|
||
}
|