mirror of
https://github.com/home-assistant/core.git
synced 2026-05-30 12:14:20 +01:00
Add tests to lutron (#162055)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
"""Provide common Lutron fixtures and mocks."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pylutron import OccupancyGroup
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.lutron.const import DOMAIN
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
@@ -13,3 +18,112 @@ def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"homeassistant.components.lutron.async_setup_entry", return_value=True
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_lutron() -> Generator[MagicMock]:
|
||||
"""Mock Lutron client."""
|
||||
with (
|
||||
patch("homeassistant.components.lutron.Lutron", autospec=True) as mock_lutron,
|
||||
patch("homeassistant.components.lutron.config_flow.Lutron", new=mock_lutron),
|
||||
):
|
||||
client = mock_lutron.return_value
|
||||
client.guid = "12345678901"
|
||||
client.areas = []
|
||||
|
||||
# Mock an area
|
||||
area = MagicMock()
|
||||
area.name = "Test Area"
|
||||
area.outputs = []
|
||||
area.keypads = []
|
||||
area.occupancy_group = None
|
||||
client.areas.append(area)
|
||||
|
||||
# Mock a light
|
||||
light = MagicMock()
|
||||
light.name = "Test Light"
|
||||
light.id = "light_id"
|
||||
light.uuid = "light_uuid"
|
||||
light.legacy_uuid = "light_legacy_uuid"
|
||||
light.is_dimmable = True
|
||||
light.type = "LIGHT"
|
||||
light.last_level.return_value = 0
|
||||
area.outputs.append(light)
|
||||
|
||||
# Mock a switch
|
||||
switch = MagicMock()
|
||||
switch.name = "Test Switch"
|
||||
switch.id = "switch_id"
|
||||
switch.uuid = "switch_uuid"
|
||||
switch.legacy_uuid = "switch_legacy_uuid"
|
||||
switch.is_dimmable = False
|
||||
switch.type = "NON_DIM"
|
||||
switch.last_level.return_value = 0
|
||||
area.outputs.append(switch)
|
||||
|
||||
# Mock a cover
|
||||
cover = MagicMock()
|
||||
cover.name = "Test Cover"
|
||||
cover.id = "cover_id"
|
||||
cover.uuid = "cover_uuid"
|
||||
cover.legacy_uuid = "cover_legacy_uuid"
|
||||
cover.type = "SYSTEM_SHADE"
|
||||
cover.last_level.return_value = 0
|
||||
area.outputs.append(cover)
|
||||
|
||||
# Mock a fan
|
||||
fan = MagicMock()
|
||||
fan.name = "Test Fan"
|
||||
fan.uuid = "fan_uuid"
|
||||
fan.legacy_uuid = "fan_legacy_uuid"
|
||||
fan.type = "CEILING_FAN_TYPE"
|
||||
fan.last_level.return_value = 0
|
||||
area.outputs.append(fan)
|
||||
|
||||
# Mock a keypad with a button and LED
|
||||
keypad = MagicMock()
|
||||
keypad.name = "Test Keypad"
|
||||
keypad.id = "keypad_id"
|
||||
keypad.type = "KEYPAD"
|
||||
area.keypads.append(keypad)
|
||||
|
||||
button = MagicMock()
|
||||
button.name = "Test Button"
|
||||
button.number = 1
|
||||
button.button_type = "SingleAction"
|
||||
button.uuid = "button_uuid"
|
||||
button.legacy_uuid = "button_legacy_uuid"
|
||||
keypad.buttons = [button]
|
||||
|
||||
led = MagicMock()
|
||||
led.name = "Test LED"
|
||||
led.number = 1
|
||||
led.uuid = "led_uuid"
|
||||
led.legacy_uuid = "led_legacy_uuid"
|
||||
led.last_state = 0
|
||||
keypad.leds = [led]
|
||||
|
||||
# Mock an occupancy group
|
||||
occ_group = MagicMock()
|
||||
occ_group.name = "Test Occupancy"
|
||||
occ_group.id = "occ_id"
|
||||
occ_group.uuid = "occ_uuid"
|
||||
occ_group.legacy_uuid = "occ_legacy_uuid"
|
||||
occ_group.state = OccupancyGroup.State.VACANT
|
||||
area.occupancy_group = occ_group
|
||||
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Mock a Lutron config entry."""
|
||||
return MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
"host": "127.0.0.1",
|
||||
"username": "lutron",
|
||||
"password": "password",
|
||||
},
|
||||
unique_id="12345678901",
|
||||
)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# serializer version: 1
|
||||
# name: test_binary_sensor_setup[binary_sensor.test_occupancy_occupancy-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'binary_sensor.test_occupancy_occupancy',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Occupancy',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <BinarySensorDeviceClass.OCCUPANCY: 'occupancy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Occupancy',
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_occ_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_binary_sensor_setup[binary_sensor.test_occupancy_occupancy-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'occupancy',
|
||||
'friendly_name': 'Test Occupancy Occupancy',
|
||||
'lutron_integration_id': 'occ_id',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.test_occupancy_occupancy',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,53 @@
|
||||
# serializer version: 1
|
||||
# name: test_cover_setup[cover.test_cover-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'cover',
|
||||
'entity_category': None,
|
||||
'entity_id': 'cover.test_cover',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 7>,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_cover_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_setup[cover.test_cover-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_position': 0,
|
||||
'friendly_name': 'Test Cover',
|
||||
'lutron_integration_id': 'cover_id',
|
||||
'supported_features': <CoverEntityFeature: 7>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_cover',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'closed',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,58 @@
|
||||
# serializer version: 1
|
||||
# name: test_event_setup[event.test_keypad_test_button-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'event_types': list([
|
||||
<LutronEventType.SINGLE_PRESS: 'single_press'>,
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'event',
|
||||
'entity_category': None,
|
||||
'entity_id': 'event.test_keypad_test_button',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Test Button',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Test Button',
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'button',
|
||||
'unique_id': '12345678901_button_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_event_setup[event.test_keypad_test_button-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'event_type': None,
|
||||
'event_types': list([
|
||||
<LutronEventType.SINGLE_PRESS: 'single_press'>,
|
||||
]),
|
||||
'friendly_name': 'Test Keypad Test Button',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'event.test_keypad_test_button',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,57 @@
|
||||
# serializer version: 1
|
||||
# name: test_fan_setup[fan.test_fan-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'preset_modes': None,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'fan',
|
||||
'entity_category': None,
|
||||
'entity_id': 'fan.test_fan',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <FanEntityFeature: 49>,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_fan_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_fan_setup[fan.test_fan-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Fan',
|
||||
'percentage': 0,
|
||||
'percentage_step': 33.333333333333336,
|
||||
'preset_mode': None,
|
||||
'preset_modes': None,
|
||||
'supported_features': <FanEntityFeature: 49>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'fan.test_fan',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,61 @@
|
||||
# serializer version: 1
|
||||
# name: test_light_setup[light.test_light-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.BRIGHTNESS: 'brightness'>,
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'light',
|
||||
'entity_category': None,
|
||||
'entity_id': 'light.test_light',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <LightEntityFeature: 40>,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_light_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_light_setup[light.test_light-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'brightness': None,
|
||||
'color_mode': None,
|
||||
'friendly_name': 'Test Light',
|
||||
'lutron_integration_id': 'light_id',
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.BRIGHTNESS: 'brightness'>,
|
||||
]),
|
||||
'supported_features': <LightEntityFeature: 40>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'light.test_light',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,50 @@
|
||||
# serializer version: 1
|
||||
# name: test_scene_setup[scene.test_keypad_test_button-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'scene',
|
||||
'entity_category': None,
|
||||
'entity_id': 'scene.test_keypad_test_button',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Test Button',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Test Button',
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_button_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_scene_setup[scene.test_keypad_test_button-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Keypad Test Button',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'scene.test_keypad_test_button',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,103 @@
|
||||
# serializer version: 1
|
||||
# name: test_switch_setup[switch.test_keypad_test_button-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.test_keypad_test_button',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Test Button',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Test Button',
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_led_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_setup[switch.test_keypad_test_button-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Keypad Test Button',
|
||||
'keypad': 'Test Keypad',
|
||||
'led': 'Test LED',
|
||||
'scene': 'Test Button',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.test_keypad_test_button',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_setup[switch.test_switch-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': None,
|
||||
'entity_id': 'switch.test_switch',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'lutron',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '12345678901_switch_uuid',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_setup[switch.test_switch-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Switch',
|
||||
'lutron_integration_id': 'switch_id',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.test_switch',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,56 @@
|
||||
"""Test Lutron binary sensor platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from pylutron import OccupancyGroup
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_binary_sensor_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test binary sensor setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
occ_group = mock_lutron.areas[0].occupancy_group
|
||||
occ_group.state = OccupancyGroup.State.VACANT
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.BINARY_SENSOR]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_binary_sensor_update(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test binary sensor update."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
occ_group = mock_lutron.areas[0].occupancy_group
|
||||
occ_group.state = OccupancyGroup.State.VACANT
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "binary_sensor.test_occupancy_occupancy"
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# Simulate update
|
||||
occ_group.state = OccupancyGroup.State.OCCUPIED
|
||||
callback = occ_group.subscribe.call_args[0][0]
|
||||
callback(occ_group, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
@@ -0,0 +1,110 @@
|
||||
"""Test Lutron cover platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.cover import DOMAIN as COVER_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_CLOSE_COVER,
|
||||
SERVICE_OPEN_COVER,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
STATE_CLOSED,
|
||||
STATE_OPEN,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_cover_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test cover setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
cover = mock_lutron.areas[0].outputs[2]
|
||||
cover.level = 0
|
||||
cover.last_level.return_value = 0
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.COVER]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_cover_services(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test cover services."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
cover = mock_lutron.areas[0].outputs[2]
|
||||
cover.level = 0
|
||||
cover.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "cover.test_cover"
|
||||
|
||||
# Open cover
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert cover.level == 100
|
||||
|
||||
# Close cover
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert cover.level == 0
|
||||
|
||||
# Set cover position
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: entity_id, "position": 50},
|
||||
blocking=True,
|
||||
)
|
||||
assert cover.level == 50
|
||||
|
||||
|
||||
async def test_cover_update(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test cover state update."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
cover = mock_lutron.areas[0].outputs[2]
|
||||
cover.level = 0
|
||||
cover.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "cover.test_cover"
|
||||
assert hass.states.get(entity_id).state == STATE_CLOSED
|
||||
|
||||
# Simulate update
|
||||
cover.last_level.return_value = 100
|
||||
callback = cover.subscribe.call_args[0][0]
|
||||
callback(cover, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_OPEN
|
||||
assert hass.states.get(entity_id).attributes["current_position"] == 100
|
||||
@@ -0,0 +1,88 @@
|
||||
"""Test Lutron event platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from pylutron import Button
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, async_capture_events, snapshot_platform
|
||||
|
||||
|
||||
async def test_event_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test event setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.EVENT]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_event_single_press(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test single press event."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
button = mock_lutron.areas[0].keypads[0].buttons[0]
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Subscribe to events
|
||||
events = async_capture_events(hass, "lutron_event")
|
||||
|
||||
# Simulate button press
|
||||
for call in button.subscribe.call_args_list:
|
||||
callback = call[0][0]
|
||||
callback(button, None, Button.Event.PRESSED, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check bus event
|
||||
assert len(events) == 1
|
||||
assert events[0].data["action"] == "single"
|
||||
assert events[0].data["uuid"] == "button_uuid"
|
||||
|
||||
|
||||
async def test_event_press_release(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test press and release events."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
button = mock_lutron.areas[0].keypads[0].buttons[0]
|
||||
button.button_type = "MasterRaiseLower"
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Subscribe to events
|
||||
events = async_capture_events(hass, "lutron_event")
|
||||
|
||||
# Simulate button press
|
||||
for call in button.subscribe.call_args_list:
|
||||
callback = call[0][0]
|
||||
callback(button, None, Button.Event.PRESSED, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(events) == 1
|
||||
assert events[0].data["action"] == "pressed"
|
||||
|
||||
# Simulate button release
|
||||
for call in button.subscribe.call_args_list:
|
||||
callback = call[0][0]
|
||||
callback(button, None, Button.Event.RELEASED, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(events) == 2
|
||||
assert events[1].data["action"] == "released"
|
||||
@@ -0,0 +1,108 @@
|
||||
"""Test Lutron fan platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.fan import (
|
||||
ATTR_PERCENTAGE,
|
||||
DOMAIN as FAN_DOMAIN,
|
||||
SERVICE_SET_PERCENTAGE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_fan_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test fan setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
fan = mock_lutron.areas[0].outputs[3]
|
||||
fan.level = 0
|
||||
fan.last_level.return_value = 0
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.FAN]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_fan_services(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test fan services."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
fan = mock_lutron.areas[0].outputs[3]
|
||||
fan.level = 0
|
||||
fan.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "fan.test_fan"
|
||||
|
||||
# Turn on (defaults to medium - 67%)
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert fan.level == 67
|
||||
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert fan.level == 0
|
||||
|
||||
# Set percentage
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
SERVICE_SET_PERCENTAGE,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_PERCENTAGE: 33},
|
||||
blocking=True,
|
||||
)
|
||||
assert fan.level == 33
|
||||
|
||||
|
||||
async def test_fan_update(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test fan state update."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
fan = mock_lutron.areas[0].outputs[3]
|
||||
fan.level = 0
|
||||
fan.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "fan.test_fan"
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# Simulate update
|
||||
fan.last_level.return_value = 100
|
||||
callback = fan.subscribe.call_args[0][0]
|
||||
callback(fan, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
assert hass.states.get(entity_id).attributes[ATTR_PERCENTAGE] == 100
|
||||
@@ -0,0 +1,101 @@
|
||||
"""Test Lutron integration setup."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from homeassistant.components.lutron.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_setup_entry(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test setting up the integration."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
assert await async_setup_component(hass, "lutron", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.runtime_data.client is mock_lutron
|
||||
assert len(mock_config_entry.runtime_data.lights) == 1
|
||||
|
||||
# Verify that the unique ID is generated correctly.
|
||||
# This prevents regression in unique ID generation which would be a breaking change.
|
||||
entity_registry = er.async_get(hass)
|
||||
# The light from mock_lutron has uuid="light_uuid" and guid="12345678901"
|
||||
expected_unique_id = "12345678901_light_uuid"
|
||||
entry = entity_registry.async_get("light.test_light")
|
||||
assert entry.unique_id == expected_unique_id
|
||||
|
||||
|
||||
async def test_unload_entry(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test unloading the integration."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
assert await async_setup_component(hass, "lutron", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_unique_id_migration(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test migration of legacy unique IDs to the newer UUID-based format.
|
||||
|
||||
In older versions of the integration, unique IDs were based on a legacy UUID format.
|
||||
The integration now prefers a newer UUID format when available. This test ensures
|
||||
that existing entities and devices are automatically migrated to the new format
|
||||
without losing their registry entries.
|
||||
"""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
# Setup registries with an entry using the "legacy" unique ID format.
|
||||
# This simulates a user who had configured the integration in an older version.
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass)
|
||||
|
||||
legacy_unique_id = "12345678901_light_legacy_uuid"
|
||||
new_unique_id = "12345678901_light_uuid"
|
||||
|
||||
# Create a device in the registry using the legacy ID
|
||||
device = device_registry.async_get_or_create(
|
||||
config_entry_id=mock_config_entry.entry_id,
|
||||
identifiers={(DOMAIN, legacy_unique_id)},
|
||||
manufacturer="Lutron",
|
||||
name="Test Light",
|
||||
)
|
||||
|
||||
# Create an entity in the registry using the legacy ID
|
||||
entity = entity_registry.async_get_or_create(
|
||||
domain="light",
|
||||
platform="lutron",
|
||||
unique_id=legacy_unique_id,
|
||||
config_entry=mock_config_entry,
|
||||
device_id=device.id,
|
||||
)
|
||||
|
||||
# Verify our starting state: registry holds the legacy ID
|
||||
assert entity.unique_id == legacy_unique_id
|
||||
assert (DOMAIN, legacy_unique_id) in device.identifiers
|
||||
|
||||
# Trigger the integration setup.
|
||||
# The async_setup_entry logic will detect the legacy IDs in the registry
|
||||
# and update them to the new UUIDs provided by the mock_lutron fixture.
|
||||
assert await async_setup_component(hass, "lutron", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify that the entity's unique ID has been updated to the new format.
|
||||
entity = entity_registry.async_get(entity.entity_id)
|
||||
assert entity.unique_id == new_unique_id
|
||||
|
||||
# Verify that the device's identifiers have also been migrated.
|
||||
device = device_registry.async_get(device.id)
|
||||
assert (DOMAIN, new_unique_id) in device.identifiers
|
||||
assert (DOMAIN, legacy_unique_id) not in device.identifiers
|
||||
@@ -0,0 +1,222 @@
|
||||
"""Test Lutron light platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_FLASH,
|
||||
ATTR_TRANSITION,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_light_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test light setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
light.level = 0
|
||||
light.last_level.return_value = 0
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.LIGHT]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_light_turn_on_off(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test light turn on and off."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
light.level = 0
|
||||
light.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.test_light"
|
||||
|
||||
# Turn on
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 128},
|
||||
blocking=True,
|
||||
)
|
||||
light.set_level.assert_called_with(new_level=pytest.approx(50.196, rel=1e-3))
|
||||
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
light.set_level.assert_called_with(new_level=0)
|
||||
|
||||
|
||||
async def test_light_update(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test light state update from library."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
light.level = 0
|
||||
light.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.test_light"
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# Simulate update from library
|
||||
light.last_level.return_value = 100
|
||||
# The library calls the callback registered with subscribe
|
||||
callback = light.subscribe.call_args[0][0]
|
||||
callback(light, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
assert hass.states.get(entity_id).attributes[ATTR_BRIGHTNESS] == 255
|
||||
|
||||
|
||||
async def test_light_transition(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test light turn on/off with transition."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
light.level = 0
|
||||
light.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.test_light"
|
||||
|
||||
# Turn on with transition
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_TRANSITION: 2.5},
|
||||
blocking=True,
|
||||
)
|
||||
# Default brightness is used if not specified (DEFAULT_DIMMER_LEVEL is 50%)
|
||||
light.set_level.assert_called_with(
|
||||
new_level=pytest.approx(50.0, abs=0.5), fade_time_seconds=2.5
|
||||
)
|
||||
|
||||
# Turn off with transition
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_TRANSITION: 3.0},
|
||||
blocking=True,
|
||||
)
|
||||
light.set_level.assert_called_with(new_level=0, fade_time_seconds=3.0)
|
||||
|
||||
|
||||
async def test_light_flash(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test light flash."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.test_light"
|
||||
|
||||
# Short flash
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_FLASH: "short"},
|
||||
blocking=True,
|
||||
)
|
||||
light.flash.assert_called_with(0.5)
|
||||
|
||||
# Long flash
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_FLASH: "long"},
|
||||
blocking=True,
|
||||
)
|
||||
light.flash.assert_called_with(1.5)
|
||||
|
||||
|
||||
async def test_light_brightness_restore(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test light brightness restore logic."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
light = mock_lutron.areas[0].outputs[0]
|
||||
light.level = 0
|
||||
light.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "light.test_light"
|
||||
|
||||
# Turn on first time - uses default (50%)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
light.set_level.assert_called_with(new_level=pytest.approx(50.0, abs=0.5))
|
||||
|
||||
# Simulate update to 50% (Lutron level 50 -> HA level 127)
|
||||
light.last_level.return_value = 50
|
||||
callback = light.subscribe.call_args[0][0]
|
||||
callback(light, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Turn off
|
||||
light.last_level.return_value = 0
|
||||
callback(light, None, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Turn on again - should restore ~50%
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
# HA level 127 -> Lutron level ~49.8
|
||||
light.set_level.assert_called_with(new_level=pytest.approx(50.0, abs=0.5))
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Test Lutron scene platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_scene_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test scene setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.SCENE]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_scene_activate(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test scene activation."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "scene.test_keypad_test_button"
|
||||
button = mock_lutron.areas[0].keypads[0].buttons[0]
|
||||
|
||||
await hass.services.async_call(
|
||||
SCENE_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
button.tap.assert_called_once()
|
||||
@@ -0,0 +1,110 @@
|
||||
"""Test Lutron switch platform."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
async def test_switch_setup(
|
||||
hass: HomeAssistant,
|
||||
mock_lutron: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test switch setup."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
switch = mock_lutron.areas[0].outputs[1]
|
||||
switch.level = 0
|
||||
switch.last_level.return_value = 0
|
||||
|
||||
led = mock_lutron.areas[0].keypads[0].leds[0]
|
||||
led.state = 0
|
||||
led.last_state = 0
|
||||
|
||||
with patch("homeassistant.components.lutron.PLATFORMS", [Platform.SWITCH]):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
async def test_switch_turn_on_off(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test switch turn on and off."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
switch = mock_lutron.areas[0].outputs[1]
|
||||
switch.level = 0
|
||||
switch.last_level.return_value = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "switch.test_switch"
|
||||
|
||||
# Turn on
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert switch.level == 100
|
||||
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert switch.level == 0
|
||||
|
||||
|
||||
async def test_led_turn_on_off(
|
||||
hass: HomeAssistant, mock_lutron: MagicMock, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test LED turn on and off."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
led = mock_lutron.areas[0].keypads[0].leds[0]
|
||||
led.state = 0
|
||||
led.last_state = 0
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_id = "switch.test_keypad_test_button"
|
||||
|
||||
# Turn on
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert led.state == 1
|
||||
|
||||
# Turn off
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert led.state == 0
|
||||
Reference in New Issue
Block a user