"""Common fixtures for the Ecovacs tests.""" from collections.abc import Generator from typing import Any from unittest.mock import AsyncMock, Mock, patch from deebot_client import const from deebot_client.device import Device from deebot_client.exceptions import ApiError from deebot_client.models import Credentials import pytest from homeassistant.components.ecovacs import PLATFORMS from homeassistant.components.ecovacs.const import DOMAIN from homeassistant.components.ecovacs.controller import EcovacsController from homeassistant.const import CONF_USERNAME, Platform from homeassistant.core import HomeAssistant from .const import VALID_ENTRY_DATA_CLOUD from tests.common import MockConfigEntry, load_json_object_fixture @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock, None, None]: """Override async_setup_entry.""" with patch( "homeassistant.components.ecovacs.async_setup_entry", return_value=True ) as async_setup_entry: yield async_setup_entry @pytest.fixture def mock_config_entry_data() -> dict[str, Any]: """Return the default mocked config entry data.""" return VALID_ENTRY_DATA_CLOUD @pytest.fixture def mock_config_entry(mock_config_entry_data: dict[str, Any]) -> MockConfigEntry: """Return the default mocked config entry.""" return MockConfigEntry( title=mock_config_entry_data[CONF_USERNAME], domain=DOMAIN, data=mock_config_entry_data, ) @pytest.fixture def device_fixture() -> str: """Device class, which should be returned by the get_devices api call.""" return "yna5x1" @pytest.fixture def mock_authenticator(device_fixture: str) -> Generator[Mock, None, None]: """Mock the authenticator.""" with patch( "homeassistant.components.ecovacs.controller.Authenticator", autospec=True, ) as mock, patch( "homeassistant.components.ecovacs.config_flow.Authenticator", new=mock, ): authenticator = mock.return_value authenticator.authenticate.return_value = Credentials("token", "user_id", 0) devices = [ load_json_object_fixture(f"devices/{device_fixture}/device.json", DOMAIN) ] async def post_authenticated( path: str, json: dict[str, Any], *, query_params: dict[str, Any] | None = None, headers: dict[str, Any] | None = None, ) -> dict[str, Any]: match path: case const.PATH_API_APPSVR_APP: return {"code": 0, "devices": devices, "errno": "0"} case const.PATH_API_USERS_USER: return {"todo": "result", "result": "ok", "devices": devices} case _: raise ApiError("Path not mocked: {path}") authenticator.post_authenticated.side_effect = post_authenticated yield authenticator @pytest.fixture def mock_authenticator_authenticate(mock_authenticator: Mock) -> AsyncMock: """Mock authenticator.authenticate.""" return mock_authenticator.authenticate @pytest.fixture def mock_mqtt_client(mock_authenticator: Mock) -> Mock: """Mock the MQTT client.""" with patch( "homeassistant.components.ecovacs.controller.MqttClient", autospec=True, ) as mock, patch( "homeassistant.components.ecovacs.config_flow.MqttClient", new=mock, ): client = mock.return_value client._authenticator = mock_authenticator client.subscribe.return_value = lambda: None yield client @pytest.fixture def mock_device_execute() -> AsyncMock: """Mock the device execute function.""" with patch.object( Device, "_execute_command", return_value=True ) as mock_device_execute: yield mock_device_execute @pytest.fixture def platforms() -> Platform | list[Platform]: """Platforms, which should be loaded during the test.""" return PLATFORMS @pytest.fixture async def init_integration( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_authenticator: Mock, mock_mqtt_client: Mock, mock_device_execute: AsyncMock, platforms: Platform | list[Platform], ) -> MockConfigEntry: """Set up the Ecovacs integration for testing.""" if not isinstance(platforms, list): platforms = [platforms] with patch( "homeassistant.components.ecovacs.PLATFORMS", platforms, ): mock_config_entry.add_to_hass(hass) await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.async_block_till_done() yield mock_config_entry @pytest.fixture def controller( hass: HomeAssistant, init_integration: MockConfigEntry ) -> EcovacsController: """Get the controller for the config entry.""" return hass.data[DOMAIN][init_integration.entry_id]