import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:dmc_app/domain/waypoint/flat_waypoint_list.dart'; import 'package:dmc_app/services/wind/wind_service.dart'; bool _isPressureRequest(http.Request request) => (request.url.queryParameters['hourly'] ?? '').contains('hPa'); http.Response _json(Object body) => http.Response(jsonEncode(body), 200, headers: { 'content-type': 'application/json', }); void main() { group('WindService.fetchHeaderWind', () { test('interpoliert auf 120 m AGL ueber dem Referenzort', () async { final client = MockClient((request) async { if (_isPressureRequest(request)) { return http.Response('', 500); } return _json({ 'elevation': 2.0, 'hourly': { 'time': ['2024-06-01T12:00'], 'wind_speed_10m': [3.0], 'wind_direction_10m': [190.0], 'wind_speed_80m': [5.0], 'wind_direction_80m': [200.0], 'wind_speed_120m': [6.0], 'wind_direction_120m': [205.0], 'wind_speed_180m': [8.0], 'wind_direction_180m': [210.0], 'wind_gusts_10m': [7.5], }, }); }); final service = WindService(client: client); final result = await service.fetchHeaderWind(52.0, 4.0); // Ziel 2 + 120 = 122 m AMSL faellt exakt auf den 120-m-Stuetzpunkt. expect(result, isNotNull); expect(result!.speedMs, closeTo(6.0, 0.001)); expect(result.dirFromDeg, closeTo(205.0, 0.001)); }); test('liefert null, wenn beide Requests fehlschlagen', () async { final client = MockClient((request) async => http.Response('', 500)); final service = WindService(client: client); final result = await service.fetchHeaderWind(52.0, 4.0); expect(result, isNull); }); }); group('WindService.fetchWindForWaypoints', () { test('interpoliert jeden Wegpunkt an seinem eigenen Ort/seiner eigenen Hoehe', () async { final client = MockClient((request) async { if (_isPressureRequest(request)) { return http.Response('', 500); } return _json([ { 'elevation': 2.0, 'hourly': { 'time': ['2024-06-01T12:00'], 'wind_speed_10m': [3.0], 'wind_direction_10m': [190.0], 'wind_speed_80m': [5.0], 'wind_direction_80m': [200.0], 'wind_speed_120m': [6.0], 'wind_direction_120m': [205.0], 'wind_speed_180m': [8.0], 'wind_direction_180m': [210.0], 'wind_gusts_10m': [7.5], }, }, { 'elevation': 50.0, 'hourly': { 'time': ['2024-06-01T12:00'], 'wind_speed_10m': [1.0], 'wind_direction_10m': [100.0], 'wind_speed_80m': [9.0], 'wind_direction_80m': [250.0], 'wind_speed_120m': [10.0], 'wind_direction_120m': [260.0], 'wind_speed_180m': [11.0], 'wind_direction_180m': [270.0], 'wind_gusts_10m': [12.0], }, }, ]); }); final service = WindService(client: client); final waypoints = [ const Waypoint( lat: 52.0, lon: 4.0, altitudeM: 10, // 2 + 10 = 12 m AMSL: exakt der 10-m-Stuetzpunkt speedMs: 15, catchRadiusM: 60, ), const Waypoint( lat: 52.1, lon: 4.1, altitudeM: 80, // 50 + 80 = 130 m AMSL: exakt der 80-m-Stuetzpunkt speedMs: 15, catchRadiusM: 60, ), ]; final result = await service.fetchWindForWaypoints(waypoints); expect(result[0].windSpeedMs, closeTo(3.0, 0.001)); expect(result[0].windDirFromDeg, closeTo(190.0, 0.001)); expect(result[0].windElevationM, closeTo(2.0, 0.001)); expect(result[1].windSpeedMs, closeTo(9.0, 0.001)); expect(result[1].windDirFromDeg, closeTo(250.0, 0.001)); expect(result[1].windElevationM, closeTo(50.0, 0.001)); }); test('leere Wegpunktliste loest keinen Request aus', () async { var called = false; final client = MockClient((request) async { called = true; return http.Response('', 500); }); final service = WindService(client: client); final result = await service.fetchWindForWaypoints(const []); expect(result, isEmpty); expect(called, isFalse); }); }); }