diff --git a/tests/components/flume/conftest.py b/tests/components/flume/conftest.py index 5df6370d9b60..83e7de0d06f7 100644 --- a/tests/components/flume/conftest.py +++ b/tests/components/flume/conftest.py @@ -28,7 +28,7 @@ DEVICE_LIST_URL = ( "https://api.flumetech.com/users/test-user-id/devices?user=true&location=true" ) BRIDGE_DEVICE = { - "id": "1234", + "id": "5678", "type": 1, # Bridge "location": { "name": "Bridge Location", diff --git a/tests/components/flume/snapshots/test_binary_sensor.ambr b/tests/components/flume/snapshots/test_binary_sensor.ambr new file mode 100644 index 000000000000..45e85bf93a66 --- /dev/null +++ b/tests/components/flume/snapshots/test_binary_sensor.ambr @@ -0,0 +1,259 @@ +# serializer version: 1 +# name: test_binary_sensors[binary_sensor.flume_bridge_bridge_location_connectivity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.flume_bridge_bridge_location_connectivity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Connectivity', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connectivity', + 'platform': 'flume', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'connected_5678', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_bridge_bridge_location_connectivity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Data provided by Flume API', + : 'connectivity', + : 'Flume Bridge Bridge Location Connectivity', + }), + 'context': , + 'entity_id': 'binary_sensor.flume_bridge_bridge_location_connectivity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_battery-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_battery', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Battery', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Battery', + 'platform': 'flume', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'low_battery_1234', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_battery-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Data provided by Flume API', + : 'battery', + : 'Flume Sensor Sensor Location Battery', + }), + 'context': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_battery', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_connectivity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_connectivity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Connectivity', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Connectivity', + 'platform': 'flume', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'connected_1234', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_connectivity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Data provided by Flume API', + : 'connectivity', + : 'Flume Sensor Sensor Location Connectivity', + }), + 'context': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_connectivity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_high_flow-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_high_flow', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'High flow', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'High flow', + 'platform': 'flume', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'flow', + 'unique_id': 'flow_1234', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_high_flow-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Data provided by Flume API', + : 'Flume Sensor Sensor Location High flow', + }), + 'context': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_high_flow', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_leak_detected-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_leak_detected', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Leak detected', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Leak detected', + 'platform': 'flume', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'leak', + 'unique_id': 'leak_1234', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.flume_sensor_sensor_location_leak_detected-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'Data provided by Flume API', + : 'Flume Sensor Sensor Location Leak detected', + }), + 'context': , + 'entity_id': 'binary_sensor.flume_sensor_sensor_location_leak_detected', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- diff --git a/tests/components/flume/test_binary_sensor.py b/tests/components/flume/test_binary_sensor.py new file mode 100644 index 000000000000..49a4cd1a91bb --- /dev/null +++ b/tests/components/flume/test_binary_sensor.py @@ -0,0 +1,93 @@ +"""Tests for Flume binary sensors.""" + +from collections.abc import Generator +from typing import Any +from unittest.mock import patch + +import pytest +from requests_mock.mocker import Mocker +from syrupy.assertion import SnapshotAssertion + +from homeassistant.components.flume.const import DOMAIN +from homeassistant.const import STATE_ON, Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from .conftest import NOTIFICATIONS_URL, SENSOR_DEVICE, USER_ID + +from tests.common import MockConfigEntry, snapshot_platform + + +def active_notification(event_rule_name: str) -> dict[str, Any]: + """Build a read but uncleared notification for the sensor device.""" + return { + "id": 222222, + "device_id": SENSOR_DEVICE["id"], + "user_id": USER_ID, + "type": 16, + "message": f"{event_rule_name} triggered at Home.", + "read": True, + "extra": {"event_rule_name": event_rule_name}, + } + + +@pytest.fixture(autouse=True) +def platforms_fixture() -> Generator[None]: + """Set up only the binary sensor platform.""" + with patch("homeassistant.components.flume.PLATFORMS", [Platform.BINARY_SENSOR]): + yield + + +@pytest.mark.usefixtures("access_token", "device_list") +async def test_binary_sensors( + hass: HomeAssistant, + config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, + requests_mock: Mocker, + snapshot: SnapshotAssertion, +) -> None: + """Test binary sensors with no notification outstanding.""" + requests_mock.get(NOTIFICATIONS_URL, json={"data": []}) + + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id) + + +@pytest.mark.usefixtures("access_token", "device_list") +@pytest.mark.parametrize( + ("event_rule_name", "unique_id"), + [ + pytest.param("Flume Smart Leak Alert", "leak_1234", id="leak"), + pytest.param("High Flow Alert", "flow_1234", id="high_flow"), + pytest.param("Low Battery", "low_battery_1234", id="low_battery"), + ], +) +async def test_notification_binary_sensors( + hass: HomeAssistant, + config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, + requests_mock: Mocker, + event_rule_name: str, + unique_id: str, +) -> None: + """Test each sensor is on while its notification is in the list. + + A notification stays in the list until it is deleted in the Flume app. + """ + requests_mock.get( + NOTIFICATIONS_URL, + json={"data": [active_notification(event_rule_name)]}, + ) + + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + entity_id = entity_registry.async_get_entity_id( + Platform.BINARY_SENSOR, DOMAIN, unique_id + ) + assert entity_id is not None + state = hass.states.get(entity_id) + assert state is not None + assert state.state == STATE_ON