UPDATE
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from django.apps import apps
|
||||
from django.test import SimpleTestCase, TestCase, override_settings
|
||||
|
||||
from location_data.models import SoilLocation
|
||||
from weather.adapters import MockWeatherAdapter, OpenMeteoWeatherAdapter
|
||||
from weather.models import WeatherForecast
|
||||
from weather.services import fetch_weather_from_api, update_weather_for_location
|
||||
|
||||
|
||||
class MockWeatherAdapterTests(SimpleTestCase):
|
||||
def setUp(self):
|
||||
self.adapter = MockWeatherAdapter(delay_seconds=0)
|
||||
|
||||
def test_same_coordinate_returns_same_forecast(self):
|
||||
first = self.adapter.fetch_forecast(35.71, 51.4)
|
||||
second = self.adapter.fetch_forecast(35.71, 51.4)
|
||||
|
||||
self.assertEqual(first, second)
|
||||
|
||||
def test_nearby_coordinates_produce_nearby_forecast(self):
|
||||
first = self.adapter.fetch_forecast(35.71, 51.4)
|
||||
second = self.adapter.fetch_forecast(35.715, 51.405)
|
||||
|
||||
first_daily = first["daily"]
|
||||
second_daily = second["daily"]
|
||||
self.assertLess(
|
||||
abs(first_daily["temperature_2m_mean"][0] - second_daily["temperature_2m_mean"][0]),
|
||||
2.5,
|
||||
)
|
||||
self.assertLess(
|
||||
abs(first_daily["relative_humidity_2m_mean"][0] - second_daily["relative_humidity_2m_mean"][0]),
|
||||
8.0,
|
||||
)
|
||||
self.assertLess(
|
||||
abs(first_daily["wind_speed_10m_max"][0] - second_daily["wind_speed_10m_max"][0]),
|
||||
6.0,
|
||||
)
|
||||
|
||||
def test_shape_matches_open_meteo_daily_contract(self):
|
||||
forecast = self.adapter.fetch_forecast(35.71, 51.4)
|
||||
daily = forecast["daily"]
|
||||
|
||||
self.assertEqual(len(daily["time"]), 7)
|
||||
self.assertEqual(len(daily["temperature_2m_max"]), 7)
|
||||
self.assertEqual(len(daily["weather_code"]), 7)
|
||||
|
||||
|
||||
class WeatherAdapterSelectionTests(SimpleTestCase):
|
||||
def tearDown(self):
|
||||
apps.get_app_config("weather").__dict__.pop("weather_data_adapter", None)
|
||||
|
||||
@override_settings(WEATHER_DATA_PROVIDER="mock", WEATHER_MOCK_DELAY_SECONDS=0)
|
||||
def test_app_config_returns_mock_adapter(self):
|
||||
config = apps.get_app_config("weather")
|
||||
config.__dict__.pop("weather_data_adapter", None)
|
||||
|
||||
adapter = config.get_weather_data_adapter()
|
||||
|
||||
self.assertIsInstance(adapter, MockWeatherAdapter)
|
||||
|
||||
@override_settings(WEATHER_DATA_PROVIDER="open-meteo", WEATHER_TIMEOUT_SECONDS=12)
|
||||
def test_app_config_returns_live_adapter(self):
|
||||
config = apps.get_app_config("weather")
|
||||
config.__dict__.pop("weather_data_adapter", None)
|
||||
|
||||
adapter = config.get_weather_data_adapter()
|
||||
|
||||
self.assertIsInstance(adapter, OpenMeteoWeatherAdapter)
|
||||
self.assertEqual(adapter.timeout, 12)
|
||||
|
||||
|
||||
@override_settings(WEATHER_DATA_PROVIDER="mock", WEATHER_MOCK_DELAY_SECONDS=0)
|
||||
class WeatherServiceTests(TestCase):
|
||||
def setUp(self):
|
||||
self.location = SoilLocation.objects.create(
|
||||
latitude="35.710000",
|
||||
longitude="51.400000",
|
||||
)
|
||||
|
||||
def test_fetch_weather_from_api_uses_mock_provider(self):
|
||||
payload = fetch_weather_from_api(35.71, 51.4)
|
||||
|
||||
self.assertIn("daily", payload)
|
||||
self.assertEqual(len(payload["daily"]["time"]), 7)
|
||||
|
||||
def test_update_weather_for_location_persists_seven_days(self):
|
||||
result = update_weather_for_location(self.location)
|
||||
|
||||
self.assertEqual(result["status"], "success")
|
||||
self.assertEqual(result["days_updated"], 7)
|
||||
self.assertEqual(
|
||||
WeatherForecast.objects.filter(location=self.location).count(),
|
||||
7,
|
||||
)
|
||||
self.assertTrue(
|
||||
WeatherForecast.objects.filter(
|
||||
location=self.location,
|
||||
precipitation__isnull=False,
|
||||
weather_code__isnull=False,
|
||||
).exists()
|
||||
)
|
||||
Reference in New Issue
Block a user