From 1ae7610622563c7e597d7cde580cee2e61b45bed Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 24 Apr 2023 10:46:00 -0400 Subject: [PATCH] Add Vacuum test for Roborock (#91870) --- .coveragerc | 1 - tests/components/roborock/common.py | 37 ----------- tests/components/roborock/conftest.py | 43 ++++++++++++- tests/components/roborock/test_init.py | 25 +++++--- tests/components/roborock/test_vacuum.py | 80 ++++++++++++++++++++++-- 5 files changed, 133 insertions(+), 53 deletions(-) delete mode 100644 tests/components/roborock/common.py diff --git a/.coveragerc b/.coveragerc index 9f5a2e643b9..f1687c2e277 100644 --- a/.coveragerc +++ b/.coveragerc @@ -997,7 +997,6 @@ omit = homeassistant/components/ring/camera.py homeassistant/components/ripple/sensor.py homeassistant/components/roborock/coordinator.py - homeassistant/components/roborock/vacuum.py homeassistant/components/rocketchat/notify.py homeassistant/components/roomba/__init__.py homeassistant/components/roomba/binary_sensor.py diff --git a/tests/components/roborock/common.py b/tests/components/roborock/common.py deleted file mode 100644 index 5155c6e0c0c..00000000000 --- a/tests/components/roborock/common.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Common methods used across tests for Roborock.""" -from unittest.mock import patch - -from homeassistant.components.roborock.const import ( - CONF_BASE_URL, - CONF_USER_DATA, - DOMAIN, -) -from homeassistant.const import CONF_USERNAME -from homeassistant.core import HomeAssistant -from homeassistant.setup import async_setup_component - -from .mock_data import BASE_URL, HOME_DATA, USER_DATA, USER_EMAIL - -from tests.common import MockConfigEntry - - -async def setup_platform(hass: HomeAssistant, platform: str) -> MockConfigEntry: - """Set up the Roborock platform.""" - mock_entry = MockConfigEntry( - domain=DOMAIN, - title=USER_EMAIL, - data={ - CONF_USERNAME: USER_EMAIL, - CONF_USER_DATA: USER_DATA.as_dict(), - CONF_BASE_URL: BASE_URL, - }, - ) - mock_entry.add_to_hass(hass) - - with patch("homeassistant.components.roborock.PLATFORMS", [platform]), patch( - "homeassistant.components.roborock.RoborockApiClient.get_home_data", - return_value=HOME_DATA, - ), patch("homeassistant.components.roborock.RoborockMqttClient.get_networking"): - assert await async_setup_component(hass, DOMAIN, {}) - await hass.async_block_till_done() - return mock_entry diff --git a/tests/components/roborock/conftest.py b/tests/components/roborock/conftest.py index 82e7be4751a..d767505feeb 100644 --- a/tests/components/roborock/conftest.py +++ b/tests/components/roborock/conftest.py @@ -3,7 +3,18 @@ from unittest.mock import patch import pytest -from .mock_data import PROP +from homeassistant.components.roborock.const import ( + CONF_BASE_URL, + CONF_USER_DATA, + DOMAIN, +) +from homeassistant.const import CONF_USERNAME +from homeassistant.core import HomeAssistant +from homeassistant.setup import async_setup_component + +from .mock_data import BASE_URL, HOME_DATA, PROP, USER_DATA, USER_EMAIL + +from tests.common import MockConfigEntry @pytest.fixture(name="bypass_api_fixture") @@ -16,3 +27,33 @@ def bypass_api_fixture() -> None: return_value=PROP, ): yield + + +@pytest.fixture +def mock_roborock_entry(hass: HomeAssistant) -> MockConfigEntry: + """Create a Roborock Entry that has not been setup.""" + mock_entry = MockConfigEntry( + domain=DOMAIN, + title=USER_EMAIL, + data={ + CONF_USERNAME: USER_EMAIL, + CONF_USER_DATA: USER_DATA.as_dict(), + CONF_BASE_URL: BASE_URL, + }, + ) + mock_entry.add_to_hass(hass) + return mock_entry + + +@pytest.fixture +async def setup_entry( + hass: HomeAssistant, mock_roborock_entry: MockConfigEntry +) -> MockConfigEntry: + """Set up the Roborock platform.""" + with patch( + "homeassistant.components.roborock.RoborockApiClient.get_home_data", + return_value=HOME_DATA, + ), patch("homeassistant.components.roborock.RoborockMqttClient.get_networking"): + assert await async_setup_component(hass, DOMAIN, {}) + await hass.async_block_till_done() + return mock_roborock_entry diff --git a/tests/components/roborock/test_init.py b/tests/components/roborock/test_init.py index bf57105a7f7..05bf0848475 100644 --- a/tests/components/roborock/test_init.py +++ b/tests/components/roborock/test_init.py @@ -3,33 +3,38 @@ from unittest.mock import patch from homeassistant.components.roborock.const import DOMAIN from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import UpdateFailed +from homeassistant.setup import async_setup_component -from .common import setup_platform +from tests.common import MockConfigEntry -async def test_unload_entry(hass: HomeAssistant, bypass_api_fixture) -> None: +async def test_unload_entry( + hass: HomeAssistant, bypass_api_fixture, setup_entry: MockConfigEntry +) -> None: """Test unloading roboorck integration.""" - entry = await setup_platform(hass, Platform.VACUUM) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 - assert entry.state is ConfigEntryState.LOADED + assert setup_entry.state is ConfigEntryState.LOADED with patch( "homeassistant.components.roborock.coordinator.RoborockLocalClient.async_disconnect" ) as mock_disconnect: - assert await hass.config_entries.async_unload(entry.entry_id) + assert await hass.config_entries.async_unload(setup_entry.entry_id) await hass.async_block_till_done() assert mock_disconnect.call_count == 1 - assert entry.state is ConfigEntryState.NOT_LOADED + assert setup_entry.state is ConfigEntryState.NOT_LOADED assert not hass.data.get(DOMAIN) -async def test_config_entry_not_ready(hass: HomeAssistant) -> None: +async def test_config_entry_not_ready( + hass: HomeAssistant, mock_roborock_entry: MockConfigEntry +) -> None: """Test that when coordinator update fails, entry retries.""" with patch( + "homeassistant.components.roborock.RoborockApiClient.get_home_data", + ), patch( "homeassistant.components.roborock.RoborockDataUpdateCoordinator._async_update_data", side_effect=UpdateFailed(), ): - entry = await setup_platform(hass, Platform.VACUUM) - assert entry.state is ConfigEntryState.SETUP_RETRY + await async_setup_component(hass, DOMAIN, {}) + assert mock_roborock_entry.state is ConfigEntryState.SETUP_RETRY diff --git a/tests/components/roborock/test_vacuum.py b/tests/components/roborock/test_vacuum.py index 2bb0432c661..f6cc5e81d1b 100644 --- a/tests/components/roborock/test_vacuum.py +++ b/tests/components/roborock/test_vacuum.py @@ -1,19 +1,91 @@ """Tests for Roborock vacuums.""" -from homeassistant.const import Platform +from typing import Any +from unittest.mock import patch + +import pytest +from roborock.typing import RoborockCommand + +from homeassistant.components.vacuum import ( + SERVICE_CLEAN_SPOT, + SERVICE_LOCATE, + SERVICE_PAUSE, + SERVICE_RETURN_TO_BASE, + SERVICE_SEND_COMMAND, + SERVICE_SET_FAN_SPEED, + SERVICE_START, + SERVICE_START_PAUSE, + SERVICE_STOP, +) +from homeassistant.const import ATTR_ENTITY_ID, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er -from .common import setup_platform +from tests.common import MockConfigEntry ENTITY_ID = "vacuum.roborock_s7_maxv" DEVICE_ID = "abc123" -async def test_registry_entries(hass: HomeAssistant, bypass_api_fixture) -> None: +async def test_registry_entries( + hass: HomeAssistant, bypass_api_fixture, setup_entry: MockConfigEntry +) -> None: """Tests devices are registered in the entity registry.""" - await setup_platform(hass, Platform.VACUUM) entity_registry = er.async_get(hass) entry = entity_registry.async_get(ENTITY_ID) assert entry.unique_id == DEVICE_ID + + +@pytest.mark.parametrize( + ("service", "command", "service_params", "called_params"), + [ + (SERVICE_START, RoborockCommand.APP_START, None, None), + (SERVICE_PAUSE, RoborockCommand.APP_PAUSE, None, None), + (SERVICE_STOP, RoborockCommand.APP_STOP, None, None), + (SERVICE_RETURN_TO_BASE, RoborockCommand.APP_CHARGE, None, None), + (SERVICE_CLEAN_SPOT, RoborockCommand.APP_SPOT, None, None), + (SERVICE_LOCATE, RoborockCommand.FIND_ME, None, None), + (SERVICE_START_PAUSE, RoborockCommand.APP_START, None, None), + ( + SERVICE_SET_FAN_SPEED, + RoborockCommand.SET_CUSTOM_MODE, + {"fan_speed": "silent"}, + [101], + ), + ( + SERVICE_SEND_COMMAND, + RoborockCommand.GET_LED_STATUS, + {"command": "get_led_status"}, + None, + ), + ], +) +async def test_commands( + hass: HomeAssistant, + bypass_api_fixture, + setup_entry: MockConfigEntry, + service: str, + command: str, + service_params: dict[str, Any], + called_params: list | None, +) -> None: + """Test sending commands to the vacuum.""" + + vacuum = hass.states.get(ENTITY_ID) + assert vacuum + + data = {ATTR_ENTITY_ID: ENTITY_ID, **(service_params or {})} + with patch( + "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_command" + ) as mock_send_command: + await hass.services.async_call( + Platform.VACUUM, + service, + data, + blocking=True, + ) + assert mock_send_command.call_count == 1 + assert mock_send_command.call_args[0][0] == DEVICE_ID + assert mock_send_command.call_args[0][1] == command + assert mock_send_command.call_args[0][2] == called_params