diff --git a/tests/components/alexa_devices/const.py b/tests/components/alexa_devices/const.py index a6e7b639bb64..c312419d7ca2 100644 --- a/tests/components/alexa_devices/const.py +++ b/tests/components/alexa_devices/const.py @@ -2,6 +2,7 @@ from datetime import UTC, datetime +from aioamazondevices.const.devices import DEVICE_TYPE_AQM from aioamazondevices.const.schedules import ( NOTIFICATION_ALARM, NOTIFICATION_REMINDER, @@ -121,6 +122,83 @@ TEST_DEVICE_2 = AmazonDevice( voice_control_supported=True, ) +TEST_DEVICE_AQM_SN = "aqm_test_serial_number" +TEST_DEVICE_AQM = AmazonDevice( + account_name="Air Quality Monitor Test", + # Air Quality Monitors are discovered via a separate GraphQL endpoint and + # never expose voice, media or notification capabilities. + capabilities=[], + device_family="AIR_QUALITY_MONITOR", + device_type=DEVICE_TYPE_AQM, + household_device=False, + device_owner_customer_id="amazon_ower_id", + device_cluster_members={TEST_DEVICE_AQM_SN: DEVICE_TYPE_AQM}, + parent_clusters=[], + online=True, + serial_number=TEST_DEVICE_AQM_SN, + manufacturer="Amazon", + model="Air Quality Monitor", + hardware_version=None, + software_version="aqm_test_software_version", + entity_id="66666666-7777-8888-9999-000000000000", + endpoint_id="G1234567890123456789012345678C", + sensors={ + "Humidity": AmazonDeviceSensor( + name="Humidity", + value="45", + error=False, + error_msg=None, + error_type=None, + scale="%", + ), + "VOC": AmazonDeviceSensor( + name="VOC", + value="120", + error=False, + error_msg=None, + error_type=None, + scale=None, + ), + "PM25": AmazonDeviceSensor( + name="PM25", + value="8", + error=False, + error_msg=None, + error_type=None, + scale="MicroGramsPerCubicMeter", + ), + "PM10": AmazonDeviceSensor( + name="PM10", + value="12", + error=False, + error_msg=None, + error_type=None, + scale="MicroGramsPerCubicMeter", + ), + "CO": AmazonDeviceSensor( + name="CO", + value="0.5", + error=False, + error_msg=None, + error_type=None, + scale="ppm", + ), + "Air Quality": AmazonDeviceSensor( + name="Air Quality", + value="42", + error=False, + error_msg=None, + error_type=None, + scale=None, + ), + }, + notifications_supported=False, + notifications={}, + media_player_supported=False, + communication_settings={}, + voice_control_supported=False, +) + TEST_VOCAL_RECORD_INITIAL = AmazonVocalRecord( timestamp=1000, history_type="WAKE_WORD_UTTERANCE", diff --git a/tests/components/alexa_devices/snapshots/test_sensor.ambr b/tests/components/alexa_devices/snapshots/test_sensor.ambr index 8dc5c2c2eb3a..235613837c04 100644 --- a/tests/components/alexa_devices/snapshots/test_sensor.ambr +++ b/tests/components/alexa_devices/snapshots/test_sensor.ambr @@ -1,5 +1,332 @@ # serializer version: 1 -# name: test_all_entities[sensor.echo_test_next_alarm-entry] +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_air_quality_index-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_air_quality_index', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Air quality index', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Air quality index', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'aqm_test_serial_number-Air Quality', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_air_quality_index-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'aqi', + : 'Air Quality Monitor Test Air quality index', + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_air_quality_index', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '42', + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_carbon_monoxide-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_carbon_monoxide', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Carbon monoxide', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Carbon monoxide', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'aqm_test_serial_number-CO', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_carbon_monoxide-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'carbon_monoxide', + : 'Air Quality Monitor Test Carbon monoxide', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_carbon_monoxide', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.5', + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_humidity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_humidity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Humidity', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Humidity', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'aqm_test_serial_number-Humidity', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_humidity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'humidity', + : 'Air Quality Monitor Test Humidity', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_humidity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '45', + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_pm10-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_pm10', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'PM10', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'PM10', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'aqm_test_serial_number-PM10', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_pm10-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'pm10', + : 'Air Quality Monitor Test PM10', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_pm10', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '12', + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_pm2_5-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_pm2_5', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'PM2.5', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'PM2.5', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'aqm_test_serial_number-PM25', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_pm2_5-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'pm25', + : 'Air Quality Monitor Test PM2.5', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_pm2_5', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '8', + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_volatile_organic_compounds_index-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.air_quality_monitor_test_volatile_organic_compounds_index', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Volatile organic compounds index', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Volatile organic compounds index', + 'platform': 'alexa_devices', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'voc_index', + 'unique_id': 'aqm_test_serial_number-VOC', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[aqm][sensor.air_quality_monitor_test_volatile_organic_compounds_index-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Air Quality Monitor Test Volatile organic compounds index', + : , + }), + 'context': , + 'entity_id': 'sensor.air_quality_monitor_test_volatile_organic_compounds_index', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '120', + }) +# --- +# name: test_all_entities[echo][sensor.echo_test_next_alarm-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -36,7 +363,7 @@ 'unit_of_measurement': None, }) # --- -# name: test_all_entities[sensor.echo_test_next_alarm-state] +# name: test_all_entities[echo][sensor.echo_test_next_alarm-state] StateSnapshot({ 'attributes': ReadOnlyDict({ : 'timestamp', @@ -50,7 +377,7 @@ 'state': '2023-10-01T07:00:00+00:00', }) # --- -# name: test_all_entities[sensor.echo_test_next_reminder-entry] +# name: test_all_entities[echo][sensor.echo_test_next_reminder-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -87,7 +414,7 @@ 'unit_of_measurement': None, }) # --- -# name: test_all_entities[sensor.echo_test_next_reminder-state] +# name: test_all_entities[echo][sensor.echo_test_next_reminder-state] StateSnapshot({ 'attributes': ReadOnlyDict({ : 'timestamp', @@ -101,7 +428,7 @@ 'state': 'unavailable', }) # --- -# name: test_all_entities[sensor.echo_test_next_timer-entry] +# name: test_all_entities[echo][sensor.echo_test_next_timer-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -138,7 +465,7 @@ 'unit_of_measurement': None, }) # --- -# name: test_all_entities[sensor.echo_test_next_timer-state] +# name: test_all_entities[echo][sensor.echo_test_next_timer-state] StateSnapshot({ 'attributes': ReadOnlyDict({ : 'timestamp', @@ -152,7 +479,7 @@ 'state': 'unavailable', }) # --- -# name: test_all_entities[sensor.echo_test_temperature-entry] +# name: test_all_entities[echo][sensor.echo_test_temperature-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -194,7 +521,7 @@ 'unit_of_measurement': , }) # --- -# name: test_all_entities[sensor.echo_test_temperature-state] +# name: test_all_entities[echo][sensor.echo_test_temperature-state] StateSnapshot({ 'attributes': ReadOnlyDict({ : 'temperature', diff --git a/tests/components/alexa_devices/test_event.py b/tests/components/alexa_devices/test_event.py index 6eba494df7e6..ed46d9715c5e 100644 --- a/tests/components/alexa_devices/test_event.py +++ b/tests/components/alexa_devices/test_event.py @@ -17,6 +17,8 @@ from .const import ( TEST_DEVICE_1_SN, TEST_DEVICE_2, TEST_DEVICE_2_SN, + TEST_DEVICE_AQM, + TEST_DEVICE_AQM_SN, TEST_VOCAL_RECORD_EVENT, ) @@ -149,3 +151,18 @@ async def test_voice_event_removed_for_unsupported_device( assert not hass.states.get(entity.entity_id) assert entity_registry.async_get(entity.entity_id) is None + + +async def test_voice_event_not_created_for_aqm_device( + hass: HomeAssistant, + mock_amazon_devices_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test no voice event entity is created for an Air Quality Monitor device.""" + mock_amazon_devices_client.get_devices_data.return_value = { + TEST_DEVICE_AQM_SN: TEST_DEVICE_AQM + } + + await setup_integration(hass, mock_config_entry) + + assert not hass.states.get("event.air_quality_monitor_test_voice_event") diff --git a/tests/components/alexa_devices/test_media_player.py b/tests/components/alexa_devices/test_media_player.py index 65680fa9a0e7..1d2e0a6897b4 100644 --- a/tests/components/alexa_devices/test_media_player.py +++ b/tests/components/alexa_devices/test_media_player.py @@ -40,7 +40,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from . import assert_device_removed_and_readded, setup_integration -from .const import TEST_DEVICE_1, TEST_DEVICE_1_SN +from .const import TEST_DEVICE_1, TEST_DEVICE_1_SN, TEST_DEVICE_AQM, TEST_DEVICE_AQM_SN from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform @@ -172,8 +172,6 @@ async def test_media_player_not_created_for_unsupported_device( mock_config_entry: MockConfigEntry, ) -> None: """No entity is created for a device that does not support media playback.""" - from .const import TEST_DEVICE_1 # noqa: PLC0415 - device = deepcopy(TEST_DEVICE_1) device.media_player_supported = False mock_amazon_devices_client.get_devices_data.return_value = { @@ -185,6 +183,21 @@ async def test_media_player_not_created_for_unsupported_device( assert hass.states.get(ENTITY_ID) is None +async def test_media_player_not_created_for_aqm_device( + hass: HomeAssistant, + mock_amazon_devices_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """No media player entity is created for an Air Quality Monitor device.""" + mock_amazon_devices_client.get_devices_data.return_value = { + TEST_DEVICE_AQM_SN: TEST_DEVICE_AQM + } + + await _setup_media_player_platform(hass, mock_config_entry) + + assert hass.states.get("media_player.air_quality_monitor_test") is None + + @pytest.mark.parametrize( "side_effect", [ diff --git a/tests/components/alexa_devices/test_sensor.py b/tests/components/alexa_devices/test_sensor.py index 902024dd81da..8171f4ae591d 100644 --- a/tests/components/alexa_devices/test_sensor.py +++ b/tests/components/alexa_devices/test_sensor.py @@ -1,5 +1,6 @@ """Tests for the Alexa Devices sensor platform.""" +from copy import deepcopy from typing import Any from unittest.mock import AsyncMock, patch @@ -8,7 +9,7 @@ from aioamazondevices.exceptions import ( CannotConnect, CannotRetrieveData, ) -from aioamazondevices.structures import AmazonDeviceSensor +from aioamazondevices.structures import AmazonDevice, AmazonDeviceSensor from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion @@ -19,19 +20,36 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from . import assert_device_removed_and_readded, setup_integration -from .const import TEST_DEVICE_1, TEST_DEVICE_1_SN, TEST_DEVICE_2, TEST_DEVICE_2_SN +from .const import ( + TEST_DEVICE_1, + TEST_DEVICE_1_SN, + TEST_DEVICE_2, + TEST_DEVICE_2_SN, + TEST_DEVICE_AQM, + TEST_DEVICE_AQM_SN, +) from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform +@pytest.mark.parametrize( + "devices", + [ + pytest.param({TEST_DEVICE_1_SN: TEST_DEVICE_1}, id="echo"), + pytest.param({TEST_DEVICE_AQM_SN: TEST_DEVICE_AQM}, id="aqm"), + ], +) async def test_all_entities( hass: HomeAssistant, snapshot: SnapshotAssertion, mock_amazon_devices_client: AsyncMock, mock_config_entry: MockConfigEntry, entity_registry: er.EntityRegistry, + devices: dict[str, AmazonDevice], ) -> None: """Test all entities.""" + mock_amazon_devices_client.get_devices_data.return_value = deepcopy(devices) + with patch("homeassistant.components.alexa_devices.PLATFORMS", [Platform.SENSOR]): await setup_integration(hass, mock_config_entry)