mirror of
https://github.com/home-assistant/core.git
synced 2026-09-16 21:48:38 +01:00
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>
626 lines
21 KiB
Python
626 lines
21 KiB
Python
"""Tests for Hue scene select entities."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from copy import deepcopy
|
|
from unittest.mock import Mock, patch
|
|
|
|
from aiohue.v2.controllers.events import EventType
|
|
from aiohue.v2.models.scene import Scene as HueScene
|
|
import pytest
|
|
|
|
from homeassistant.components.hue.v2.select import HueSceneSelectEntity
|
|
from homeassistant.const import STATE_UNKNOWN, Platform
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers import entity_registry as er
|
|
from homeassistant.util.json import JsonArrayType
|
|
|
|
from .conftest import setup_platform
|
|
|
|
TEST_ROOM_ID = "6ddc9066-7e7d-4a03-a773-c73937968296"
|
|
TEST_ZONE_ID = "7cee478d-6455-483a-9e32-9f9fdcbcc4f6"
|
|
TEST_ROOM_SCENE_ENTITY = "select.test_room_test_room_scene"
|
|
DUPLICATE_SCENE_ID = "22222222-3333-4444-8555-666666666666"
|
|
LITERAL_SUFFIX_SCENE_ID = "33333333-4444-4555-8666-777777777777"
|
|
|
|
|
|
async def test_scene_select_initial_state(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test that scene select entities are created with correct initial state."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
# A smart scene and its effective regular scene can both be active. The smart
|
|
# scene is the top-level selection shown by the Hue app.
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state is not None
|
|
assert state.state == "Smart Test Scene"
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Smart Test Scene",
|
|
]
|
|
assert hass.states.get("select.test_room_test_room_smart_scene") is None
|
|
|
|
# Test Zone has "Dynamic Test Scene" active (dynamic_palette) from fixture
|
|
state = hass.states.get("select.test_zone_scene")
|
|
assert state is not None
|
|
assert state.state == "Dynamic Test Scene"
|
|
assert state.attributes["options"] == ["Dynamic Test Scene"]
|
|
assert hass.states.get("select.test_zone_smart_scene") is None
|
|
|
|
|
|
async def test_scene_select_becomes_inactive(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test that the select entity reflects unknown state when no scene is active."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
# The active smart scene takes precedence over its effective regular scene.
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state == "Smart Test Scene"
|
|
)
|
|
|
|
smart_scene_id = "8abe5a3e-94c8-4058-908f-56241818509a"
|
|
regular_scene_id = "cdbf3740-7977-4a11-8275-8c78636ad4bd"
|
|
|
|
# When the smart scene stops, fall back to the still-active regular scene.
|
|
mock_bridge_v2.api.emit_event(
|
|
"update",
|
|
{"id": smart_scene_id, "type": "smart_scene", "state": "inactive"},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state
|
|
== "Regular Test Scene"
|
|
)
|
|
|
|
# Once both scenes are inactive, the select has no active option.
|
|
mock_bridge_v2.api.emit_event(
|
|
"update",
|
|
{
|
|
"id": regular_scene_id,
|
|
"type": "scene",
|
|
"status": {"active": "inactive"},
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get("select.test_room_test_room_scene").state == STATE_UNKNOWN
|
|
|
|
# Reactivate the scene
|
|
mock_bridge_v2.api.emit_event(
|
|
"update",
|
|
{
|
|
"id": regular_scene_id,
|
|
"type": "scene",
|
|
"status": {
|
|
"active": "static",
|
|
"last_recall": "2025-12-31T23:59:59.999Z",
|
|
},
|
|
},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state
|
|
== "Regular Test Scene"
|
|
)
|
|
|
|
|
|
async def test_scene_select_activate_option(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test that selecting an option calls the bridge scene recall API."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
# Select an option by calling the select_option service
|
|
mock_bridge_v2.mock_requests.clear()
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
"entity_id": "select.test_room_test_room_scene",
|
|
"option": "Regular Test Scene",
|
|
},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
# Bridge API should have been called with the correct scene id
|
|
regular_scene_id = "cdbf3740-7977-4a11-8275-8c78636ad4bd"
|
|
assert len(mock_bridge_v2.mock_requests) == 1
|
|
path = mock_bridge_v2.mock_requests[0]["path"]
|
|
assert "/scene/" in path
|
|
assert regular_scene_id in path
|
|
|
|
|
|
async def test_scene_select_disambiguates_duplicate_names(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test duplicate regular scene names are exposed and recalled distinctly."""
|
|
test_data = deepcopy(v2_resources_test_data)
|
|
duplicate_scene = deepcopy(
|
|
next(
|
|
resource
|
|
for resource in test_data
|
|
if resource["type"] == "scene"
|
|
and resource["metadata"]["name"] == "Regular Test Scene"
|
|
)
|
|
)
|
|
duplicate_scene["id"] = DUPLICATE_SCENE_ID
|
|
duplicate_scene["status"] = {
|
|
"active": "inactive",
|
|
"last_recall": "2025-09-12T11:41:46.318Z",
|
|
}
|
|
test_data.append(duplicate_scene)
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state is not None
|
|
assert state.state == "Smart Test Scene"
|
|
# The duplicate sorts before the original on scene id, so it keeps the bare name.
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Regular Test Scene (2)",
|
|
"Smart Test Scene",
|
|
]
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
"entity_id": "select.test_room_test_room_scene",
|
|
"option": "Regular Test Scene",
|
|
},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
last_request = mock_bridge_v2.mock_requests[-1]
|
|
assert "/scene/" in last_request["path"]
|
|
assert DUPLICATE_SCENE_ID in last_request["path"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("option", "expected_scene_id"),
|
|
[
|
|
pytest.param(
|
|
"Regular Test Scene",
|
|
DUPLICATE_SCENE_ID,
|
|
id="duplicate_keeps_bare_name",
|
|
),
|
|
pytest.param(
|
|
"Regular Test Scene (2) (2)",
|
|
LITERAL_SUFFIX_SCENE_ID,
|
|
id="literal_name_is_disambiguated",
|
|
),
|
|
],
|
|
)
|
|
async def test_scene_select_disambiguated_label_does_not_shadow_scene_name(
|
|
hass: HomeAssistant,
|
|
mock_bridge_v2: Mock,
|
|
v2_resources_test_data: JsonArrayType,
|
|
option: str,
|
|
expected_scene_id: str,
|
|
) -> None:
|
|
"""Test a generated duplicate label cannot shadow a literal scene name."""
|
|
test_data = deepcopy(v2_resources_test_data)
|
|
regular_scene = next(
|
|
resource
|
|
for resource in test_data
|
|
if resource["type"] == "scene"
|
|
and resource["metadata"]["name"] == "Regular Test Scene"
|
|
)
|
|
|
|
duplicate_scene = deepcopy(regular_scene)
|
|
duplicate_scene["id"] = DUPLICATE_SCENE_ID
|
|
duplicate_scene["status"]["active"] = "inactive"
|
|
test_data.append(duplicate_scene)
|
|
|
|
literal_suffix_scene = deepcopy(regular_scene)
|
|
literal_suffix_scene["id"] = LITERAL_SUFFIX_SCENE_ID
|
|
literal_suffix_scene["metadata"]["name"] = "Regular Test Scene (2)"
|
|
literal_suffix_scene["status"]["active"] = "inactive"
|
|
test_data.append(literal_suffix_scene)
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
state = hass.states.get(TEST_ROOM_SCENE_ENTITY)
|
|
assert state is not None
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Regular Test Scene (2)",
|
|
"Regular Test Scene (2) (2)",
|
|
"Smart Test Scene",
|
|
]
|
|
|
|
mock_bridge_v2.mock_requests.clear()
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{"entity_id": TEST_ROOM_SCENE_ENTITY, "option": option},
|
|
blocking=True,
|
|
)
|
|
assert expected_scene_id in mock_bridge_v2.mock_requests[0]["path"]
|
|
|
|
|
|
async def test_scene_select_refreshes_options_for_scene_events(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test add, rename, and delete events refresh the unified scene options."""
|
|
test_data = deepcopy(v2_resources_test_data)
|
|
regular_scene = next(
|
|
resource
|
|
for resource in test_data
|
|
if resource["type"] == "scene"
|
|
and resource["metadata"]["name"] == "Regular Test Scene"
|
|
)
|
|
smart_scene = next(
|
|
resource for resource in test_data if resource["type"] == "smart_scene"
|
|
)
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
added_scene = deepcopy(regular_scene)
|
|
added_scene["id"] = "22222222-3333-4444-8555-666666666666"
|
|
added_scene["metadata"]["name"] = "Added scene"
|
|
added_scene["status"]["active"] = "inactive"
|
|
mock_bridge_v2.api.emit_event("add", added_scene)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state is not None
|
|
assert state.attributes["options"] == [
|
|
"Added scene",
|
|
"Regular Test Scene",
|
|
"Smart Test Scene",
|
|
]
|
|
|
|
renamed_scene = deepcopy(added_scene)
|
|
renamed_scene["metadata"]["name"] = "Renamed scene"
|
|
mock_bridge_v2.api.emit_event("update", renamed_scene)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Renamed scene",
|
|
"Smart Test Scene",
|
|
]
|
|
|
|
# Deleting the active smart scene removes its option and exposes its effective
|
|
# regular scene as the current selection.
|
|
mock_bridge_v2.api.emit_event("delete", smart_scene)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state.state == "Regular Test Scene"
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Renamed scene",
|
|
]
|
|
|
|
|
|
async def test_scene_select_prefers_active_smart_scene(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test smart scene state transitions in the unified scene select."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
# Smart scene starts active
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state == "Smart Test Scene"
|
|
)
|
|
|
|
smart_scene_id = "8abe5a3e-94c8-4058-908f-56241818509a"
|
|
|
|
# Deactivate smart scene
|
|
mock_bridge_v2.api.emit_event(
|
|
"update",
|
|
{"id": smart_scene_id, "type": "smart_scene", "state": "inactive"},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state
|
|
== "Regular Test Scene"
|
|
)
|
|
|
|
# Reactivate smart scene
|
|
mock_bridge_v2.api.emit_event(
|
|
"update",
|
|
{"id": smart_scene_id, "type": "smart_scene", "state": "active"},
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert (
|
|
hass.states.get("select.test_room_test_room_scene").state == "Smart Test Scene"
|
|
)
|
|
|
|
|
|
async def test_scene_select_activate_smart_scene_option(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test selecting a smart scene uses the smart scene recall API."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
mock_bridge_v2.mock_requests.clear()
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{"entity_id": "select.test_room_test_room_scene", "option": "Smart Test Scene"},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
smart_scene_id = "8abe5a3e-94c8-4058-908f-56241818509a"
|
|
assert len(mock_bridge_v2.mock_requests) == 1
|
|
path = mock_bridge_v2.mock_requests[0]["path"]
|
|
assert "/smart_scene/" in path
|
|
assert smart_scene_id in path
|
|
|
|
|
|
async def test_scene_select_disambiguates_duplicate_smart_scene_names(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test duplicate smart scene names are exposed and recalled distinctly."""
|
|
test_data = deepcopy(v2_resources_test_data)
|
|
duplicate_smart_scene = deepcopy(
|
|
next(resource for resource in test_data if resource["type"] == "smart_scene")
|
|
)
|
|
duplicate_smart_scene_id = "11111111-2222-4333-8444-555555555555"
|
|
duplicate_smart_scene["id"] = duplicate_smart_scene_id
|
|
duplicate_smart_scene["state"] = "inactive"
|
|
test_data.append(duplicate_smart_scene)
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state is not None
|
|
# The duplicate sorts before the original on scene id, so it keeps the bare name.
|
|
assert state.state == "Smart Test Scene (2)"
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Smart Test Scene",
|
|
"Smart Test Scene (2)",
|
|
]
|
|
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
"entity_id": "select.test_room_test_room_scene",
|
|
"option": "Smart Test Scene",
|
|
},
|
|
blocking=True,
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
last_request = mock_bridge_v2.mock_requests[-1]
|
|
assert "/smart_scene/" in last_request["path"]
|
|
assert duplicate_smart_scene_id in last_request["path"]
|
|
|
|
|
|
async def test_scene_select_disambiguates_names_across_scene_types(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test identical regular and smart scene names remain independently selectable."""
|
|
test_data = deepcopy(v2_resources_test_data)
|
|
smart_scene = next(
|
|
resource for resource in test_data if resource["type"] == "smart_scene"
|
|
)
|
|
smart_scene["metadata"]["name"] = "Regular Test Scene"
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
state = hass.states.get("select.test_room_test_room_scene")
|
|
assert state is not None
|
|
# The smart scene sorts before the regular scene on scene id.
|
|
assert state.state == "Regular Test Scene"
|
|
assert state.attributes["options"] == [
|
|
"Regular Test Scene",
|
|
"Regular Test Scene (2)",
|
|
]
|
|
|
|
mock_bridge_v2.mock_requests.clear()
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
"entity_id": "select.test_room_test_room_scene",
|
|
"option": "Regular Test Scene (2)",
|
|
},
|
|
blocking=True,
|
|
)
|
|
assert "/scene/" in mock_bridge_v2.mock_requests[0]["path"]
|
|
|
|
mock_bridge_v2.mock_requests.clear()
|
|
await hass.services.async_call(
|
|
"select",
|
|
"select_option",
|
|
{
|
|
"entity_id": "select.test_room_test_room_scene",
|
|
"option": "Regular Test Scene",
|
|
},
|
|
blocking=True,
|
|
)
|
|
assert "/smart_scene/" in mock_bridge_v2.mock_requests[0]["path"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("entity_id", "expected_options"),
|
|
[
|
|
(
|
|
"select.test_room_test_room_scene",
|
|
["Regular Test Scene", "Smart Test Scene"],
|
|
),
|
|
("select.test_zone_scene", ["Dynamic Test Scene"]),
|
|
],
|
|
)
|
|
async def test_scene_select_options(
|
|
hass: HomeAssistant,
|
|
mock_bridge_v2: Mock,
|
|
v2_resources_test_data: JsonArrayType,
|
|
entity_id: str,
|
|
expected_options: list[str],
|
|
) -> None:
|
|
"""Test that each select entity exposes the correct scene options for its group."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state is not None
|
|
assert state.attributes["options"] == expected_options
|
|
|
|
|
|
async def test_scene_select_removed_when_group_deleted(
|
|
hass: HomeAssistant,
|
|
entity_registry: er.EntityRegistry,
|
|
mock_bridge_v2: Mock,
|
|
v2_resources_test_data: JsonArrayType,
|
|
) -> None:
|
|
"""Test that deleting a Hue group removes its scene select entity."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
assert hass.states.get(TEST_ROOM_SCENE_ENTITY) is not None
|
|
assert entity_registry.async_get(TEST_ROOM_SCENE_ENTITY) is not None
|
|
|
|
mock_bridge_v2.api.emit_event(
|
|
"delete",
|
|
{"type": "room", "id": TEST_ROOM_ID},
|
|
)
|
|
await hass.async_block_till_done()
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.states.get(TEST_ROOM_SCENE_ENTITY) is None
|
|
assert entity_registry.async_get(TEST_ROOM_SCENE_ENTITY) is None
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("source_id", "new_id", "new_name", "entity_id"),
|
|
[
|
|
pytest.param(
|
|
TEST_ROOM_ID,
|
|
"aaaaaaaa-bbbb-4ccc-8ddd-111111111111",
|
|
"New Room",
|
|
"select.new_room_new_room_scene",
|
|
id="room",
|
|
),
|
|
pytest.param(
|
|
TEST_ZONE_ID,
|
|
"aaaaaaaa-bbbb-4ccc-8ddd-222222222222",
|
|
"New Zone",
|
|
"select.new_zone_scene",
|
|
id="zone",
|
|
),
|
|
],
|
|
)
|
|
async def test_scene_select_created_when_group_added(
|
|
hass: HomeAssistant,
|
|
mock_bridge_v2: Mock,
|
|
v2_resources_test_data: JsonArrayType,
|
|
source_id: str,
|
|
new_id: str,
|
|
new_name: str,
|
|
entity_id: str,
|
|
) -> None:
|
|
"""Test that adding a Hue group at runtime creates its scene select entity."""
|
|
await mock_bridge_v2.api.load_test_data(v2_resources_test_data)
|
|
await setup_platform(hass, mock_bridge_v2, [Platform.SCENE, Platform.SELECT])
|
|
|
|
assert hass.states.get(entity_id) is None
|
|
|
|
new_group = deepcopy(
|
|
next(
|
|
resource
|
|
for resource in v2_resources_test_data
|
|
if resource["id"] == source_id
|
|
)
|
|
)
|
|
new_group["id"] = new_id
|
|
new_group["metadata"]["name"] = new_name
|
|
mock_bridge_v2.api.emit_event("add", new_group)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(entity_id)
|
|
assert state is not None
|
|
assert state.attributes["options"] == []
|
|
|
|
|
|
async def test_scene_select_refreshes_options_missed_before_subscribe(
|
|
hass: HomeAssistant, mock_bridge_v2: Mock, v2_resources_test_data: JsonArrayType
|
|
) -> None:
|
|
"""Test options include a scene added after init and before subscribe."""
|
|
test_data = [
|
|
deepcopy(resource)
|
|
for resource in v2_resources_test_data
|
|
if resource["id"] != TEST_ZONE_ID
|
|
]
|
|
regular_scene = next(
|
|
resource
|
|
for resource in test_data
|
|
if resource["type"] == "scene"
|
|
and resource["metadata"]["name"] == "Regular Test Scene"
|
|
)
|
|
late_scene = deepcopy(regular_scene)
|
|
late_scene["id"] = "44444444-5555-4666-8777-888888888888"
|
|
late_scene["metadata"]["name"] = "Late scene"
|
|
late_scene["status"]["active"] = "inactive"
|
|
|
|
original_added_to_hass = HueSceneSelectEntity.async_added_to_hass
|
|
|
|
async def async_added_to_hass_with_late_scene(
|
|
self: HueSceneSelectEntity,
|
|
) -> None:
|
|
assert self.unique_id == f"{TEST_ROOM_ID}_scene_select"
|
|
scene_added = asyncio.Event()
|
|
|
|
def on_scene_added(_: EventType, scene: HueScene) -> None:
|
|
scene_added.set()
|
|
|
|
unsubscribe = mock_bridge_v2.api.scenes.subscribe(
|
|
on_scene_added,
|
|
late_scene["id"],
|
|
EventType.RESOURCE_ADDED,
|
|
)
|
|
try:
|
|
mock_bridge_v2.api.emit_event("add", late_scene)
|
|
async with asyncio.timeout(5):
|
|
await scene_added.wait()
|
|
finally:
|
|
unsubscribe()
|
|
|
|
assert late_scene["id"] in mock_bridge_v2.api.scenes
|
|
assert "Late scene" not in self.options
|
|
await original_added_to_hass(self)
|
|
|
|
await mock_bridge_v2.api.load_test_data(test_data)
|
|
with patch.object(
|
|
HueSceneSelectEntity,
|
|
"async_added_to_hass",
|
|
async_added_to_hass_with_late_scene,
|
|
):
|
|
await setup_platform(hass, mock_bridge_v2, Platform.SELECT)
|
|
|
|
state = hass.states.get(TEST_ROOM_SCENE_ENTITY)
|
|
assert state is not None
|
|
assert state.attributes["options"] == [
|
|
"Late scene",
|
|
"Regular Test Scene",
|
|
"Smart Test Scene",
|
|
]
|