mirror of
https://github.com/jdejaegh/irm-kmi-ha.git
synced 2025-06-27 03:35:56 +02:00
Add test for config and repair flow
This commit is contained in:
parent
2cca89f5ba
commit
e53f9aded4
5 changed files with 255 additions and 4 deletions
|
@ -88,6 +88,6 @@ async def async_create_fix_flow(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
issue_id: str,
|
issue_id: str,
|
||||||
data: dict[str, str | int | float | None] | None,
|
data: dict[str, str | int | float | None] | None,
|
||||||
) -> RepairsFlow:
|
) -> OutOfBeneluxRepairFlow:
|
||||||
"""Create flow."""
|
"""Create flow."""
|
||||||
return OutOfBeneluxRepairFlow(data)
|
return OutOfBeneluxRepairFlow(data)
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
"use_deprecated_forecast_attribute": "Use the deprecated forecat attribute"
|
"use_deprecated_forecast_attribute": "Use the deprecated forecat attribute"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"out_of_benelux": "{zone} is out of Benelux. Pick a zone in Benelux.",
|
||||||
|
"api_error": "Could not get data from the API",
|
||||||
|
"zone_not_exist": "{zone} does not exist"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
|
@ -57,7 +62,7 @@
|
||||||
"fix_flow": {
|
"fix_flow": {
|
||||||
"step": {
|
"step": {
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"title": "Title for the confirm step",
|
"title": "Repair: {zone} is outside of Benelux",
|
||||||
"description": "This integration can only get data for location in the Benelux. Move the zone or delete this configuration entry."
|
"description": "This integration can only get data for location in the Benelux. Move the zone or delete this configuration entry."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -85,6 +85,14 @@ def mock_get_forecast_api_error():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_get_forecast_api_error_repair():
|
||||||
|
"""Mock a call to IrmKmiApiClient.get_forecasts_coord() so that it raises an error"""
|
||||||
|
with patch("custom_components.irm_kmi.repairs.IrmKmiApiClient.get_forecasts_coord",
|
||||||
|
side_effet=IrmKmiApiError):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
def mock_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
"""Return a mocked IrmKmi api client."""
|
"""Return a mocked IrmKmi api client."""
|
||||||
|
@ -100,7 +108,7 @@ def mock_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMoc
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_irm_kmi_api_out_benelux(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
def mock_irm_kmi_api_coordinator_out_benelux(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
"""Return a mocked IrmKmi api client."""
|
"""Return a mocked IrmKmi api client."""
|
||||||
fixture: str = "forecast_out_of_benelux.json"
|
fixture: str = "forecast_out_of_benelux.json"
|
||||||
|
|
||||||
|
@ -113,6 +121,34 @@ def mock_irm_kmi_api_out_benelux(request: pytest.FixtureRequest) -> Generator[No
|
||||||
yield irm_kmi
|
yield irm_kmi
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_irm_kmi_api_repair_in_benelux(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
|
"""Return a mocked IrmKmi api client."""
|
||||||
|
fixture: str = "forecast.json"
|
||||||
|
|
||||||
|
forecast = json.loads(load_fixture(fixture))
|
||||||
|
with patch(
|
||||||
|
"custom_components.irm_kmi.repairs.IrmKmiApiClient", autospec=True
|
||||||
|
) as irm_kmi_api_mock:
|
||||||
|
irm_kmi = irm_kmi_api_mock.return_value
|
||||||
|
irm_kmi.get_forecasts_coord.return_value = forecast
|
||||||
|
yield irm_kmi
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_irm_kmi_api_repair_out_of_benelux(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
|
"""Return a mocked IrmKmi api client."""
|
||||||
|
fixture: str = "forecast_out_of_benelux.json"
|
||||||
|
|
||||||
|
forecast = json.loads(load_fixture(fixture))
|
||||||
|
with patch(
|
||||||
|
"custom_components.irm_kmi.repairs.IrmKmiApiClient", autospec=True
|
||||||
|
) as irm_kmi_api_mock:
|
||||||
|
irm_kmi = irm_kmi_api_mock.return_value
|
||||||
|
irm_kmi.get_forecasts_coord.return_value = forecast
|
||||||
|
yield irm_kmi
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_exception_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
def mock_exception_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
"""Return a mocked IrmKmi api client."""
|
"""Return a mocked IrmKmi api client."""
|
||||||
|
|
|
@ -13,7 +13,7 @@ from custom_components.irm_kmi import async_migrate_entry
|
||||||
from custom_components.irm_kmi.const import (
|
from custom_components.irm_kmi.const import (
|
||||||
CONF_DARK_MODE, CONF_STYLE, CONF_USE_DEPRECATED_FORECAST,
|
CONF_DARK_MODE, CONF_STYLE, CONF_USE_DEPRECATED_FORECAST,
|
||||||
CONFIG_FLOW_VERSION, DOMAIN, OPTION_DEPRECATED_FORECAST_NOT_USED,
|
CONFIG_FLOW_VERSION, DOMAIN, OPTION_DEPRECATED_FORECAST_NOT_USED,
|
||||||
OPTION_STYLE_STD)
|
OPTION_STYLE_SATELLITE, OPTION_STYLE_STD)
|
||||||
|
|
||||||
|
|
||||||
async def test_full_user_flow(
|
async def test_full_user_flow(
|
||||||
|
@ -86,6 +86,53 @@ async def test_config_flow_with_api_error(
|
||||||
assert 'base' in result2.get('errors')
|
assert 'base' in result2.get('errors')
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_flow_unknown_zone(hass: HomeAssistant) -> None:
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
|
)
|
||||||
|
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={CONF_ZONE: "zone.what",
|
||||||
|
CONF_STYLE: OPTION_STYLE_STD,
|
||||||
|
CONF_DARK_MODE: False},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2.get("type") == FlowResultType.FORM
|
||||||
|
assert result2.get("step_id") == "user"
|
||||||
|
assert CONF_ZONE in result2.get('errors')
|
||||||
|
|
||||||
|
|
||||||
|
async def test_option_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert not mock_config_entry.options
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id, data=None)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_STYLE: OPTION_STYLE_SATELLITE,
|
||||||
|
CONF_DARK_MODE: True,
|
||||||
|
CONF_USE_DEPRECATED_FORECAST: OPTION_DEPRECATED_FORECAST_NOT_USED
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
CONF_STYLE: OPTION_STYLE_SATELLITE,
|
||||||
|
CONF_DARK_MODE: True,
|
||||||
|
CONF_USE_DEPRECATED_FORECAST: OPTION_DEPRECATED_FORECAST_NOT_USED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_config_entry_migration(hass: HomeAssistant) -> None:
|
async def test_config_entry_migration(hass: HomeAssistant) -> None:
|
||||||
"""Ensure that config entry migration takes the configuration to the latest version"""
|
"""Ensure that config entry migration takes the configuration to the latest version"""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
|
|
163
tests/test_repairs.py
Normal file
163
tests/test_repairs.py
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
import logging
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
from homeassistant.helpers import issue_registry
|
||||||
|
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||||
|
|
||||||
|
from custom_components.irm_kmi import DOMAIN, IrmKmiCoordinator
|
||||||
|
from custom_components.irm_kmi.const import (REPAIR_OPT_DELETE,
|
||||||
|
REPAIR_OPT_MOVE, REPAIR_SOLUTION)
|
||||||
|
from custom_components.irm_kmi.repairs import (OutOfBeneluxRepairFlow,
|
||||||
|
async_create_fix_flow)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_repair_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> OutOfBeneluxRepairFlow:
|
||||||
|
hass.states.async_set(
|
||||||
|
"zone.home",
|
||||||
|
0,
|
||||||
|
{"latitude": 50.738681639, "longitude": 4.054077148},
|
||||||
|
)
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
coordinator = IrmKmiCoordinator(hass, mock_config_entry)
|
||||||
|
await coordinator._async_update_data()
|
||||||
|
ir = issue_registry.async_get(hass)
|
||||||
|
issue = ir.async_get_issue(DOMAIN, "zone_moved")
|
||||||
|
repair_flow = await async_create_fix_flow(hass, issue.issue_id, issue.data)
|
||||||
|
repair_flow.hass = hass
|
||||||
|
return repair_flow
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_triggers_when_out_of_benelux(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
hass.states.async_set(
|
||||||
|
"zone.home",
|
||||||
|
0,
|
||||||
|
{"latitude": 50.738681639, "longitude": 4.054077148},
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
coordinator = IrmKmiCoordinator(hass, mock_config_entry)
|
||||||
|
await coordinator._async_update_data()
|
||||||
|
|
||||||
|
ir = issue_registry.async_get(hass)
|
||||||
|
|
||||||
|
issue = ir.async_get_issue(DOMAIN, "zone_moved")
|
||||||
|
|
||||||
|
assert issue is not None
|
||||||
|
assert issue.data == {'config_entry_id': mock_config_entry.entry_id, 'zone': "zone.home"}
|
||||||
|
assert issue.translation_key == "zone_moved"
|
||||||
|
assert issue.is_fixable
|
||||||
|
assert issue.translation_placeholders == {'zone': "zone.home"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_irm_kmi_api_repair_in_benelux: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
repair_flow = await get_repair_flow(hass, mock_config_entry)
|
||||||
|
result = await repair_flow.async_step_init()
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
assert result['errors'] == {}
|
||||||
|
assert result['description_placeholders'] == {"zone": "zone.home"}
|
||||||
|
|
||||||
|
user_input = {REPAIR_SOLUTION: REPAIR_OPT_MOVE}
|
||||||
|
|
||||||
|
result = await repair_flow.async_step_confirm(user_input)
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result['title'] == ""
|
||||||
|
assert result['data'] == {}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_flow_invalid_choice(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_irm_kmi_api_repair_in_benelux: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
repair_flow = await get_repair_flow(hass, mock_config_entry)
|
||||||
|
result = await repair_flow.async_step_init()
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
user_input = {REPAIR_SOLUTION: "whut?"}
|
||||||
|
|
||||||
|
result = await repair_flow.async_step_confirm(user_input)
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
assert REPAIR_SOLUTION in result['errors']
|
||||||
|
assert result['errors'][REPAIR_SOLUTION] == 'invalid_choice'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_flow_api_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_get_forecast_api_error_repair: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
repair_flow = await get_repair_flow(hass, mock_config_entry)
|
||||||
|
result = await repair_flow.async_step_init()
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
user_input = {REPAIR_SOLUTION: REPAIR_OPT_MOVE}
|
||||||
|
|
||||||
|
result = await repair_flow.async_step_confirm(user_input)
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
assert REPAIR_SOLUTION in result['errors']
|
||||||
|
assert result['errors'][REPAIR_SOLUTION] == 'api_error'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_flow_out_of_benelux(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_irm_kmi_api_repair_out_of_benelux: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
repair_flow = await get_repair_flow(hass, mock_config_entry)
|
||||||
|
result = await repair_flow.async_step_init()
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
user_input = {REPAIR_SOLUTION: REPAIR_OPT_MOVE}
|
||||||
|
|
||||||
|
result = await repair_flow.async_step_confirm(user_input)
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
assert REPAIR_SOLUTION in result['errors']
|
||||||
|
assert result['errors'][REPAIR_SOLUTION] == 'out_of_benelux'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_repair_flow_delete_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_irm_kmi_api_coordinator_out_benelux: MagicMock,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
repair_flow = await get_repair_flow(hass, mock_config_entry)
|
||||||
|
result = await repair_flow.async_step_init()
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.FORM
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||||
|
assert hass.config_entries.async_entries(DOMAIN)[0].entry_id == mock_config_entry.entry_id
|
||||||
|
|
||||||
|
user_input = {REPAIR_SOLUTION: REPAIR_OPT_DELETE}
|
||||||
|
result = await repair_flow.async_step_confirm(user_input)
|
||||||
|
|
||||||
|
assert result['type'] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert result['title'] == ""
|
||||||
|
assert result['data'] == {}
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
Loading…
Add table
Reference in a new issue