using System.IO.Compression; using System.Text; using Xunit; namespace LehrerApp.Api.Tests; public sealed class DwdWeatherServiceTests { [Fact] public void ParseStationCatalog_LiestFestbreitenformatUndFindetNaechsteStation() { const string catalog = """ ID ICAO NAME LAT LON ELEV ----- ---- -------------------- ----- ------- ----- 10641 EDDF OFFENBACH-WETTERPARK 50.08 8.78 119 10382 EDDT BERLIN-TEGEL 52.56 13.31 37 """; var stations = DwdWeatherService.ParseStationCatalog(catalog); var nearest = DwdWeatherService.FindNearestStation(stations, 50.1, 8.7); Assert.Equal(2, stations.Count); Assert.Equal("10641", nearest!.Id); Assert.Equal("OFFENBACH-WETTERPARK", nearest.Name); } [Fact] public void ParseMosmix_KonvertiertEinheitenUndBehaeltFehlwerteAlsNull() { var now = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-dd'T'HH:00:00.000'Z'"); var kml = $$""" 2026-08-23T15:00:00Z {{now}} 293.15 5 - 1.25 67.6 1800 75 61 """; var parsed = DwdWeatherService.ParseMosmix(Zip("forecast.kml", kml)); var hour = Assert.Single(parsed.Hours); Assert.Equal(20, hour.TemperatureC); Assert.Equal(18, hour.WindSpeedKmh); Assert.Null(hour.WindGustKmh); Assert.Equal(1.3, hour.PrecipitationMm); Assert.Equal(68, hour.PrecipitationProbabilityPercent); Assert.Equal(30, hour.SunshineDurationMinutes); Assert.Equal(61, hour.WeatherCode); } [Fact] public void ParseMosmix_LiefertMehrAlsDreiTageFuerFolgewoche() { var start = DateTime.UtcNow.AddHours(1); var timeSteps = string.Join("", Enumerable.Range(0, 100) .Select(i => $"{start.AddHours(i):yyyy-MM-dd'T'HH:mm:ss'Z'}")); var values = string.Join(' ', Enumerable.Repeat("293.15", 100)); var kml = $$""" {{timeSteps}} {{values}} """; var parsed = DwdWeatherService.ParseMosmix(Zip("forecast.kml", kml)); Assert.Equal(100, parsed.Hours.Count); } [Fact] public void ParseCapArchive_OrdnetWarnpolygonGeografischZu() { var xml = """ warnung-1Actual de-DEGEWITTERSevere 2026-08-23T18:00:00Z2099-08-23T20:00:00Z Amtliche WarnungTest 50.0,8.0 50.0,9.0 51.0,9.0 51.0,8.0 50.0,8.0 """; var warning = Assert.Single(DwdWeatherService.ParseCapArchive( Zip("warning.xml", xml), DateTime.UtcNow)); Assert.True(DwdWeatherService.PointInPolygon(warning.Polygons[0], 50.5, 8.5)); Assert.False(DwdWeatherService.PointInPolygon(warning.Polygons[0], 52.0, 8.5)); Assert.Equal("GEWITTER", warning.Warning.Event); } private static byte[] Zip(string fileName, string content) { using var memory = new MemoryStream(); using (var archive = new ZipArchive(memory, ZipArchiveMode.Create, leaveOpen: true)) { var entry = archive.CreateEntry(fileName); using var writer = new StreamWriter(entry.Open(), new UTF8Encoding(false)); writer.Write(content); } return memory.ToArray(); } }