From 3540e1eabe76e89aba8762b3fea5f4b0381d509a Mon Sep 17 00:00:00 2001 From: Sander Date: Fri, 19 Apr 2024 13:54:59 +0000 Subject: [PATCH 1/3] Fix for JSON unexpected character error - Add response text to diagnostics - Easier way to load fixtures for tests --- custom_components/knmi/api.py | 46 ++- custom_components/knmi/diagnostics.py | 1 + tests/conftest.py | 34 +- tests/fixtures/_.json | 452 ++++++++++++++++++++++++++ tests/fixtures/response_alarm.json | 452 ++++++++++++++++++++++++++ tests/test_api.py | 13 + tests/test_binary_sensor.py | 4 +- 7 files changed, 964 insertions(+), 38 deletions(-) create mode 100644 tests/fixtures/_.json create mode 100644 tests/fixtures/response_alarm.json diff --git a/custom_components/knmi/api.py b/custom_components/knmi/api.py index 20a23a0..ea5b7e5 100644 --- a/custom_components/knmi/api.py +++ b/custom_components/knmi/api.py @@ -1,12 +1,16 @@ """KnmiApiClient""" import asyncio +import json +import logging import socket import aiohttp from .const import API_ENDPOINT, API_TIMEOUT +_LOGGER: logging.Logger = logging.getLogger(__package__) + class KnmiApiClientError(Exception): """Exception to indicate a general API error.""" @@ -27,6 +31,8 @@ class KnmiApiRateLimitError(KnmiApiClientError): class KnmiApiClient: """KNMI API wrapper""" + response_text = None + def __init__( self, api_key: str, @@ -40,27 +46,39 @@ def __init__( self.longitude = longitude self._session = session + async def get_response_text(self) -> str: + """Get API response text""" + async with asyncio.timeout(API_TIMEOUT): + response = await self._session.get( + API_ENDPOINT.format(self.api_key, self.latitude, self.longitude) + ) + + return await response.text() + async def async_get_data(self) -> dict: """Get data from the API.""" try: - async with asyncio.timeout(API_TIMEOUT): - response = await self._session.get( - API_ENDPOINT.format(self.api_key, self.latitude, self.longitude) - ) + self.response_text = await self.get_response_text() - response_text = await response.text() + # The API has no proper error handling for a wrong API key or rate limit. + # Instead a 200 with a message is returned, try to detect that here. + if "Vraag eerst een API-key op" in self.response_text: + raise KnmiApiClientApiKeyError("The given API key is invalid") - # The API has no proper error handling for a wrong API key or rate limit. - # Instead a 200 with a message is returned, try to detect that here. - if "Vraag eerst een API-key op" in response_text: - raise KnmiApiClientApiKeyError("The given API key is invalid") + if "Dagelijkse limiet" in self.response_text: + raise KnmiApiRateLimitError( + "API key daily limit exceeded, try again tomorrow" + ) - if "Dagelijkse limiet" in response_text: - raise KnmiApiRateLimitError( - "API key daily limit exceeded, try again tomorrow" - ) + # The API has an ongoing issue due ot invalid JSON repsponse. + # Where a null value of a number field is set to _ (without quotes). + # Here we fix tje JSON by setting the value to null. + # More info: https://github.com/golles/ha-knmi/issues/130 + if '": _,' in self.response_text: + _LOGGER.debug("Detected invalid JSON, attempting to fix that...") + return json.loads(self.response_text.replace('": _,', '": null,')) - return await response.json() + return json.loads(self.response_text) except asyncio.TimeoutError as exception: raise KnmiApiClientCommunicationError( diff --git a/custom_components/knmi/diagnostics.py b/custom_components/knmi/diagnostics.py index 0ad3d26..5b10978 100644 --- a/custom_components/knmi/diagnostics.py +++ b/custom_components/knmi/diagnostics.py @@ -20,4 +20,5 @@ async def async_get_config_entry_diagnostics( return { "config_entry": async_redact_data(config_entry.as_dict(), TO_REDACT), "data": coordinator.data, + "response_text": coordinator.api.response_text, } diff --git a/tests/conftest.py b/tests/conftest.py index 3563f9d..9b10cd2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,7 +15,7 @@ # # See here for more info: https://docs.pytest.org/en/latest/fixture.html (note that # pytest includes fixtures OOB which you can use as defined on this page) -import json + from unittest.mock import PropertyMock, patch import pytest @@ -63,31 +63,19 @@ def enable_all_entities(): yield -# This fixture, when used, will have the mocked values from response.json loaded in the integration. +# This fixture, when used, will have the mocked data from a given json file. @pytest.fixture(name="mocked_data") -def mocked_data_fixture(): - """Skip calls to get data from API.""" - data = json.loads(load_fixture(response_json)) - - with patch( - async_get_data, - return_value=data, - ): - yield - - -# This fixture, when used, will have the mocked values from response.json loaded in the integration. -# As an addition, the alarm and related values are set. -@pytest.fixture(name="mocked_data_alarm") -def mocked_data_alarm_fixture(): - """Skip calls to get data from API.""" - data = json.loads(load_fixture(response_json)) - - data["liveweer"][0]["alarm"] = 1 +def mocked_data_fixture(request): + """Use mocked data in the integration""" + json_file = request.node.get_closest_marker("fixture") + if json_file is None: + json_file = "response.json" + else: + json_file = json_file.args[0] with patch( - async_get_data, - return_value=data, + "custom_components.knmi.KnmiApiClient.get_response_text", + return_value=load_fixture(json_file), ): yield diff --git a/tests/fixtures/_.json b/tests/fixtures/_.json new file mode 100644 index 0000000..9738c74 --- /dev/null +++ b/tests/fixtures/_.json @@ -0,0 +1,452 @@ +{ + "liveweer": [ + { + "plaats": "Zwolle", + "timestamp": 1711718284, + "time": "29-03-2024 14:18:04", + "temp": 12.2, + "gtemp": 9, + "samenv": "Onbewolkt", + "lv": 71, + "windr": "ZW", + "windrgr": 210.7, + "windms": 4.86, + "windbft": 3, + "windknp": 9.4, + "windkmh": 17.5, + "luchtd": _, + "ldmmhg": _, + "dauwp": 7.1, + "zicht": 100000, + "gr": 238, + "verw": "Af en toe een bui, soms ook zon. Morgen vooral in het oosten warm. ", + "sup": "06:14", + "sunder": "19:07", + "image": "zonnig", + "alarm": 0, + "lkop": "Er zijn geen waarschuwingen", + "ltekst": "Er zijn momenteel geen waarschuwingen van kracht.", + "wrschklr": "groen", + "wrsch_g": "-", + "wrsch_gts": 0, + "wrsch_gc": "-" + } + ], + "wk_verw": [ + { + "dag": "29-03-2024", + "image": "buien", + "max_temp": 13, + "min_temp": 9, + "windbft": 4, + "windkmh": 21, + "windknp": 12, + "windms": 6, + "windrgr": 190, + "windr": "Z", + "neersl_perc_dag": 40, + "zond_perc_dag": 10 + }, + { + "dag": "30-03-2024", + "image": "buien", + "max_temp": 18, + "min_temp": 8, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 160, + "windr": "ZO", + "neersl_perc_dag": 40, + "zond_perc_dag": 17 + }, + { + "dag": "31-03-2024", + "image": "halfbewolkt", + "max_temp": 15, + "min_temp": 7, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 145, + "windr": "ZO", + "neersl_perc_dag": 0, + "zond_perc_dag": 39 + }, + { + "dag": "01-04-2024", + "image": "bewolkt", + "max_temp": 9, + "min_temp": 7, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 143, + "windr": "ZO", + "neersl_perc_dag": 20, + "zond_perc_dag": 13 + }, + { + "dag": "02-04-2024", + "image": "bewolkt", + "max_temp": 9, + "min_temp": 6, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 163, + "windr": "ZO", + "neersl_perc_dag": 10, + "zond_perc_dag": 10 + } + ], + "uur_verw": [ + { + "uur": "29-03-2024 14:00", + "timestamp": 1711717200, + "image": "regen", + "temp": 12, + "windbft": 4, + "windkmh": 21, + "windknp": 12, + "windms": 6, + "windrgr": 212, + "windr": "Z", + "neersl": 0.1, + "gr": 510 + }, + { + "uur": "29-03-2024 15:00", + "timestamp": 1711720800, + "image": "halfbewolkt", + "temp": 12, + "windbft": 4, + "windkmh": 21, + "windknp": 12, + "windms": 6, + "windrgr": 215, + "windr": "ZW", + "neersl": 0, + "gr": 504 + }, + { + "uur": "29-03-2024 16:00", + "timestamp": 1711724400, + "image": "halfbewolkt", + "temp": 12, + "windbft": 4, + "windkmh": 21, + "windknp": 12, + "windms": 6, + "windrgr": 214, + "windr": "ZW", + "neersl": 0, + "gr": 357 + }, + { + "uur": "29-03-2024 17:00", + "timestamp": 1711728000, + "image": "halfbewolkt", + "temp": 13, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 216, + "windr": "ZW", + "neersl": 0, + "gr": 291 + }, + { + "uur": "29-03-2024 18:00", + "timestamp": 1711731600, + "image": "zonnig", + "temp": 13, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 197, + "windr": "Z", + "neersl": 0, + "gr": 180 + }, + { + "uur": "29-03-2024 19:00", + "timestamp": 1711735200, + "image": "zonnig", + "temp": 12, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 180, + "windr": "Z", + "neersl": 0, + "gr": 50 + }, + { + "uur": "29-03-2024 20:00", + "timestamp": 1711738800, + "image": "nachtbewolkt", + "temp": 11, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 173, + "windr": "Z", + "neersl": 0, + "gr": 0 + }, + { + "uur": "29-03-2024 21:00", + "timestamp": 1711742400, + "image": "nachtbewolkt", + "temp": 10, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 160, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "29-03-2024 22:00", + "timestamp": 1711746000, + "image": "bewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 174, + "windr": "Z", + "neersl": 0, + "gr": 0 + }, + { + "uur": "29-03-2024 23:00", + "timestamp": 1711749600, + "image": "nachtbewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 162, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 00:00", + "timestamp": 1711753200, + "image": "bewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 164, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 01:00", + "timestamp": 1711756800, + "image": "nachtbewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 159, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 02:00", + "timestamp": 1711760400, + "image": "bewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 163, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 03:00", + "timestamp": 1711764000, + "image": "bewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 144, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 04:00", + "timestamp": 1711767600, + "image": "bewolkt", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 137, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "30-03-2024 05:00", + "timestamp": 1711771200, + "image": "regen", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 146, + "windr": "ZO", + "neersl": 0.1, + "gr": 0 + }, + { + "uur": "30-03-2024 06:00", + "timestamp": 1711774800, + "image": "regen", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 110, + "windr": "ZO", + "neersl": 0.6, + "gr": 0 + }, + { + "uur": "30-03-2024 07:00", + "timestamp": 1711778400, + "image": "regen", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 70, + "windr": "NO", + "neersl": 0.9, + "gr": 0 + }, + { + "uur": "30-03-2024 08:00", + "timestamp": 1711782000, + "image": "regen", + "temp": 9, + "windbft": 2, + "windkmh": 7, + "windknp": 4, + "windms": 2, + "windrgr": 39, + "windr": "NO", + "neersl": 0.8, + "gr": 3 + }, + { + "uur": "30-03-2024 09:00", + "timestamp": 1711785600, + "image": "regen", + "temp": 9, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 58, + "windr": "NO", + "neersl": 0.2, + "gr": 14 + }, + { + "uur": "30-03-2024 10:00", + "timestamp": 1711789200, + "image": "bewolkt", + "temp": 10, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 108, + "windr": "ZO", + "neersl": 0, + "gr": 213 + }, + { + "uur": "30-03-2024 11:00", + "timestamp": 1711792800, + "image": "bewolkt", + "temp": 12, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 168, + "windr": "Z", + "neersl": 0, + "gr": 416 + }, + { + "uur": "30-03-2024 12:00", + "timestamp": 1711796400, + "image": "bewolkt", + "temp": 13, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 188, + "windr": "Z", + "neersl": 0, + "gr": 507 + }, + { + "uur": "30-03-2024 13:00", + "timestamp": 1711800000, + "image": "bewolkt", + "temp": 14, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 193, + "windr": "Z", + "neersl": 0, + "gr": 463 + } + ], + "api": [ + { + "bron": "Bron: Weerdata KNMI/NOAA via Weerlive.nl", + "max_verz": 300, + "rest_verz": -16814 + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/response_alarm.json b/tests/fixtures/response_alarm.json new file mode 100644 index 0000000..f5e5fa8 --- /dev/null +++ b/tests/fixtures/response_alarm.json @@ -0,0 +1,452 @@ +{ + "liveweer": [ + { + "plaats": "Purmerend", + "timestamp": 1707944883, + "time": "14-02-2024 22:08:03", + "temp": 10.5, + "gtemp": 6.8, + "samenv": "Licht bewolkt", + "lv": 97, + "windr": "WZW", + "windrgr": 226, + "windms": 8.08, + "windbft": 5, + "windknp": 15.7, + "windkmh": 29.1, + "luchtd": 1015.03, + "ldmmhg": 761, + "dauwp": 10.1, + "zicht": 6990, + "gr": 0, + "verw": "Bewolkt en perioden met regen. Morgen in de middag droog en zeer zacht", + "sup": "07:57", + "sunder": "17:51", + "image": "wolkennacht", + "alarm": 1, + "lkop": "Vanavond (zeer) zware windstoten", + "ltekst": "De eerstkomende uren zijn er geen waarschuwingen van kracht. Vanavond komen er (zeer) zware windstoten voor. Landinwaarts tot 90 km/u, aan de kust tot 110 km/u. De wind komt uit een zuidwestelijke richting. Verkeer en buitenactiviteiten kunnen hinder ondervinden.", + "wrschklr": "groen", + "wrsch_g": "22-02-2024 18:00", + "wrsch_gts": 1708621200, + "wrsch_gc": "geel" + } + ], + "wk_verw": [ + { + "dag": "14-02-2024", + "image": "bewolkt", + "max_temp": 10, + "min_temp": 10, + "windbft": 4, + "windkmh": 25, + "windknp": 14, + "windms": 7, + "windrgr": 221, + "windr": "ZW", + "neersl_perc_dag": 0, + "zond_perc_dag": 0 + }, + { + "dag": "15-02-2024", + "image": "bewolkt", + "max_temp": 12, + "min_temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 184, + "windr": "Z", + "neersl_perc_dag": 10, + "zond_perc_dag": 8 + }, + { + "dag": "16-02-2024", + "image": "buien", + "max_temp": 10, + "min_temp": 9, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 199, + "windr": "Z", + "neersl_perc_dag": 40, + "zond_perc_dag": 14 + }, + { + "dag": "17-02-2024", + "image": "halfbewolkt", + "max_temp": 8, + "min_temp": 6, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 228, + "windr": "ZW", + "neersl_perc_dag": 20, + "zond_perc_dag": 46 + }, + { + "dag": "18-02-2024", + "image": "bewolkt", + "max_temp": 8, + "min_temp": 7, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 210, + "windr": "Z", + "neersl_perc_dag": 10, + "zond_perc_dag": 0 + } + ], + "uur_verw": [ + { + "uur": "14-02-2024 23:00", + "timestamp": 1707948000, + "image": "nachtbewolkt", + "temp": 10, + "windbft": 4, + "windkmh": 21, + "windknp": 12, + "windms": 6, + "windrgr": 231, + "windr": "ZW", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 00:00", + "timestamp": 1707951600, + "image": "nachtbewolkt", + "temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 233, + "windr": "ZW", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 01:00", + "timestamp": 1707955200, + "image": "regen", + "temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 232, + "windr": "ZW", + "neersl": 0.1, + "gr": 0 + }, + { + "uur": "15-02-2024 02:00", + "timestamp": 1707958800, + "image": "bewolkt", + "temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 226, + "windr": "ZW", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 03:00", + "timestamp": 1707962400, + "image": "bewolkt", + "temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 224, + "windr": "ZW", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 04:00", + "timestamp": 1707966000, + "image": "bewolkt", + "temp": 10, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 219, + "windr": "ZW", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 05:00", + "timestamp": 1707969600, + "image": "bewolkt", + "temp": 10, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 203, + "windr": "Z", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 06:00", + "timestamp": 1707973200, + "image": "regen", + "temp": 10, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 190, + "windr": "Z", + "neersl": 0.2, + "gr": 0 + }, + { + "uur": "15-02-2024 07:00", + "timestamp": 1707976800, + "image": "regen", + "temp": 10, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 196, + "windr": "Z", + "neersl": 0.9, + "gr": 0 + }, + { + "uur": "15-02-2024 08:00", + "timestamp": 1707980400, + "image": "regen", + "temp": 11, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 210, + "windr": "Z", + "neersl": 1, + "gr": 0 + }, + { + "uur": "15-02-2024 09:00", + "timestamp": 1707984000, + "image": "regen", + "temp": 11, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 218, + "windr": "ZW", + "neersl": 0.1, + "gr": 3 + }, + { + "uur": "15-02-2024 10:00", + "timestamp": 1707987600, + "image": "bewolkt", + "temp": 11, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 217, + "windr": "ZW", + "neersl": 0, + "gr": 6 + }, + { + "uur": "15-02-2024 11:00", + "timestamp": 1707991200, + "image": "regen", + "temp": 11, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 214, + "windr": "ZW", + "neersl": 0.1, + "gr": 11 + }, + { + "uur": "15-02-2024 12:00", + "timestamp": 1707994800, + "image": "bewolkt", + "temp": 12, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 206, + "windr": "Z", + "neersl": 0, + "gr": 30 + }, + { + "uur": "15-02-2024 13:00", + "timestamp": 1707998400, + "image": "bewolkt", + "temp": 13, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 211, + "windr": "Z", + "neersl": 0, + "gr": 172 + }, + { + "uur": "15-02-2024 14:00", + "timestamp": 1708002000, + "image": "bewolkt", + "temp": 14, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 200, + "windr": "Z", + "neersl": 0, + "gr": 161 + }, + { + "uur": "15-02-2024 15:00", + "timestamp": 1708005600, + "image": "bewolkt", + "temp": 14, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 179, + "windr": "Z", + "neersl": 0, + "gr": 58 + }, + { + "uur": "15-02-2024 16:00", + "timestamp": 1708009200, + "image": "bewolkt", + "temp": 14, + "windbft": 2, + "windkmh": 10, + "windknp": 6, + "windms": 3, + "windrgr": 167, + "windr": "ZO", + "neersl": 0, + "gr": 114 + }, + { + "uur": "15-02-2024 17:00", + "timestamp": 1708012800, + "image": "bewolkt", + "temp": 14, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 168, + "windr": "Z", + "neersl": 0, + "gr": 72 + }, + { + "uur": "15-02-2024 18:00", + "timestamp": 1708016400, + "image": "bewolkt", + "temp": 13, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 156, + "windr": "ZO", + "neersl": 0, + "gr": 14 + }, + { + "uur": "15-02-2024 19:00", + "timestamp": 1708020000, + "image": "bewolkt", + "temp": 12, + "windbft": 3, + "windkmh": 14, + "windknp": 8, + "windms": 4, + "windrgr": 155, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 20:00", + "timestamp": 1708023600, + "image": "bewolkt", + "temp": 12, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 152, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 21:00", + "timestamp": 1708027200, + "image": "bewolkt", + "temp": 12, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 155, + "windr": "ZO", + "neersl": 0, + "gr": 0 + }, + { + "uur": "15-02-2024 22:00", + "timestamp": 1708030800, + "image": "bewolkt", + "temp": 12, + "windbft": 3, + "windkmh": 18, + "windknp": 10, + "windms": 5, + "windrgr": 162, + "windr": "ZO", + "neersl": 0, + "gr": 0 + } + ], + "api": [ + { + "bron": "Bron: Weerdata KNMI/NOAA via Weerlive.nl", + "max_verz": 300, + "rest_verz": 132 + } + ] +} diff --git a/tests/test_api.py b/tests/test_api.py index 3c84006..f5f284e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -14,6 +14,7 @@ ) from custom_components.knmi.const import API_ENDPOINT +from . import setup_component from .const import MOCK_CONFIG @@ -50,3 +51,15 @@ async def test_api_error( with pytest.raises(exception): await api.async_get_data() + + +@pytest.mark.fixture("_.json") +async def test_invalid_json_fix(hass: HomeAssistant, mocked_data): + """Test for fix https://github.com/golles/ha-knmi/issues/130.""" + config_entry = await setup_component(hass) + + state = hass.states.get("sensor.knmi_air_pressure") + assert state.state == "unknown" + + assert await config_entry.async_unload(hass) + await hass.async_block_till_done() diff --git a/tests/test_binary_sensor.py b/tests/test_binary_sensor.py index dbcdadb..e250dfb 100644 --- a/tests/test_binary_sensor.py +++ b/tests/test_binary_sensor.py @@ -2,6 +2,7 @@ from freezegun import freeze_time from homeassistant.core import HomeAssistant +import pytest from . import setup_component @@ -25,7 +26,8 @@ async def test_knmi_binary_alarm_sensor_is_off(hass: HomeAssistant, mocked_data) await hass.async_block_till_done() -async def test_knmi_binary_alarm_sensor_is_on(hass: HomeAssistant, mocked_data_alarm): +@pytest.mark.fixture("response_alarm.json") +async def test_knmi_binary_alarm_sensor_is_on(hass: HomeAssistant, mocked_data): """Test is_on function on alarm sensor.""" config_entry = await setup_component(hass) From b5777a1b110b773914a50dc4913d8b9abafa8636 Mon Sep 17 00:00:00 2001 From: Sander Date: Fri, 19 Apr 2024 16:16:53 +0200 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Hmmbob <33529490+hmmbob@users.noreply.github.com> --- custom_components/knmi/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/knmi/api.py b/custom_components/knmi/api.py index ea5b7e5..7aec33f 100644 --- a/custom_components/knmi/api.py +++ b/custom_components/knmi/api.py @@ -70,9 +70,9 @@ async def async_get_data(self) -> dict: "API key daily limit exceeded, try again tomorrow" ) - # The API has an ongoing issue due ot invalid JSON repsponse. + # The API has an ongoing issue due to invalid JSON response. # Where a null value of a number field is set to _ (without quotes). - # Here we fix tje JSON by setting the value to null. + # Here we fix the JSON by setting the value to null. # More info: https://github.com/golles/ha-knmi/issues/130 if '": _,' in self.response_text: _LOGGER.debug("Detected invalid JSON, attempting to fix that...") From eb3557be7a4b028495bba292e5e1ac153512603f Mon Sep 17 00:00:00 2001 From: Sander Date: Fri, 19 Apr 2024 14:27:23 +0000 Subject: [PATCH 3/3] Optimize fixture --- tests/conftest.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9b10cd2..03172b2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -67,11 +67,11 @@ def enable_all_entities(): @pytest.fixture(name="mocked_data") def mocked_data_fixture(request): """Use mocked data in the integration""" - json_file = request.node.get_closest_marker("fixture") - if json_file is None: - json_file = "response.json" - else: - json_file = json_file.args[0] + json_file = "response.json" + fixture = request.node.get_closest_marker("fixture") + + if fixture is not None: + json_file = fixture.args[0] with patch( "custom_components.knmi.KnmiApiClient.get_response_text",