core/tests/components/cookidoo/test_init.py

338 lines
9.3 KiB
Python

"""Unit tests for the cookidoo integration."""
from unittest.mock import AsyncMock
from cookidoo_api import CookidooAuthException, CookidooRequestException
import pytest
from homeassistant.components.cookidoo.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_COUNTRY,
CONF_EMAIL,
CONF_LANGUAGE,
CONF_PASSWORD,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import setup_integration
from .conftest import COUNTRY, EMAIL, LANGUAGE, PASSWORD, TEST_UUID
from tests.common import MockConfigEntry
@pytest.mark.usefixtures("mock_cookidoo_client")
async def test_load_unload(
hass: HomeAssistant,
cookidoo_config_entry: MockConfigEntry,
) -> None:
"""Test loading and unloading of the config entry."""
await setup_integration(hass, cookidoo_config_entry)
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert cookidoo_config_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(cookidoo_config_entry.entry_id)
assert cookidoo_config_entry.state is ConfigEntryState.NOT_LOADED
@pytest.mark.parametrize(
("exception", "status"),
[
(CookidooRequestException, ConfigEntryState.SETUP_RETRY),
(CookidooAuthException, ConfigEntryState.SETUP_ERROR),
],
)
async def test_init_failure(
hass: HomeAssistant,
mock_cookidoo_client: AsyncMock,
status: ConfigEntryState,
exception: Exception,
cookidoo_config_entry: MockConfigEntry,
) -> None:
"""Test an initialization error on integration load."""
mock_cookidoo_client.login.side_effect = exception
await setup_integration(hass, cookidoo_config_entry)
assert cookidoo_config_entry.state == status
@pytest.mark.parametrize(
"cookidoo_method",
[
"get_ingredient_items",
"get_additional_items",
],
)
async def test_config_entry_not_ready(
hass: HomeAssistant,
cookidoo_config_entry: MockConfigEntry,
mock_cookidoo_client: AsyncMock,
cookidoo_method: str,
) -> None:
"""Test config entry not ready."""
getattr(
mock_cookidoo_client, cookidoo_method
).side_effect = CookidooRequestException()
cookidoo_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(cookidoo_config_entry.entry_id)
await hass.async_block_till_done()
assert cookidoo_config_entry.state is ConfigEntryState.SETUP_RETRY
@pytest.mark.parametrize(
("exception", "status"),
[
(None, ConfigEntryState.LOADED),
(CookidooRequestException, ConfigEntryState.SETUP_RETRY),
(CookidooAuthException, ConfigEntryState.SETUP_ERROR),
],
)
async def test_config_entry_not_ready_auth_error(
hass: HomeAssistant,
cookidoo_config_entry: MockConfigEntry,
mock_cookidoo_client: AsyncMock,
exception: Exception | None,
status: ConfigEntryState,
) -> None:
"""Test config entry not ready from authentication error."""
mock_cookidoo_client.get_ingredient_items.side_effect = CookidooAuthException
mock_cookidoo_client.refresh_token.side_effect = exception
cookidoo_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(cookidoo_config_entry.entry_id)
await hass.async_block_till_done()
assert cookidoo_config_entry.state is status
MOCK_CONFIG_ENTRY_MIGRATION = {
CONF_EMAIL: EMAIL,
CONF_PASSWORD: PASSWORD,
CONF_COUNTRY: COUNTRY,
CONF_LANGUAGE: LANGUAGE,
}
OLD_ENTRY_ID = "OLD_OLD_ENTRY_ID"
@pytest.mark.parametrize(
(
"from_version",
"from_minor_version",
"config_data",
"unique_id",
),
[
(
1,
1,
MOCK_CONFIG_ENTRY_MIGRATION,
None,
),
(1, 2, MOCK_CONFIG_ENTRY_MIGRATION, TEST_UUID),
],
)
async def test_migration_from(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
from_version,
from_minor_version,
config_data,
unique_id,
mock_cookidoo_client: AsyncMock,
) -> None:
"""Test different expected migration paths."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data=config_data,
title=f"MIGRATION_TEST from {from_version}.{from_minor_version}",
version=from_version,
minor_version=from_minor_version,
unique_id=unique_id,
entry_id=OLD_ENTRY_ID,
)
config_entry.add_to_hass(hass)
device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, OLD_ENTRY_ID)},
entry_type=dr.DeviceEntryType.SERVICE,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="todo",
unique_id=f"{OLD_ENTRY_ID}_ingredients",
device_id=device.id,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="todo",
unique_id=f"{OLD_ENTRY_ID}_additional_items",
device_id=device.id,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="button",
unique_id=f"{OLD_ENTRY_ID}_todo_clear",
device_id=device.id,
)
await hass.config_entries.async_setup(config_entry.entry_id)
assert config_entry.state is ConfigEntryState.LOADED
# Check change in config entry and verify most recent version
assert config_entry.version == 1
assert config_entry.minor_version == 2
assert config_entry.unique_id == TEST_UUID
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.TODO,
DOMAIN,
f"{TEST_UUID}_ingredients",
)
)
)
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.TODO,
DOMAIN,
f"{TEST_UUID}_additional_items",
)
)
)
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.BUTTON,
DOMAIN,
f"{TEST_UUID}_todo_clear",
)
)
)
@pytest.mark.parametrize(
(
"from_version",
"from_minor_version",
"config_data",
"unique_id",
"login_exception",
),
[
(
1,
1,
MOCK_CONFIG_ENTRY_MIGRATION,
None,
CookidooRequestException,
),
(
1,
1,
MOCK_CONFIG_ENTRY_MIGRATION,
None,
CookidooAuthException,
),
],
)
async def test_migration_from_with_error(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
from_version,
from_minor_version,
config_data,
unique_id,
login_exception: Exception,
mock_cookidoo_client: AsyncMock,
) -> None:
"""Test different expected migration paths but with connection issues."""
# Migration can fail due to connection issues as we have to fetch the uuid
mock_cookidoo_client.login.side_effect = login_exception
config_entry = MockConfigEntry(
domain=DOMAIN,
data=config_data,
title=f"MIGRATION_TEST from {from_version}.{from_minor_version} with login exception '{login_exception}'",
version=from_version,
minor_version=from_minor_version,
unique_id=unique_id,
entry_id=OLD_ENTRY_ID,
)
config_entry.add_to_hass(hass)
device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, OLD_ENTRY_ID)},
entry_type=dr.DeviceEntryType.SERVICE,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="todo",
unique_id=f"{OLD_ENTRY_ID}_ingredients",
device_id=device.id,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="todo",
unique_id=f"{OLD_ENTRY_ID}_additional_items",
device_id=device.id,
)
entity_registry.async_get_or_create(
config_entry=config_entry,
platform=DOMAIN,
domain="button",
unique_id=f"{OLD_ENTRY_ID}_todo_clear",
device_id=device.id,
)
await hass.config_entries.async_setup(config_entry.entry_id)
assert config_entry.state is ConfigEntryState.MIGRATION_ERROR
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.TODO,
DOMAIN,
f"{OLD_ENTRY_ID}_ingredients",
)
)
)
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.TODO,
DOMAIN,
f"{OLD_ENTRY_ID}_additional_items",
)
)
)
assert entity_registry.async_is_registered(
entity_registry.entities.get_entity_id(
(
Platform.BUTTON,
DOMAIN,
f"{OLD_ENTRY_ID}_todo_clear",
)
)
)