From 1e63665bf259d27a7c4e8623244a69b60e537cc7 Mon Sep 17 00:00:00 2001 From: andarotajo <55669170+andarotajo@users.noreply.github.com> Date: Tue, 30 Apr 2024 18:08:15 +0200 Subject: [PATCH] Mock dwdwfsapi in all tests that use it (#116414) * Mock dwdwfsapi in all tests * Add mocking for config entries * Fix assertions in init test --- .../dwd_weather_warnings/__init__.py | 15 +++ .../dwd_weather_warnings/conftest.py | 73 +++++++++++++- .../dwd_weather_warnings/test_config_flow.py | 84 +++++++--------- .../dwd_weather_warnings/test_init.py | 99 ++++++++----------- 4 files changed, 164 insertions(+), 107 deletions(-) diff --git a/tests/components/dwd_weather_warnings/__init__.py b/tests/components/dwd_weather_warnings/__init__.py index 03d27d28503341..d349f1e7b81137 100644 --- a/tests/components/dwd_weather_warnings/__init__.py +++ b/tests/components/dwd_weather_warnings/__init__.py @@ -1 +1,16 @@ """Tests for Deutscher Wetterdienst (DWD) Weather Warnings.""" + +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + + +async def init_integration( + hass: HomeAssistant, entry: MockConfigEntry +) -> MockConfigEntry: + """Set up the integration based on the config entry.""" + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + return entry diff --git a/tests/components/dwd_weather_warnings/conftest.py b/tests/components/dwd_weather_warnings/conftest.py index a09f6cb2fb3cd1..a2932944cc2531 100644 --- a/tests/components/dwd_weather_warnings/conftest.py +++ b/tests/components/dwd_weather_warnings/conftest.py @@ -1,10 +1,26 @@ """Configuration for Deutscher Wetterdienst (DWD) Weather Warnings tests.""" from collections.abc import Generator -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest +from homeassistant.components.dwd_weather_warnings.const import ( + ADVANCE_WARNING_SENSOR, + CONF_REGION_DEVICE_TRACKER, + CONF_REGION_IDENTIFIER, + CURRENT_WARNING_SENSOR, + DOMAIN, +) +from homeassistant.const import CONF_MONITORED_CONDITIONS, CONF_NAME + +from tests.common import MockConfigEntry + +MOCK_NAME = "Unit Test" +MOCK_REGION_IDENTIFIER = "807111000" +MOCK_REGION_DEVICE_TRACKER = "device_tracker.test_gps" +MOCK_CONDITIONS = [CURRENT_WARNING_SENSOR, ADVANCE_WARNING_SENSOR] + @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock, None, None]: @@ -14,3 +30,58 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]: return_value=True, ) as mock_setup_entry: yield mock_setup_entry + + +@pytest.fixture +def mock_identifier_entry() -> MockConfigEntry: + """Return a mocked config entry with a region identifier.""" + return MockConfigEntry( + domain=DOMAIN, + data={ + CONF_NAME: MOCK_NAME, + CONF_REGION_IDENTIFIER: MOCK_REGION_IDENTIFIER, + CONF_MONITORED_CONDITIONS: MOCK_CONDITIONS, + }, + ) + + +@pytest.fixture +def mock_tracker_entry() -> MockConfigEntry: + """Return a mocked config entry with a region identifier.""" + return MockConfigEntry( + domain=DOMAIN, + data={ + CONF_NAME: MOCK_NAME, + CONF_REGION_DEVICE_TRACKER: MOCK_REGION_DEVICE_TRACKER, + CONF_MONITORED_CONDITIONS: MOCK_CONDITIONS, + }, + ) + + +@pytest.fixture +def mock_dwdwfsapi() -> Generator[MagicMock, None, None]: + """Return a mocked dwdwfsapi API client.""" + with ( + patch( + "homeassistant.components.dwd_weather_warnings.coordinator.DwdWeatherWarningsAPI", + autospec=True, + ) as mock_api, + patch( + "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", + new=mock_api, + ), + ): + api = mock_api.return_value + api.data_valid = False + api.warncell_id = None + api.warncell_name = None + api.last_update = None + api.current_warning_level = None + api.current_warnings = None + api.expected_warning_level = None + api.expected_warnings = None + api.update = Mock() + api.__bool__ = Mock() + api.__bool__.return_value = True + + yield api diff --git a/tests/components/dwd_weather_warnings/test_config_flow.py b/tests/components/dwd_weather_warnings/test_config_flow.py index 119c029767a146..dfdef0196cbaf9 100644 --- a/tests/components/dwd_weather_warnings/test_config_flow.py +++ b/tests/components/dwd_weather_warnings/test_config_flow.py @@ -1,7 +1,7 @@ """Tests for Deutscher Wetterdienst (DWD) Weather Warnings config flow.""" from typing import Final -from unittest.mock import patch +from unittest.mock import MagicMock import pytest @@ -29,7 +29,9 @@ pytestmark = pytest.mark.usefixtures("mock_setup_entry") -async def test_create_entry_region(hass: HomeAssistant) -> None: +async def test_create_entry_region( + hass: HomeAssistant, mock_dwdwfsapi: MagicMock +) -> None: """Test that the full config flow works for a region identifier.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} @@ -37,26 +39,20 @@ async def test_create_entry_region(hass: HomeAssistant) -> None: await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM - with patch( - "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", - return_value=False, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION - ) + mock_dwdwfsapi.__bool__.return_value = False + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION + ) # Test for invalid region identifier. await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "invalid_identifier"} - with patch( - "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", - return_value=True, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION - ) + mock_dwdwfsapi.__bool__.return_value = True + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION + ) # Test for successfully created entry. await hass.async_block_till_done() @@ -68,14 +64,14 @@ async def test_create_entry_region(hass: HomeAssistant) -> None: async def test_create_entry_gps( - hass: HomeAssistant, entity_registry: er.EntityRegistry + hass: HomeAssistant, entity_registry: er.EntityRegistry, mock_dwdwfsapi: MagicMock ) -> None: """Test that the full config flow works for a device tracker.""" result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM # Test for missing registry entry error. result = await hass.config_entries.flow.async_configure( @@ -83,7 +79,7 @@ async def test_create_entry_gps( ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "entity_not_found"} # Test for missing device tracker error. @@ -96,7 +92,7 @@ async def test_create_entry_gps( ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "entity_not_found"} # Test for missing attribute error. @@ -111,7 +107,7 @@ async def test_create_entry_gps( ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "attribute_not_found"} # Test for invalid provided identifier. @@ -121,36 +117,32 @@ async def test_create_entry_gps( {ATTR_LATITUDE: "50.180454", ATTR_LONGITUDE: "7.610263"}, ) - with patch( - "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", - return_value=False, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=DEMO_CONFIG_ENTRY_GPS - ) + mock_dwdwfsapi.__bool__.return_value = False + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=DEMO_CONFIG_ENTRY_GPS + ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "invalid_identifier"} # Test for successfully created entry. - with patch( - "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", - return_value=True, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=DEMO_CONFIG_ENTRY_GPS - ) + mock_dwdwfsapi.__bool__.return_value = True + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=DEMO_CONFIG_ENTRY_GPS + ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.CREATE_ENTRY + assert result["type"] is FlowResultType.CREATE_ENTRY assert result["title"] == "test_gps" assert result["data"] == { CONF_REGION_DEVICE_TRACKER: registry_entry.id, } -async def test_config_flow_already_configured(hass: HomeAssistant) -> None: +async def test_config_flow_already_configured( + hass: HomeAssistant, mock_dwdwfsapi: MagicMock +) -> None: """Test aborting, if the warncell ID / name is already configured during the config.""" entry = MockConfigEntry( domain=DOMAIN, @@ -167,13 +159,9 @@ async def test_config_flow_already_configured(hass: HomeAssistant) -> None: await hass.async_block_till_done() assert result["type"] is FlowResultType.FORM - with patch( - "homeassistant.components.dwd_weather_warnings.config_flow.DwdWeatherWarningsAPI", - return_value=True, - ): - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION - ) + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input=DEMO_CONFIG_ENTRY_REGION + ) await hass.async_block_till_done() assert result["type"] is FlowResultType.ABORT @@ -187,7 +175,7 @@ async def test_config_flow_with_errors(hass: HomeAssistant) -> None: ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM # Test error for empty input data. result = await hass.config_entries.flow.async_configure( @@ -195,7 +183,7 @@ async def test_config_flow_with_errors(hass: HomeAssistant) -> None: ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "no_identifier"} # Test error for setting both options during configuration. @@ -207,5 +195,5 @@ async def test_config_flow_with_errors(hass: HomeAssistant) -> None: ) await hass.async_block_till_done() - assert result["type"] == FlowResultType.FORM + assert result["type"] is FlowResultType.FORM assert result["errors"] == {"base": "ambiguous_identifier"} diff --git a/tests/components/dwd_weather_warnings/test_init.py b/tests/components/dwd_weather_warnings/test_init.py index bfd03b2fdd4db4..360efc390db6ed 100644 --- a/tests/components/dwd_weather_warnings/test_init.py +++ b/tests/components/dwd_weather_warnings/test_init.py @@ -1,46 +1,28 @@ """Tests for Deutscher Wetterdienst (DWD) Weather Warnings integration.""" -from typing import Final +from unittest.mock import MagicMock from homeassistant.components.dwd_weather_warnings.const import ( - ADVANCE_WARNING_SENSOR, CONF_REGION_DEVICE_TRACKER, - CONF_REGION_IDENTIFIER, - CURRENT_WARNING_SENSOR, DOMAIN, ) from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import ( - ATTR_LATITUDE, - ATTR_LONGITUDE, - CONF_MONITORED_CONDITIONS, - CONF_NAME, - STATE_HOME, -) +from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, STATE_HOME from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er -from tests.common import MockConfigEntry - -DEMO_IDENTIFIER_CONFIG_ENTRY: Final = { - CONF_NAME: "Unit Test", - CONF_REGION_IDENTIFIER: "807111000", - CONF_MONITORED_CONDITIONS: [CURRENT_WARNING_SENSOR, ADVANCE_WARNING_SENSOR], -} +from . import init_integration -DEMO_TRACKER_CONFIG_ENTRY: Final = { - CONF_NAME: "Unit Test", - CONF_REGION_DEVICE_TRACKER: "device_tracker.test_gps", - CONF_MONITORED_CONDITIONS: [CURRENT_WARNING_SENSOR, ADVANCE_WARNING_SENSOR], -} +from tests.common import MockConfigEntry -async def test_load_unload_entry(hass: HomeAssistant) -> None: +async def test_load_unload_entry( + hass: HomeAssistant, + mock_identifier_entry: MockConfigEntry, + mock_dwdwfsapi: MagicMock, +) -> None: """Test loading and unloading the integration with a region identifier based entry.""" - entry = MockConfigEntry(domain=DOMAIN, data=DEMO_IDENTIFIER_CONFIG_ENTRY) - entry.add_to_hass(hass) - await hass.config_entries.async_setup(entry.entry_id) - await hass.async_block_till_done() + entry = await init_integration(hass, mock_identifier_entry) assert entry.state is ConfigEntryState.LOADED assert entry.entry_id in hass.data[DOMAIN] @@ -52,66 +34,67 @@ async def test_load_unload_entry(hass: HomeAssistant) -> None: assert entry.entry_id not in hass.data[DOMAIN] -async def test_load_invalid_registry_entry(hass: HomeAssistant) -> None: +async def test_load_invalid_registry_entry( + hass: HomeAssistant, mock_tracker_entry: MockConfigEntry +) -> None: """Test loading the integration with an invalid registry entry ID.""" - INVALID_DATA = DEMO_TRACKER_CONFIG_ENTRY.copy() + INVALID_DATA = mock_tracker_entry.data.copy() INVALID_DATA[CONF_REGION_DEVICE_TRACKER] = "invalid_registry_id" - entry = MockConfigEntry(domain=DOMAIN, data=INVALID_DATA) - entry.add_to_hass(hass) - await hass.config_entries.async_setup(entry.entry_id) - await hass.async_block_till_done() - assert entry.state == ConfigEntryState.SETUP_RETRY + entry = await init_integration( + hass, MockConfigEntry(domain=DOMAIN, data=INVALID_DATA) + ) + assert entry.state is ConfigEntryState.SETUP_RETRY -async def test_load_missing_device_tracker(hass: HomeAssistant) -> None: +async def test_load_missing_device_tracker( + hass: HomeAssistant, mock_tracker_entry: MockConfigEntry +) -> None: """Test loading the integration with a missing device tracker.""" - entry = MockConfigEntry(domain=DOMAIN, data=DEMO_TRACKER_CONFIG_ENTRY) - entry.add_to_hass(hass) - - await hass.config_entries.async_setup(entry.entry_id) - await hass.async_block_till_done() - assert entry.state == ConfigEntryState.SETUP_RETRY + entry = await init_integration(hass, mock_tracker_entry) + assert entry.state is ConfigEntryState.SETUP_RETRY -async def test_load_missing_required_attribute(hass: HomeAssistant) -> None: +async def test_load_missing_required_attribute( + hass: HomeAssistant, mock_tracker_entry: MockConfigEntry +) -> None: """Test loading the integration with a device tracker missing a required attribute.""" - entry = MockConfigEntry(domain=DOMAIN, data=DEMO_TRACKER_CONFIG_ENTRY) - entry.add_to_hass(hass) - + mock_tracker_entry.add_to_hass(hass) hass.states.async_set( - DEMO_TRACKER_CONFIG_ENTRY[CONF_REGION_DEVICE_TRACKER], + mock_tracker_entry.data[CONF_REGION_DEVICE_TRACKER], STATE_HOME, {ATTR_LONGITUDE: "7.610263"}, ) - await hass.config_entries.async_setup(entry.entry_id) + await hass.config_entries.async_setup(mock_tracker_entry.entry_id) await hass.async_block_till_done() - assert entry.state == ConfigEntryState.SETUP_RETRY + assert mock_tracker_entry.state is ConfigEntryState.SETUP_RETRY async def test_load_valid_device_tracker( - hass: HomeAssistant, entity_registry: er.EntityRegistry + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + mock_tracker_entry: MockConfigEntry, + mock_dwdwfsapi: MagicMock, ) -> None: """Test loading the integration with a valid device tracker based entry.""" - entry = MockConfigEntry(domain=DOMAIN, data=DEMO_TRACKER_CONFIG_ENTRY) - entry.add_to_hass(hass) + mock_tracker_entry.add_to_hass(hass) entity_registry.async_get_or_create( "device_tracker", - entry.domain, + mock_tracker_entry.domain, "uuid", suggested_object_id="test_gps", - config_entry=entry, + config_entry=mock_tracker_entry, ) hass.states.async_set( - DEMO_TRACKER_CONFIG_ENTRY[CONF_REGION_DEVICE_TRACKER], + mock_tracker_entry.data[CONF_REGION_DEVICE_TRACKER], STATE_HOME, {ATTR_LATITUDE: "50.180454", ATTR_LONGITUDE: "7.610263"}, ) - await hass.config_entries.async_setup(entry.entry_id) + await hass.config_entries.async_setup(mock_tracker_entry.entry_id) await hass.async_block_till_done() - assert entry.state == ConfigEntryState.LOADED - assert entry.entry_id in hass.data[DOMAIN] + assert mock_tracker_entry.state is ConfigEntryState.LOADED + assert mock_tracker_entry.entry_id in hass.data[DOMAIN]