From 68e1aaa0be9bad826ebb0d8afda267c311e16f09 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 19 Feb 2023 20:14:18 +0100 Subject: [PATCH] Refactor Elgato tests (#88376) --- homeassistant/components/elgato/button.py | 2 +- tests/components/elgato/conftest.py | 17 +- .../elgato/snapshots/test_button.ambr | 149 ++++++++ .../elgato/snapshots/test_light.ambr | 321 ++++++++++++++++++ .../elgato/snapshots/test_switch.ambr | 149 ++++++++ tests/components/elgato/test_button.py | 96 ++---- tests/components/elgato/test_config_flow.py | 24 +- tests/components/elgato/test_light.py | 106 ++---- tests/components/elgato/test_sensor.py | 12 +- tests/components/elgato/test_switch.py | 118 ++----- 10 files changed, 729 insertions(+), 265 deletions(-) create mode 100644 tests/components/elgato/snapshots/test_button.ambr create mode 100644 tests/components/elgato/snapshots/test_light.ambr create mode 100644 tests/components/elgato/snapshots/test_switch.ambr diff --git a/homeassistant/components/elgato/button.py b/homeassistant/components/elgato/button.py index 9f68074bb28..0dd602f1ecd 100644 --- a/homeassistant/components/elgato/button.py +++ b/homeassistant/components/elgato/button.py @@ -94,5 +94,5 @@ class ElgatoButtonEntity(ElgatoEntity, ButtonEntity): await self.entity_description.press_fn(self.coordinator.client) except ElgatoError as error: raise HomeAssistantError( - "An error occurred while identifying the Elgato Light" + "An error occurred while communicating with the Elgato Light" ) from error diff --git a/tests/components/elgato/conftest.py b/tests/components/elgato/conftest.py index a32b3a70368..bd1b4242ede 100644 --- a/tests/components/elgato/conftest.py +++ b/tests/components/elgato/conftest.py @@ -59,19 +59,6 @@ def mock_onboarding() -> Generator[None, MagicMock, None]: yield mock_onboarding -@pytest.fixture -def mock_elgato_config_flow(device_fixtures: str) -> Generator[None, MagicMock, None]: - """Return a mocked Elgato client.""" - with patch( - "homeassistant.components.elgato.config_flow.Elgato", autospec=True - ) as elgato_mock: - elgato = elgato_mock.return_value - elgato.info.return_value = Info.parse_raw( - load_fixture(f"{device_fixtures}/info.json", DOMAIN) - ) - yield elgato - - @pytest.fixture def mock_elgato( device_fixtures: str, state_variant: str @@ -79,7 +66,9 @@ def mock_elgato( """Return a mocked Elgato client.""" with patch( "homeassistant.components.elgato.coordinator.Elgato", autospec=True - ) as elgato_mock: + ) as elgato_mock, patch( + "homeassistant.components.elgato.config_flow.Elgato", new=elgato_mock + ): elgato = elgato_mock.return_value elgato.info.return_value = Info.parse_raw( load_fixture(f"{device_fixtures}/info.json", DOMAIN) diff --git a/tests/components/elgato/snapshots/test_button.ambr b/tests/components/elgato/snapshots/test_button.ambr new file mode 100644 index 00000000000..900a3f316f5 --- /dev/null +++ b/tests/components/elgato/snapshots/test_button.ambr @@ -0,0 +1,149 @@ +# serializer version: 1 +# name: test_buttons[button.frenck_identify-identify-key-light-mini] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Frenck Identify', + 'icon': 'mdi:help', + }), + 'context': , + 'entity_id': 'button.frenck_identify', + 'last_changed': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_buttons[button.frenck_identify-identify-key-light-mini].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.frenck_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:help', + 'original_name': 'Identify', + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'GW24L1A02987_identify', + 'unit_of_measurement': None, + }) +# --- +# name: test_buttons[button.frenck_identify-identify-key-light-mini].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '202', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'GW24L1A02987', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light Mini', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.4 (229)', + 'via_device_id': None, + }) +# --- +# name: test_buttons[button.frenck_restart-restart-key-light-mini] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'restart', + 'friendly_name': 'Frenck Restart', + }), + 'context': , + 'entity_id': 'button.frenck_restart', + 'last_changed': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_buttons[button.frenck_restart-restart-key-light-mini].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.frenck_restart', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Restart', + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'GW24L1A02987_restart', + 'unit_of_measurement': None, + }) +# --- +# name: test_buttons[button.frenck_restart-restart-key-light-mini].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '202', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'GW24L1A02987', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light Mini', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.4 (229)', + 'via_device_id': None, + }) +# --- diff --git a/tests/components/elgato/snapshots/test_light.ambr b/tests/components/elgato/snapshots/test_light.ambr new file mode 100644 index 00000000000..53958516739 --- /dev/null +++ b/tests/components/elgato/snapshots/test_light.ambr @@ -0,0 +1,321 @@ +# serializer version: 1 +# name: test_light_state_temperature[key-light-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'brightness': 54, + 'color_mode': , + 'color_temp': 297, + 'color_temp_kelvin': 3367, + 'friendly_name': 'Frenck', + 'hs_color': tuple( + 27.316, + 47.743, + ), + 'max_color_temp_kelvin': 6993, + 'max_mireds': 344, + 'min_color_temp_kelvin': 2906, + 'min_mireds': 143, + 'rgb_color': tuple( + 255, + 188, + 133, + ), + 'supported_color_modes': list([ + , + ]), + 'supported_features': 0, + 'xy_color': tuple( + 0.465, + 0.376, + ), + }), + 'context': , + 'entity_id': 'light.frenck', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_light_state_temperature[key-light-state].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'max_color_temp_kelvin': 6993, + 'max_mireds': 344, + 'min_color_temp_kelvin': 2906, + 'min_mireds': 143, + 'supported_color_modes': list([ + , + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'light', + 'entity_category': None, + 'entity_id': 'light.frenck', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'CN11A1A00001', + 'unit_of_measurement': None, + }) +# --- +# name: test_light_state_temperature[key-light-state].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '53', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'CN11A1A00001', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.3 (192)', + 'via_device_id': None, + }) +# --- +# name: test_light_state_temperature[light-strip-state-color-temperature] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'brightness': 54, + 'color_mode': , + 'color_temp': 297, + 'color_temp_kelvin': 3367, + 'friendly_name': 'Frenck', + 'hs_color': tuple( + 27.316, + 47.743, + ), + 'max_color_temp_kelvin': 6535, + 'max_mireds': 285, + 'min_color_temp_kelvin': 3508, + 'min_mireds': 153, + 'rgb_color': tuple( + 255, + 188, + 133, + ), + 'supported_color_modes': list([ + , + , + ]), + 'supported_features': 0, + 'xy_color': tuple( + 0.465, + 0.376, + ), + }), + 'context': , + 'entity_id': 'light.frenck', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_light_state_temperature[light-strip-state-color-temperature].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'max_color_temp_kelvin': 6535, + 'max_mireds': 285, + 'min_color_temp_kelvin': 3508, + 'min_mireds': 153, + 'supported_color_modes': list([ + , + , + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'light', + 'entity_category': None, + 'entity_id': 'light.frenck', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'CN11A1A00001', + 'unit_of_measurement': None, + }) +# --- +# name: test_light_state_temperature[light-strip-state-color-temperature].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '53', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'CN11A1A00001', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.3 (192)', + 'via_device_id': None, + }) +# --- +# name: test_light_state_temperature[light-strip-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'brightness': 128, + 'color_mode': , + 'friendly_name': 'Frenck', + 'hs_color': tuple( + 358.0, + 6.0, + ), + 'max_color_temp_kelvin': 6535, + 'max_mireds': 285, + 'min_color_temp_kelvin': 3508, + 'min_mireds': 153, + 'rgb_color': tuple( + 255, + 239, + 240, + ), + 'supported_color_modes': list([ + , + , + ]), + 'supported_features': 0, + 'xy_color': tuple( + 0.34, + 0.327, + ), + }), + 'context': , + 'entity_id': 'light.frenck', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_light_state_temperature[light-strip-state].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'max_color_temp_kelvin': 6535, + 'max_mireds': 285, + 'min_color_temp_kelvin': 3508, + 'min_mireds': 153, + 'supported_color_modes': list([ + , + , + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'light', + 'entity_category': None, + 'entity_id': 'light.frenck', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'CN11A1A00001', + 'unit_of_measurement': None, + }) +# --- +# name: test_light_state_temperature[light-strip-state].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '53', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'CN11A1A00001', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.3 (192)', + 'via_device_id': None, + }) +# --- diff --git a/tests/components/elgato/snapshots/test_switch.ambr b/tests/components/elgato/snapshots/test_switch.ambr new file mode 100644 index 00000000000..02f32d22f96 --- /dev/null +++ b/tests/components/elgato/snapshots/test_switch.ambr @@ -0,0 +1,149 @@ +# serializer version: 1 +# name: test_switches[switch.frenck_energy_saving-energy_saving-key-light-mini] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Frenck Energy saving', + 'icon': 'mdi:leaf', + }), + 'context': , + 'entity_id': 'switch.frenck_energy_saving', + 'last_changed': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_switches[switch.frenck_energy_saving-energy_saving-key-light-mini].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.frenck_energy_saving', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:leaf', + 'original_name': 'Energy saving', + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'GW24L1A02987_energy_saving', + 'unit_of_measurement': None, + }) +# --- +# name: test_switches[switch.frenck_energy_saving-energy_saving-key-light-mini].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '202', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'GW24L1A02987', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light Mini', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.4 (229)', + 'via_device_id': None, + }) +# --- +# name: test_switches[switch.frenck_studio_mode-battery_bypass-key-light-mini] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Frenck Studio mode', + 'icon': 'mdi:battery-off-outline', + }), + 'context': , + 'entity_id': 'switch.frenck_studio_mode', + 'last_changed': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_switches[switch.frenck_studio_mode-battery_bypass-key-light-mini].1 + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': , + 'entity_id': 'switch.frenck_studio_mode', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:battery-off-outline', + 'original_name': 'Studio mode', + 'platform': 'elgato', + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'GW24L1A02987_bypass', + 'unit_of_measurement': None, + }) +# --- +# name: test_switches[switch.frenck_studio_mode-battery_bypass-key-light-mini].2 + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'configuration_url': None, + 'connections': set({ + tuple( + 'mac', + 'aa:bb:cc:dd:ee:ff', + ), + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': '202', + 'id': , + 'identifiers': set({ + tuple( + 'elgato', + 'GW24L1A02987', + ), + }), + 'is_new': False, + 'manufacturer': 'Elgato', + 'model': 'Elgato Key Light Mini', + 'name': 'Frenck', + 'name_by_user': None, + 'suggested_area': None, + 'sw_version': '1.0.4 (229)', + 'via_device_id': None, + }) +# --- diff --git a/tests/components/elgato/test_button.py b/tests/components/elgato/test_button.py index 6c85fbf31e9..bd6c9a1bfe5 100644 --- a/tests/components/elgato/test_button.py +++ b/tests/components/elgato/test_button.py @@ -3,10 +3,10 @@ from unittest.mock import MagicMock from elgato import ElgatoError import pytest +from syrupy.assertion import SnapshotAssertion from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS -from homeassistant.components.elgato.const import DOMAIN -from homeassistant.const import ATTR_ENTITY_ID, ATTR_ICON, STATE_UNKNOWN, EntityCategory +from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, entity_registry as er @@ -18,97 +18,59 @@ pytestmark = [ ] -async def test_button_identify( +@pytest.mark.parametrize( + ("entity_id", "method"), + [ + ("button.frenck_identify", "identify"), + ("button.frenck_restart", "restart"), + ], +) +async def test_buttons( hass: HomeAssistant, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, mock_elgato: MagicMock, + snapshot: SnapshotAssertion, + entity_id: str, + method: str, ) -> None: """Test the Elgato identify button.""" - state = hass.states.get("button.frenck_identify") - assert state - assert state.attributes.get(ATTR_ICON) == "mdi:help" - assert state.state == STATE_UNKNOWN + assert (state := hass.states.get(entity_id)) + assert state == snapshot - entry = entity_registry.async_get("button.frenck_identify") - assert entry - assert entry.unique_id == "GW24L1A02987_identify" - assert entry.entity_category == EntityCategory.CONFIG + assert (entry := entity_registry.async_get(entity_id)) + assert entry == snapshot assert entry.device_id - device_entry = device_registry.async_get(entry.device_id) - assert device_entry - assert device_entry.configuration_url is None - assert device_entry.connections == { - (dr.CONNECTION_NETWORK_MAC, "aa:bb:cc:dd:ee:ff") - } - assert device_entry.entry_type is None - assert device_entry.identifiers == {(DOMAIN, "GW24L1A02987")} - assert device_entry.manufacturer == "Elgato" - assert device_entry.model == "Elgato Key Light Mini" - assert device_entry.name == "Frenck" - assert device_entry.sw_version == "1.0.4 (229)" - assert device_entry.hw_version == "202" + assert (device_entry := device_registry.async_get(entry.device_id)) + assert device_entry == snapshot await hass.services.async_call( BUTTON_DOMAIN, SERVICE_PRESS, - {ATTR_ENTITY_ID: "button.frenck_identify"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - assert len(mock_elgato.identify.mock_calls) == 1 - mock_elgato.identify.assert_called_with() + mocked_method = getattr(mock_elgato, method) + assert len(mocked_method.mock_calls) == 1 + mocked_method.assert_called_with() - state = hass.states.get("button.frenck_identify") + state = hass.states.get(entity_id) assert state assert state.state == "2021-11-13T11:48:00+00:00" - -async def test_button_restart( - hass: HomeAssistant, - device_registry: dr.DeviceRegistry, - entity_registry: er.EntityRegistry, - mock_elgato: MagicMock, -) -> None: - """Test the Elgato restart button.""" - state = hass.states.get("button.frenck_restart") - assert state - assert state.state == STATE_UNKNOWN - assert not state.attributes.get(ATTR_ICON) - - entry = entity_registry.async_get("button.frenck_restart") - assert entry - assert entry.unique_id == "GW24L1A02987_restart" - assert entry.entity_category == EntityCategory.CONFIG - - await hass.services.async_call( - BUTTON_DOMAIN, - SERVICE_PRESS, - {ATTR_ENTITY_ID: "button.frenck_restart"}, - blocking=True, - ) - - assert len(mock_elgato.restart.mock_calls) == 1 - mock_elgato.restart.assert_called_with() - - state = hass.states.get("button.frenck_restart") - assert state - assert state.state == "2021-11-13T11:48:00+00:00" - - -async def test_button_error(hass: HomeAssistant, mock_elgato: MagicMock) -> None: - """Test an error occurs with the Elgato buttons.""" - mock_elgato.identify.side_effect = ElgatoError + mocked_method.side_effect = ElgatoError with pytest.raises( - HomeAssistantError, match="An error occurred while identifying the Elgato Light" + HomeAssistantError, + match="An error occurred while communicating with the Elgato Light", ): await hass.services.async_call( BUTTON_DOMAIN, SERVICE_PRESS, - {ATTR_ENTITY_ID: "button.frenck_identify"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - assert len(mock_elgato.identify.mock_calls) == 1 + assert len(mocked_method.mock_calls) == 2 diff --git a/tests/components/elgato/test_config_flow.py b/tests/components/elgato/test_config_flow.py index 96da6ec4a4f..3447038b778 100644 --- a/tests/components/elgato/test_config_flow.py +++ b/tests/components/elgato/test_config_flow.py @@ -17,7 +17,7 @@ from tests.common import MockConfigEntry async def test_full_user_flow_implementation( hass: HomeAssistant, - mock_elgato_config_flow: MagicMock, + mock_elgato: MagicMock, mock_setup_entry: AsyncMock, snapshot: SnapshotAssertion, ) -> None: @@ -38,12 +38,12 @@ async def test_full_user_flow_implementation( assert result2 == snapshot assert len(mock_setup_entry.mock_calls) == 1 - assert len(mock_elgato_config_flow.info.mock_calls) == 1 + assert len(mock_elgato.info.mock_calls) == 1 async def test_full_zeroconf_flow_implementation( hass: HomeAssistant, - mock_elgato_config_flow: MagicMock, + mock_elgato: MagicMock, mock_setup_entry: AsyncMock, snapshot: SnapshotAssertion, ) -> None: @@ -80,15 +80,15 @@ async def test_full_zeroconf_flow_implementation( assert result2 == snapshot assert len(mock_setup_entry.mock_calls) == 1 - assert len(mock_elgato_config_flow.info.mock_calls) == 1 + assert len(mock_elgato.info.mock_calls) == 1 async def test_connection_error( hass: HomeAssistant, - mock_elgato_config_flow: MagicMock, + mock_elgato: MagicMock, ) -> None: """Test we show user form on Elgato Key Light connection error.""" - mock_elgato_config_flow.info.side_effect = ElgatoConnectionError + mock_elgato.info.side_effect = ElgatoConnectionError result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, @@ -102,10 +102,10 @@ async def test_connection_error( async def test_zeroconf_connection_error( hass: HomeAssistant, - mock_elgato_config_flow: MagicMock, + mock_elgato: MagicMock, ) -> None: """Test we abort zeroconf flow on Elgato Key Light connection error.""" - mock_elgato_config_flow.info.side_effect = ElgatoConnectionError + mock_elgato.info.side_effect = ElgatoConnectionError result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_ZEROCONF}, @@ -124,7 +124,7 @@ async def test_zeroconf_connection_error( assert result.get("type") == FlowResultType.ABORT -@pytest.mark.usefixtures("mock_elgato_config_flow") +@pytest.mark.usefixtures("mock_elgato") async def test_user_device_exists_abort( hass: HomeAssistant, mock_config_entry: MockConfigEntry ) -> None: @@ -140,7 +140,7 @@ async def test_user_device_exists_abort( assert result.get("reason") == "already_configured" -@pytest.mark.usefixtures("mock_elgato_config_flow") +@pytest.mark.usefixtures("mock_elgato") async def test_zeroconf_device_exists_abort( hass: HomeAssistant, mock_config_entry: MockConfigEntry ) -> None: @@ -190,7 +190,7 @@ async def test_zeroconf_device_exists_abort( async def test_zeroconf_during_onboarding( hass: HomeAssistant, - mock_elgato_config_flow: MagicMock, + mock_elgato: MagicMock, mock_setup_entry: AsyncMock, mock_onboarding: MagicMock, snapshot: SnapshotAssertion, @@ -214,5 +214,5 @@ async def test_zeroconf_during_onboarding( assert result == snapshot assert len(mock_setup_entry.mock_calls) == 1 - assert len(mock_elgato_config_flow.info.mock_calls) == 1 + assert len(mock_elgato.info.mock_calls) == 1 assert len(mock_onboarding.mock_calls) == 1 diff --git a/tests/components/elgato/test_light.py b/tests/components/elgato/test_light.py index 1f1dd5217b4..066e980653f 100644 --- a/tests/components/elgato/test_light.py +++ b/tests/components/elgato/test_light.py @@ -3,18 +3,14 @@ from unittest.mock import MagicMock from elgato import ElgatoError import pytest +from syrupy.assertion import SnapshotAssertion from homeassistant.components.elgato.const import DOMAIN, SERVICE_IDENTIFY from homeassistant.components.light import ( ATTR_BRIGHTNESS, - ATTR_COLOR_MODE, ATTR_COLOR_TEMP, ATTR_HS_COLOR, - ATTR_MAX_MIREDS, - ATTR_MIN_MIREDS, - ATTR_SUPPORTED_COLOR_MODES, DOMAIN as LIGHT_DOMAIN, - ColorMode, ) from homeassistant.const import ( ATTR_ENTITY_ID, @@ -27,69 +23,36 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, entity_registry as er +pytestmark = pytest.mark.usefixtures("init_integration") -@pytest.mark.usefixtures("init_integration", "mock_elgato") -async def test_light_state_temperature(hass: HomeAssistant) -> None: + +@pytest.mark.usefixtures("mock_elgato") +@pytest.mark.parametrize( + ("device_fixtures", "state_variant"), + [ + ("key-light", "state"), + ("light-strip", "state"), + ("light-strip", "state-color-temperature"), + ], +) +async def test_light_state_temperature( + hass: HomeAssistant, + device_registry: dr.DeviceEntry, + entity_registry: er.RegistryEntry, + snapshot: SnapshotAssertion, +) -> None: """Test the creation and values of the Elgato Lights in temperature mode.""" - device_registry = dr.async_get(hass) - entity_registry = er.async_get(hass) # First segment of the strip - state = hass.states.get("light.frenck") - assert state - assert state.attributes.get(ATTR_BRIGHTNESS) == 54 - assert state.attributes.get(ATTR_COLOR_TEMP) == 297 - assert state.attributes.get(ATTR_HS_COLOR) == (27.316, 47.743) - assert state.attributes.get(ATTR_COLOR_MODE) == ColorMode.COLOR_TEMP - assert state.attributes.get(ATTR_MIN_MIREDS) == 143 - assert state.attributes.get(ATTR_MAX_MIREDS) == 344 - assert state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) == [ColorMode.COLOR_TEMP] - assert state.state == STATE_ON + assert (state := hass.states.get("light.frenck")) + assert state == snapshot - entry = entity_registry.async_get("light.frenck") - assert entry - assert entry.unique_id == "CN11A1A00001" + assert (entry := entity_registry.async_get("light.frenck")) + assert entry == snapshot assert entry.device_id - device_entry = device_registry.async_get(entry.device_id) - assert device_entry - assert device_entry.configuration_url is None - assert device_entry.connections == { - (dr.CONNECTION_NETWORK_MAC, "aa:bb:cc:dd:ee:ff") - } - assert device_entry.entry_type is None - assert device_entry.identifiers == {(DOMAIN, "CN11A1A00001")} - assert device_entry.manufacturer == "Elgato" - assert device_entry.model == "Elgato Key Light" - assert device_entry.name == "Frenck" - assert device_entry.sw_version == "1.0.3 (192)" - assert device_entry.hw_version == "53" - - -@pytest.mark.parametrize("device_fixtures", ["light-strip"]) -@pytest.mark.usefixtures("device_fixtures", "init_integration", "mock_elgato") -async def test_light_state_color(hass: HomeAssistant) -> None: - """Test the creation and values of the Elgato Lights in temperature mode.""" - entity_registry = er.async_get(hass) - - # First segment of the strip - state = hass.states.get("light.frenck") - assert state - assert state.attributes.get(ATTR_BRIGHTNESS) == 128 - assert state.attributes.get(ATTR_COLOR_TEMP) is None - assert state.attributes.get(ATTR_HS_COLOR) == (358.0, 6.0) - assert state.attributes.get(ATTR_MIN_MIREDS) == 153 - assert state.attributes.get(ATTR_MAX_MIREDS) == 285 - assert state.attributes.get(ATTR_COLOR_MODE) == ColorMode.HS - assert state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) == [ - ColorMode.COLOR_TEMP, - ColorMode.HS, - ] - assert state.state == STATE_ON - - entry = entity_registry.async_get("light.frenck") - assert entry - assert entry.unique_id == "CN11A1A00001" + assert (device_entry := device_registry.async_get(entry.device_id)) + assert device_entry == snapshot @pytest.mark.parametrize( @@ -101,8 +64,7 @@ async def test_light_change_state_temperature( mock_elgato: MagicMock, ) -> None: """Test the change of state of a Elgato Key Light device.""" - state = hass.states.get("light.frenck") - assert state + assert (state := hass.states.get("light.frenck")) assert state.state == STATE_ON await hass.services.async_call( @@ -115,7 +77,6 @@ async def test_light_change_state_temperature( }, blocking=True, ) - await hass.async_block_till_done() assert len(mock_elgato.light.mock_calls) == 1 mock_elgato.light.assert_called_with( on=True, brightness=100, temperature=100, hue=None, saturation=None @@ -130,7 +91,6 @@ async def test_light_change_state_temperature( }, blocking=True, ) - await hass.async_block_till_done() assert len(mock_elgato.light.mock_calls) == 2 mock_elgato.light.assert_called_with( on=True, brightness=100, temperature=297, hue=None, saturation=None @@ -142,7 +102,6 @@ async def test_light_change_state_temperature( {ATTR_ENTITY_ID: "light.frenck"}, blocking=True, ) - await hass.async_block_till_done() assert len(mock_elgato.light.mock_calls) == 3 mock_elgato.light.assert_called_with(on=False) @@ -156,7 +115,6 @@ async def test_light_change_state_temperature( }, blocking=True, ) - await hass.async_block_till_done() assert len(mock_elgato.light.mock_calls) == 4 mock_elgato.light.assert_called_with( on=True, brightness=100, temperature=None, hue=10.1, saturation=20.2 @@ -164,7 +122,6 @@ async def test_light_change_state_temperature( @pytest.mark.parametrize("service", [SERVICE_TURN_ON, SERVICE_TURN_OFF]) -@pytest.mark.usefixtures("init_integration") async def test_light_unavailable( hass: HomeAssistant, mock_elgato: MagicMock, service: str ) -> None: @@ -180,8 +137,7 @@ async def test_light_unavailable( blocking=True, ) - state = hass.states.get("light.frenck") - assert state + assert (state := hass.states.get("light.frenck")) assert state.state == STATE_UNAVAILABLE @@ -196,17 +152,11 @@ async def test_light_identify(hass: HomeAssistant, mock_elgato: MagicMock) -> No }, blocking=True, ) - await hass.async_block_till_done() assert len(mock_elgato.identify.mock_calls) == 1 mock_elgato.identify.assert_called_with() - -@pytest.mark.usefixtures("init_integration") -async def test_light_identify_error( - hass: HomeAssistant, mock_elgato: MagicMock -) -> None: - """Test error occurred during identifying an Elgato Light.""" mock_elgato.identify.side_effect = ElgatoError + with pytest.raises( HomeAssistantError, match="An error occurred while identifying the Elgato Light" ): @@ -219,4 +169,4 @@ async def test_light_identify_error( blocking=True, ) - assert len(mock_elgato.identify.mock_calls) == 1 + assert len(mock_elgato.identify.mock_calls) == 2 diff --git a/tests/components/elgato/test_sensor.py b/tests/components/elgato/test_sensor.py index 6e45cfeb48a..f53e2e43156 100644 --- a/tests/components/elgato/test_sensor.py +++ b/tests/components/elgato/test_sensor.py @@ -31,14 +31,14 @@ async def test_sensors( ) -> None: """Test the Elgato sensors.""" - state = hass.states.get(entity_id) + assert (state := hass.states.get(entity_id)) assert state == snapshot - entry = entity_registry.async_get(entity_id) + assert (entry := entity_registry.async_get(entity_id)) assert entry == snapshot assert entry.device_id - device_entry = device_registry.async_get(entry.device_id) + assert (device_entry := device_registry.async_get(entry.device_id)) assert device_entry == snapshot @@ -55,10 +55,8 @@ async def test_disabled_by_default_sensors( hass: HomeAssistant, entity_registry: er.EntityRegistry, entity_id: str ) -> None: """Test the disabled by default Elgato sensors.""" - state = hass.states.get(entity_id) - assert state is None + assert not hass.states.get(entity_id) - entry = entity_registry.async_get(entity_id) - assert entry + assert (entry := entity_registry.async_get(entity_id)) assert entry.disabled assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION diff --git a/tests/components/elgato/test_switch.py b/tests/components/elgato/test_switch.py index dab891065cf..336c2a9376b 100644 --- a/tests/components/elgato/test_switch.py +++ b/tests/components/elgato/test_switch.py @@ -3,21 +3,14 @@ from unittest.mock import MagicMock from elgato import ElgatoError import pytest +from syrupy.assertion import SnapshotAssertion -from homeassistant.components.elgato.const import DOMAIN from homeassistant.components.switch import ( DOMAIN as SWITCH_DOMAIN, SERVICE_TURN_OFF, SERVICE_TURN_ON, ) -from homeassistant.const import ( - ATTR_DEVICE_CLASS, - ATTR_ENTITY_ID, - ATTR_FRIENDLY_NAME, - ATTR_ICON, - STATE_OFF, - EntityCategory, -) +from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, entity_registry as er @@ -28,61 +21,55 @@ pytestmark = [ ] -async def test_battery_bypass( +@pytest.mark.parametrize( + ("entity_id", "method"), + [ + ("switch.frenck_studio_mode", "battery_bypass"), + ("switch.frenck_energy_saving", "energy_saving"), + ], +) +async def test_switches( hass: HomeAssistant, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, mock_elgato: MagicMock, + snapshot: SnapshotAssertion, + entity_id: str, + method: str, ) -> None: - """Test the Elgato battery bypass switch.""" - state = hass.states.get("switch.frenck_studio_mode") - assert state - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Frenck Studio mode" - assert state.attributes.get(ATTR_ICON) == "mdi:battery-off-outline" - assert not state.attributes.get(ATTR_DEVICE_CLASS) + """Test the Elgato switches.""" + assert (state := hass.states.get(entity_id)) + assert state == snapshot - entry = entity_registry.async_get("switch.frenck_studio_mode") - assert entry - assert entry.unique_id == "GW24L1A02987_bypass" - assert entry.entity_category == EntityCategory.CONFIG + assert (entry := entity_registry.async_get(entity_id)) + assert entry == snapshot assert entry.device_id - device_entry = device_registry.async_get(entry.device_id) - assert device_entry - assert device_entry.configuration_url is None - assert device_entry.connections == { - (dr.CONNECTION_NETWORK_MAC, "aa:bb:cc:dd:ee:ff") - } - assert device_entry.entry_type is None - assert device_entry.identifiers == {(DOMAIN, "GW24L1A02987")} - assert device_entry.manufacturer == "Elgato" - assert device_entry.model == "Elgato Key Light Mini" - assert device_entry.name == "Frenck" - assert device_entry.sw_version == "1.0.4 (229)" - assert device_entry.hw_version == "202" + assert (device_entry := device_registry.async_get(entry.device_id)) + assert device_entry == snapshot await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "switch.frenck_studio_mode"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - assert len(mock_elgato.battery_bypass.mock_calls) == 1 - mock_elgato.battery_bypass.assert_called_once_with(on=True) + mocked_method = getattr(mock_elgato, method) + assert len(mocked_method.mock_calls) == 1 + mocked_method.assert_called_once_with(on=True) await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.frenck_studio_mode"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - assert len(mock_elgato.battery_bypass.mock_calls) == 2 - mock_elgato.battery_bypass.assert_called_with(on=False) + assert len(mocked_method.mock_calls) == 2 + mocked_method.assert_called_with(on=False) - mock_elgato.battery_bypass.side_effect = ElgatoError + mocked_method.side_effect = ElgatoError with pytest.raises( HomeAssistantError, match="An error occurred while updating the Elgato Light" @@ -90,12 +77,11 @@ async def test_battery_bypass( await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "switch.frenck_studio_mode"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - await hass.async_block_till_done() - assert len(mock_elgato.battery_bypass.mock_calls) == 3 + assert len(mocked_method.mock_calls) == 3 with pytest.raises( HomeAssistantError, match="An error occurred while updating the Elgato Light" @@ -103,48 +89,8 @@ async def test_battery_bypass( await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.frenck_studio_mode"}, + {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - await hass.async_block_till_done() - assert len(mock_elgato.battery_bypass.mock_calls) == 4 - - -async def test_battery_energy_saving( - hass: HomeAssistant, - entity_registry: er.EntityRegistry, - mock_elgato: MagicMock, -) -> None: - """Test the Elgato energy saving switch.""" - state = hass.states.get("switch.frenck_energy_saving") - assert state - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Frenck Energy saving" - assert state.attributes.get(ATTR_ICON) == "mdi:leaf" - assert not state.attributes.get(ATTR_DEVICE_CLASS) - - entry = entity_registry.async_get("switch.frenck_energy_saving") - assert entry - assert entry.unique_id == "GW24L1A02987_energy_saving" - assert entry.entity_category == EntityCategory.CONFIG - - await hass.services.async_call( - SWITCH_DOMAIN, - SERVICE_TURN_ON, - {ATTR_ENTITY_ID: "switch.frenck_energy_saving"}, - blocking=True, - ) - - assert len(mock_elgato.energy_saving.mock_calls) == 1 - mock_elgato.energy_saving.assert_called_once_with(on=True) - - await hass.services.async_call( - SWITCH_DOMAIN, - SERVICE_TURN_OFF, - {ATTR_ENTITY_ID: "switch.frenck_energy_saving"}, - blocking=True, - ) - - assert len(mock_elgato.energy_saving.mock_calls) == 2 - mock_elgato.energy_saving.assert_called_with(on=False) + assert len(mocked_method.mock_calls) == 4