AccuWeather tests refactoring (#116923)
* Add mock_accuweather_client * Improve tests * Fix exceptions * Remove unneeded update_listener() * Fix arguments for fixtures --------- Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
This commit is contained in:
parent
72d6b4d1c9
commit
09be56964d
9 changed files with 305 additions and 387 deletions
|
@ -64,8 +64,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
await coordinator_observation.async_config_entry_first_refresh()
|
await coordinator_observation.async_config_entry_first_refresh()
|
||||||
await coordinator_daily_forecast.async_config_entry_first_refresh()
|
await coordinator_daily_forecast.async_config_entry_first_refresh()
|
||||||
|
|
||||||
entry.async_on_unload(entry.add_update_listener(update_listener))
|
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = AccuWeatherData(
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = AccuWeatherData(
|
||||||
coordinator_observation=coordinator_observation,
|
coordinator_observation=coordinator_observation,
|
||||||
coordinator_daily_forecast=coordinator_daily_forecast,
|
coordinator_daily_forecast=coordinator_daily_forecast,
|
||||||
|
@ -92,8 +90,3 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
return unload_ok
|
return unload_ok
|
||||||
|
|
||||||
|
|
||||||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|
||||||
"""Update listener."""
|
|
||||||
await hass.config_entries.async_reload(entry.entry_id)
|
|
||||||
|
|
|
@ -1,17 +1,11 @@
|
||||||
"""Tests for AccuWeather."""
|
"""Tests for AccuWeather."""
|
||||||
|
|
||||||
from unittest.mock import PropertyMock, patch
|
|
||||||
|
|
||||||
from homeassistant.components.accuweather.const import DOMAIN
|
from homeassistant.components.accuweather.const import DOMAIN
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry
|
||||||
MockConfigEntry,
|
|
||||||
load_json_array_fixture,
|
|
||||||
load_json_object_fixture,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def init_integration(hass, unsupported_icon=False) -> MockConfigEntry:
|
async def init_integration(hass) -> MockConfigEntry:
|
||||||
"""Set up the AccuWeather integration in Home Assistant."""
|
"""Set up the AccuWeather integration in Home Assistant."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
|
@ -25,29 +19,8 @@ async def init_integration(hass, unsupported_icon=False) -> MockConfigEntry:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
entry.add_to_hass(hass)
|
||||||
forecast = load_json_array_fixture("accuweather/forecast_data.json")
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
if unsupported_icon:
|
|
||||||
current["WeatherIcon"] = 999
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
|
||||||
return_value=current,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_daily_forecast",
|
|
||||||
return_value=forecast,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
36
tests/components/accuweather/conftest.py
Normal file
36
tests/components/accuweather/conftest.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
"""Common fixtures for the AccuWeather tests."""
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.accuweather.const import DOMAIN
|
||||||
|
|
||||||
|
from tests.common import load_json_array_fixture, load_json_object_fixture
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_accuweather_client() -> Generator[AsyncMock, None, None]:
|
||||||
|
"""Mock a AccuWeather client."""
|
||||||
|
current = load_json_object_fixture("current_conditions_data.json", DOMAIN)
|
||||||
|
forecast = load_json_array_fixture("forecast_data.json", DOMAIN)
|
||||||
|
location = load_json_object_fixture("location_data.json", DOMAIN)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.accuweather.AccuWeather", autospec=True
|
||||||
|
) as mock_client,
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.accuweather.config_flow.AccuWeather",
|
||||||
|
new=mock_client,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
client = mock_client.return_value
|
||||||
|
client.async_get_location.return_value = location
|
||||||
|
client.async_get_current_conditions.return_value = current
|
||||||
|
client.async_get_daily_forecast.return_value = forecast
|
||||||
|
client.location_key = "0123456"
|
||||||
|
client.requests_remaining = 10
|
||||||
|
|
||||||
|
yield client
|
|
@ -1,6 +1,6 @@
|
||||||
"""Define tests for the AccuWeather config flow."""
|
"""Define tests for the AccuWeather config flow."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from accuweather import ApiError, InvalidApiKeyError, RequestsExceededError
|
from accuweather import ApiError, InvalidApiKeyError, RequestsExceededError
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CON
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, load_json_object_fixture
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
VALID_CONFIG = {
|
VALID_CONFIG = {
|
||||||
CONF_NAME: "abcd",
|
CONF_NAME: "abcd",
|
||||||
|
@ -48,95 +48,90 @@ async def test_api_key_too_short(hass: HomeAssistant) -> None:
|
||||||
assert result["errors"] == {CONF_API_KEY: "invalid_api_key"}
|
assert result["errors"] == {CONF_API_KEY: "invalid_api_key"}
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_api_key(hass: HomeAssistant) -> None:
|
async def test_invalid_api_key(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test that errors are shown when API key is invalid."""
|
"""Test that errors are shown when API key is invalid."""
|
||||||
with patch(
|
mock_accuweather_client.async_get_location.side_effect = InvalidApiKeyError(
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
"Invalid API key"
|
||||||
side_effect=InvalidApiKeyError("Invalid API key"),
|
)
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_USER},
|
|
||||||
data=VALID_CONFIG,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["errors"] == {CONF_API_KEY: "invalid_api_key"}
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
data=VALID_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == {CONF_API_KEY: "invalid_api_key"}
|
||||||
|
|
||||||
|
|
||||||
async def test_api_error(hass: HomeAssistant) -> None:
|
async def test_api_error(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test API error."""
|
"""Test API error."""
|
||||||
with patch(
|
mock_accuweather_client.async_get_location.side_effect = ApiError(
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
"Invalid response from AccuWeather API"
|
||||||
side_effect=ApiError("Invalid response from AccuWeather API"),
|
)
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_USER},
|
|
||||||
data=VALID_CONFIG,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["errors"] == {"base": "cannot_connect"}
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
data=VALID_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == {"base": "cannot_connect"}
|
||||||
|
|
||||||
|
|
||||||
async def test_requests_exceeded_error(hass: HomeAssistant) -> None:
|
async def test_requests_exceeded_error(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test requests exceeded error."""
|
"""Test requests exceeded error."""
|
||||||
with patch(
|
mock_accuweather_client.async_get_location.side_effect = RequestsExceededError(
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
"The allowed number of requests has been exceeded"
|
||||||
side_effect=RequestsExceededError(
|
)
|
||||||
"The allowed number of requests has been exceeded"
|
|
||||||
),
|
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_USER},
|
|
||||||
data=VALID_CONFIG,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["errors"] == {CONF_API_KEY: "requests_exceeded"}
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
data=VALID_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == {CONF_API_KEY: "requests_exceeded"}
|
||||||
|
|
||||||
|
|
||||||
async def test_integration_already_exists(hass: HomeAssistant) -> None:
|
async def test_integration_already_exists(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test we only allow a single config flow."""
|
"""Test we only allow a single config flow."""
|
||||||
with patch(
|
MockConfigEntry(
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
domain=DOMAIN,
|
||||||
return_value=load_json_object_fixture("accuweather/location_data.json"),
|
unique_id="123456",
|
||||||
):
|
data=VALID_CONFIG,
|
||||||
MockConfigEntry(
|
).add_to_hass(hass)
|
||||||
domain=DOMAIN,
|
|
||||||
unique_id="123456",
|
|
||||||
data=VALID_CONFIG,
|
|
||||||
).add_to_hass(hass)
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
context={"source": SOURCE_USER},
|
context={"source": SOURCE_USER},
|
||||||
data=VALID_CONFIG,
|
data=VALID_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.ABORT
|
assert result["type"] is FlowResultType.ABORT
|
||||||
assert result["reason"] == "single_instance_allowed"
|
assert result["reason"] == "single_instance_allowed"
|
||||||
|
|
||||||
|
|
||||||
async def test_create_entry(hass: HomeAssistant) -> None:
|
async def test_create_entry(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test that the user step works."""
|
"""Test that the user step works."""
|
||||||
with (
|
result = await hass.config_entries.flow.async_init(
|
||||||
patch(
|
DOMAIN,
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
context={"source": SOURCE_USER},
|
||||||
return_value=load_json_object_fixture("accuweather/location_data.json"),
|
data=VALID_CONFIG,
|
||||||
),
|
)
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.async_setup_entry", return_value=True
|
|
||||||
),
|
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": SOURCE_USER},
|
|
||||||
data=VALID_CONFIG,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == "abcd"
|
assert result["title"] == "abcd"
|
||||||
assert result["data"][CONF_NAME] == "abcd"
|
assert result["data"][CONF_NAME] == "abcd"
|
||||||
assert result["data"][CONF_LATITUDE] == 55.55
|
assert result["data"][CONF_LATITUDE] == 55.55
|
||||||
assert result["data"][CONF_LONGITUDE] == 122.12
|
assert result["data"][CONF_LONGITUDE] == 122.12
|
||||||
assert result["data"][CONF_API_KEY] == "32-character-string-1234567890qw"
|
assert result["data"][CONF_API_KEY] == "32-character-string-1234567890qw"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
"""Test AccuWeather diagnostics."""
|
"""Test AccuWeather diagnostics."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
@ -13,6 +15,7 @@ from tests.typing import ClientSessionGenerator
|
||||||
async def test_entry_diagnostics(
|
async def test_entry_diagnostics(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test config entry diagnostics."""
|
"""Test config entry diagnostics."""
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
"""Test init of AccuWeather integration."""
|
"""Test init of AccuWeather integration."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from accuweather import ApiError
|
from accuweather import ApiError
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
|
|
||||||
from homeassistant.components.accuweather.const import (
|
from homeassistant.components.accuweather.const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -14,19 +15,15 @@ from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import STATE_UNAVAILABLE
|
from homeassistant.const import STATE_UNAVAILABLE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.util.dt import utcnow
|
|
||||||
|
|
||||||
from . import init_integration
|
from . import init_integration
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
MockConfigEntry,
|
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_array_fixture,
|
|
||||||
load_json_object_fixture,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_async_setup_entry(hass: HomeAssistant) -> None:
|
async def test_async_setup_entry(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test a successful setup entry."""
|
"""Test a successful setup entry."""
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
|
@ -36,7 +33,9 @@ async def test_async_setup_entry(hass: HomeAssistant) -> None:
|
||||||
assert state.state == "sunny"
|
assert state.state == "sunny"
|
||||||
|
|
||||||
|
|
||||||
async def test_config_not_ready(hass: HomeAssistant) -> None:
|
async def test_config_not_ready(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test for setup failure if connection to AccuWeather is missing."""
|
"""Test for setup failure if connection to AccuWeather is missing."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
|
@ -50,16 +49,18 @@ async def test_config_not_ready(hass: HomeAssistant) -> None:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
mock_accuweather_client.async_get_current_conditions.side_effect = ApiError(
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
"API Error"
|
||||||
side_effect=ApiError("API Error"),
|
)
|
||||||
):
|
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
|
||||||
|
|
||||||
async def test_unload_entry(hass: HomeAssistant) -> None:
|
async def test_unload_entry(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test successful unload of entry."""
|
"""Test successful unload of entry."""
|
||||||
entry = await init_integration(hass)
|
entry = await init_integration(hass)
|
||||||
|
|
||||||
|
@ -73,41 +74,36 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
|
||||||
assert not hass.data.get(DOMAIN)
|
assert not hass.data.get(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
async def test_update_interval(hass: HomeAssistant) -> None:
|
async def test_update_interval(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
"""Test correct update interval."""
|
"""Test correct update interval."""
|
||||||
entry = await init_integration(hass)
|
entry = await init_integration(hass)
|
||||||
|
|
||||||
assert entry.state is ConfigEntryState.LOADED
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 1
|
||||||
forecast = load_json_array_fixture("accuweather/forecast_data.json")
|
assert mock_accuweather_client.async_get_daily_forecast.call_count == 1
|
||||||
|
|
||||||
with (
|
freezer.tick(UPDATE_INTERVAL_OBSERVATION)
|
||||||
patch(
|
async_fire_time_changed(hass)
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
await hass.async_block_till_done()
|
||||||
return_value=current,
|
|
||||||
) as mock_current,
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_daily_forecast",
|
|
||||||
return_value=forecast,
|
|
||||||
) as mock_forecast,
|
|
||||||
):
|
|
||||||
assert mock_current.call_count == 0
|
|
||||||
assert mock_forecast.call_count == 0
|
|
||||||
|
|
||||||
async_fire_time_changed(hass, utcnow() + UPDATE_INTERVAL_OBSERVATION)
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 2
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert mock_current.call_count == 1
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
async_fire_time_changed(hass, utcnow() + UPDATE_INTERVAL_DAILY_FORECAST)
|
assert mock_accuweather_client.async_get_daily_forecast.call_count == 2
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert mock_forecast.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_remove_ozone_sensors(
|
async def test_remove_ozone_sensors(
|
||||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test remove ozone sensors from registry."""
|
"""Test remove ozone sensors from registry."""
|
||||||
entity_registry.async_get_or_create(
|
entity_registry.async_get_or_create(
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
"""Test sensor of AccuWeather integration."""
|
"""Test sensor of AccuWeather integration."""
|
||||||
|
|
||||||
from datetime import timedelta
|
from unittest.mock import AsyncMock, patch
|
||||||
from unittest.mock import PropertyMock, patch
|
|
||||||
|
|
||||||
from accuweather import ApiError, InvalidApiKeyError, RequestsExceededError
|
from accuweather import ApiError, InvalidApiKeyError, RequestsExceededError
|
||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.accuweather.const import UPDATE_INTERVAL_DAILY_FORECAST
|
from homeassistant.components.accuweather.const import (
|
||||||
|
UPDATE_INTERVAL_DAILY_FORECAST,
|
||||||
|
UPDATE_INTERVAL_OBSERVATION,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
|
@ -21,23 +24,18 @@ from homeassistant.const import (
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util.dt import utcnow
|
|
||||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||||
|
|
||||||
from . import init_integration
|
from . import init_integration
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import async_fire_time_changed, snapshot_platform
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_array_fixture,
|
|
||||||
load_json_object_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_sensor(
|
async def test_sensor(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_registry_enabled_by_default: None,
|
entity_registry_enabled_by_default: None,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test states of the sensor."""
|
"""Test states of the sensor."""
|
||||||
|
@ -46,64 +44,59 @@ async def test_sensor(
|
||||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
async def test_availability(hass: HomeAssistant) -> None:
|
async def test_availability(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
||||||
|
entity_id = "sensor.home_cloud_ceiling"
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
state = hass.states.get("sensor.home_cloud_ceiling")
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state != STATE_UNAVAILABLE
|
assert state.state != STATE_UNAVAILABLE
|
||||||
assert state.state == "3200.0"
|
assert state.state == "3200.0"
|
||||||
|
|
||||||
future = utcnow() + timedelta(minutes=60)
|
mock_accuweather_client.async_get_current_conditions.side_effect = ConnectionError
|
||||||
with patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
|
||||||
side_effect=ConnectionError(),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, future)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.home_cloud_ceiling")
|
freezer.tick(UPDATE_INTERVAL_OBSERVATION)
|
||||||
assert state
|
async_fire_time_changed(hass)
|
||||||
assert state.state == STATE_UNAVAILABLE
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
future = utcnow() + timedelta(minutes=120)
|
state = hass.states.get(entity_id)
|
||||||
with (
|
assert state
|
||||||
patch(
|
assert state.state == STATE_UNAVAILABLE
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
|
||||||
return_value=load_json_object_fixture(
|
|
||||||
"accuweather/current_conditions_data.json"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, future)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.home_cloud_ceiling")
|
mock_accuweather_client.async_get_current_conditions.side_effect = None
|
||||||
assert state
|
|
||||||
assert state.state != STATE_UNAVAILABLE
|
freezer.tick(UPDATE_INTERVAL_OBSERVATION)
|
||||||
assert state.state == "3200.0"
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state
|
||||||
|
assert state.state != STATE_UNAVAILABLE
|
||||||
|
assert state.state == "3200.0"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"exception",
|
"exception",
|
||||||
[
|
[
|
||||||
ApiError,
|
ApiError("API Error"),
|
||||||
ConnectionError,
|
ConnectionError,
|
||||||
ClientConnectorError,
|
ClientConnectorError,
|
||||||
InvalidApiKeyError,
|
InvalidApiKeyError("Invalid API key"),
|
||||||
RequestsExceededError,
|
RequestsExceededError("Requests exceeded"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_availability_forecast(hass: HomeAssistant, exception: Exception) -> None:
|
async def test_availability_forecast(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
exception: Exception,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
|
||||||
forecast = load_json_array_fixture("accuweather/forecast_data.json")
|
|
||||||
entity_id = "sensor.home_hours_of_sun_day_2"
|
entity_id = "sensor.home_hours_of_sun_day_2"
|
||||||
|
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
@ -113,45 +106,21 @@ async def test_availability_forecast(hass: HomeAssistant, exception: Exception)
|
||||||
assert state.state != STATE_UNAVAILABLE
|
assert state.state != STATE_UNAVAILABLE
|
||||||
assert state.state == "5.7"
|
assert state.state == "5.7"
|
||||||
|
|
||||||
with (
|
mock_accuweather_client.async_get_daily_forecast.side_effect = exception
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST)
|
||||||
return_value=current,
|
async_fire_time_changed(hass)
|
||||||
),
|
await hass.async_block_till_done()
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_daily_forecast",
|
|
||||||
side_effect=exception,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, utcnow() + UPDATE_INTERVAL_DAILY_FORECAST)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
with (
|
mock_accuweather_client.async_get_daily_forecast.side_effect = None
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST)
|
||||||
return_value=current,
|
async_fire_time_changed(hass)
|
||||||
),
|
await hass.async_block_till_done()
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_daily_forecast",
|
|
||||||
return_value=forecast,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, utcnow() + UPDATE_INTERVAL_DAILY_FORECAST * 2)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
|
@ -159,35 +128,29 @@ async def test_availability_forecast(hass: HomeAssistant, exception: Exception)
|
||||||
assert state.state == "5.7"
|
assert state.state == "5.7"
|
||||||
|
|
||||||
|
|
||||||
async def test_manual_update_entity(hass: HomeAssistant) -> None:
|
async def test_manual_update_entity(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test manual update entity via service homeassistant/update_entity."""
|
"""Test manual update entity via service homeassistant/update_entity."""
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
await async_setup_component(hass, "homeassistant", {})
|
await async_setup_component(hass, "homeassistant", {})
|
||||||
|
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 1
|
||||||
|
|
||||||
with (
|
await hass.services.async_call(
|
||||||
patch(
|
"homeassistant",
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
"update_entity",
|
||||||
return_value=current,
|
{ATTR_ENTITY_ID: ["sensor.home_cloud_ceiling"]},
|
||||||
) as mock_current,
|
blocking=True,
|
||||||
patch(
|
)
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 2
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
await hass.services.async_call(
|
|
||||||
"homeassistant",
|
|
||||||
"update_entity",
|
|
||||||
{ATTR_ENTITY_ID: ["sensor.home_cloud_ceiling"]},
|
|
||||||
blocking=True,
|
|
||||||
)
|
|
||||||
assert mock_current.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_sensor_imperial_units(hass: HomeAssistant) -> None:
|
async def test_sensor_imperial_units(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test states of the sensor without forecast."""
|
"""Test states of the sensor without forecast."""
|
||||||
hass.config.units = US_CUSTOMARY_SYSTEM
|
hass.config.units = US_CUSTOMARY_SYSTEM
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
@ -210,37 +173,30 @@ async def test_sensor_imperial_units(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_state_update(hass: HomeAssistant) -> None:
|
async def test_state_update(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
"""Ensure the sensor state changes after updating the data."""
|
"""Ensure the sensor state changes after updating the data."""
|
||||||
|
entity_id = "sensor.home_cloud_ceiling"
|
||||||
|
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
state = hass.states.get("sensor.home_cloud_ceiling")
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state != STATE_UNAVAILABLE
|
assert state.state != STATE_UNAVAILABLE
|
||||||
assert state.state == "3200.0"
|
assert state.state == "3200.0"
|
||||||
|
|
||||||
future = utcnow() + timedelta(minutes=60)
|
mock_accuweather_client.async_get_current_conditions.return_value["Ceiling"][
|
||||||
|
"Metric"
|
||||||
|
]["Value"] = 3300
|
||||||
|
|
||||||
current_condition = load_json_object_fixture(
|
freezer.tick(UPDATE_INTERVAL_OBSERVATION)
|
||||||
"accuweather/current_conditions_data.json"
|
async_fire_time_changed(hass)
|
||||||
)
|
await hass.async_block_till_done()
|
||||||
current_condition["Ceiling"]["Metric"]["Value"] = 3300
|
|
||||||
|
|
||||||
with (
|
state = hass.states.get(entity_id)
|
||||||
patch(
|
assert state
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
assert state.state != STATE_UNAVAILABLE
|
||||||
return_value=current_condition,
|
assert state.state == "3300"
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, future)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get("sensor.home_cloud_ceiling")
|
|
||||||
assert state
|
|
||||||
assert state.state != STATE_UNAVAILABLE
|
|
||||||
assert state.state == "3300"
|
|
||||||
|
|
|
@ -1,34 +1,32 @@
|
||||||
"""Test AccuWeather system health."""
|
"""Test AccuWeather system health."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from unittest.mock import Mock
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from aiohttp import ClientError
|
from aiohttp import ClientError
|
||||||
|
|
||||||
from homeassistant.components.accuweather import AccuWeatherData
|
|
||||||
from homeassistant.components.accuweather.const import DOMAIN
|
from homeassistant.components.accuweather.const import DOMAIN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
from . import init_integration
|
||||||
|
|
||||||
from tests.common import get_system_health_info
|
from tests.common import get_system_health_info
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
|
|
||||||
async def test_accuweather_system_health(
|
async def test_accuweather_system_health(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test AccuWeather system health."""
|
"""Test AccuWeather system health."""
|
||||||
aioclient_mock.get("https://dataservice.accuweather.com/", text="")
|
aioclient_mock.get("https://dataservice.accuweather.com/", text="")
|
||||||
hass.config.components.add(DOMAIN)
|
|
||||||
|
await init_integration(hass)
|
||||||
assert await async_setup_component(hass, "system_health", {})
|
assert await async_setup_component(hass, "system_health", {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.data[DOMAIN] = {}
|
|
||||||
hass.data[DOMAIN]["0123xyz"] = AccuWeatherData(
|
|
||||||
coordinator_observation=Mock(accuweather=Mock(requests_remaining="42")),
|
|
||||||
coordinator_daily_forecast=Mock(),
|
|
||||||
)
|
|
||||||
|
|
||||||
info = await get_system_health_info(hass, DOMAIN)
|
info = await get_system_health_info(hass, DOMAIN)
|
||||||
|
|
||||||
for key, val in info.items():
|
for key, val in info.items():
|
||||||
|
@ -37,25 +35,22 @@ async def test_accuweather_system_health(
|
||||||
|
|
||||||
assert info == {
|
assert info == {
|
||||||
"can_reach_server": "ok",
|
"can_reach_server": "ok",
|
||||||
"remaining_requests": "42",
|
"remaining_requests": 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_accuweather_system_health_fail(
|
async def test_accuweather_system_health_fail(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant,
|
||||||
|
aioclient_mock: AiohttpClientMocker,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test AccuWeather system health."""
|
"""Test AccuWeather system health."""
|
||||||
aioclient_mock.get("https://dataservice.accuweather.com/", exc=ClientError)
|
aioclient_mock.get("https://dataservice.accuweather.com/", exc=ClientError)
|
||||||
hass.config.components.add(DOMAIN)
|
|
||||||
|
await init_integration(hass)
|
||||||
assert await async_setup_component(hass, "system_health", {})
|
assert await async_setup_component(hass, "system_health", {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
hass.data[DOMAIN] = {}
|
|
||||||
hass.data[DOMAIN]["0123xyz"] = AccuWeatherData(
|
|
||||||
coordinator_observation=Mock(accuweather=Mock(requests_remaining="0")),
|
|
||||||
coordinator_daily_forecast=Mock(),
|
|
||||||
)
|
|
||||||
|
|
||||||
info = await get_system_health_info(hass, DOMAIN)
|
info = await get_system_health_info(hass, DOMAIN)
|
||||||
|
|
||||||
for key, val in info.items():
|
for key, val in info.items():
|
||||||
|
@ -64,5 +59,5 @@ async def test_accuweather_system_health_fail(
|
||||||
|
|
||||||
assert info == {
|
assert info == {
|
||||||
"can_reach_server": {"type": "failed", "error": "unreachable"},
|
"can_reach_server": {"type": "failed", "error": "unreachable"},
|
||||||
"remaining_requests": "0",
|
"remaining_requests": 10,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Test weather of AccuWeather integration."""
|
"""Test weather of AccuWeather integration."""
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unittest.mock import PropertyMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -18,21 +18,18 @@ from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util.dt import utcnow
|
|
||||||
|
|
||||||
from . import init_integration
|
from . import init_integration
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import async_fire_time_changed, snapshot_platform
|
||||||
async_fire_time_changed,
|
|
||||||
load_json_array_fixture,
|
|
||||||
load_json_object_fixture,
|
|
||||||
snapshot_platform,
|
|
||||||
)
|
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
|
|
||||||
async def test_weather(
|
async def test_weather(
|
||||||
hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test states of the weather without forecast."""
|
"""Test states of the weather without forecast."""
|
||||||
with patch("homeassistant.components.accuweather.PLATFORMS", [Platform.WEATHER]):
|
with patch("homeassistant.components.accuweather.PLATFORMS", [Platform.WEATHER]):
|
||||||
|
@ -40,81 +37,71 @@ async def test_weather(
|
||||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
async def test_availability(hass: HomeAssistant) -> None:
|
async def test_availability(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
"""Ensure that we mark the entities unavailable correctly when service is offline."""
|
||||||
|
entity_id = "weather.home"
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
state = hass.states.get("weather.home")
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state != STATE_UNAVAILABLE
|
assert state.state != STATE_UNAVAILABLE
|
||||||
assert state.state == "sunny"
|
assert state.state == "sunny"
|
||||||
|
|
||||||
future = utcnow() + timedelta(minutes=60)
|
mock_accuweather_client.async_get_current_conditions.side_effect = ConnectionError
|
||||||
with patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather._async_get_data",
|
|
||||||
side_effect=ConnectionError(),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, future)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get("weather.home")
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST)
|
||||||
assert state
|
async_fire_time_changed(hass)
|
||||||
assert state.state == STATE_UNAVAILABLE
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
future = utcnow() + timedelta(minutes=120)
|
state = hass.states.get(entity_id)
|
||||||
with (
|
assert state
|
||||||
patch(
|
assert state.state == STATE_UNAVAILABLE
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
|
||||||
return_value=load_json_object_fixture(
|
|
||||||
"accuweather/current_conditions_data.json"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
async_fire_time_changed(hass, future)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
state = hass.states.get("weather.home")
|
mock_accuweather_client.async_get_current_conditions.side_effect = None
|
||||||
assert state
|
|
||||||
assert state.state != STATE_UNAVAILABLE
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST)
|
||||||
assert state.state == "sunny"
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state
|
||||||
|
assert state.state != STATE_UNAVAILABLE
|
||||||
|
assert state.state == "sunny"
|
||||||
|
|
||||||
|
|
||||||
async def test_manual_update_entity(hass: HomeAssistant) -> None:
|
async def test_manual_update_entity(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test manual update entity via service homeassistant/update_entity."""
|
"""Test manual update entity via service homeassistant/update_entity."""
|
||||||
await init_integration(hass)
|
await init_integration(hass)
|
||||||
|
|
||||||
await async_setup_component(hass, "homeassistant", {})
|
await async_setup_component(hass, "homeassistant", {})
|
||||||
|
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 1
|
||||||
|
|
||||||
with (
|
await hass.services.async_call(
|
||||||
patch(
|
"homeassistant",
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
"update_entity",
|
||||||
return_value=current,
|
{ATTR_ENTITY_ID: ["weather.home"]},
|
||||||
) as mock_current,
|
blocking=True,
|
||||||
patch(
|
)
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
assert mock_accuweather_client.async_get_current_conditions.call_count == 2
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
await hass.services.async_call(
|
|
||||||
"homeassistant",
|
|
||||||
"update_entity",
|
|
||||||
{ATTR_ENTITY_ID: ["weather.home"]},
|
|
||||||
blocking=True,
|
|
||||||
)
|
|
||||||
assert mock_current.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_unsupported_condition_icon_data(hass: HomeAssistant) -> None:
|
async def test_unsupported_condition_icon_data(
|
||||||
|
hass: HomeAssistant, mock_accuweather_client: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test with unsupported condition icon data."""
|
"""Test with unsupported condition icon data."""
|
||||||
await init_integration(hass, unsupported_icon=True)
|
mock_accuweather_client.async_get_current_conditions.return_value["WeatherIcon"] = (
|
||||||
|
999
|
||||||
|
)
|
||||||
|
|
||||||
|
await init_integration(hass)
|
||||||
|
|
||||||
state = hass.states.get("weather.home")
|
state = hass.states.get("weather.home")
|
||||||
assert state.attributes.get(ATTR_FORECAST_CONDITION) is None
|
assert state.attributes.get(ATTR_FORECAST_CONDITION) is None
|
||||||
|
@ -130,6 +117,7 @@ async def test_unsupported_condition_icon_data(hass: HomeAssistant) -> None:
|
||||||
async def test_forecast_service(
|
async def test_forecast_service(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
service: str,
|
service: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test multiple forecast."""
|
"""Test multiple forecast."""
|
||||||
|
@ -153,6 +141,7 @@ async def test_forecast_subscription(
|
||||||
hass_ws_client: WebSocketGenerator,
|
hass_ws_client: WebSocketGenerator,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
|
mock_accuweather_client: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test multiple forecast."""
|
"""Test multiple forecast."""
|
||||||
client = await hass_ws_client(hass)
|
client = await hass_ws_client(hass)
|
||||||
|
@ -179,27 +168,9 @@ async def test_forecast_subscription(
|
||||||
assert forecast1 != []
|
assert forecast1 != []
|
||||||
assert forecast1 == snapshot
|
assert forecast1 == snapshot
|
||||||
|
|
||||||
current = load_json_object_fixture("accuweather/current_conditions_data.json")
|
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST + timedelta(seconds=1))
|
||||||
forecast = load_json_array_fixture("accuweather/forecast_data.json")
|
await hass.async_block_till_done()
|
||||||
|
msg = await client.receive_json()
|
||||||
with (
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
|
|
||||||
return_value=current,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.async_get_daily_forecast",
|
|
||||||
return_value=forecast,
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"homeassistant.components.accuweather.AccuWeather.requests_remaining",
|
|
||||||
new_callable=PropertyMock,
|
|
||||||
return_value=10,
|
|
||||||
),
|
|
||||||
):
|
|
||||||
freezer.tick(UPDATE_INTERVAL_DAILY_FORECAST + timedelta(seconds=1))
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
msg = await client.receive_json()
|
|
||||||
|
|
||||||
assert msg["id"] == subscription_id
|
assert msg["id"] == subscription_id
|
||||||
assert msg["type"] == "event"
|
assert msg["type"] == "event"
|
||||||
|
|
Loading…
Add table
Reference in a new issue