Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions tests/components/overkiz/fixtures/scenarios/cozytouch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[
{
"creationTime": 1763489130000,
"lastUpdateTime": 1763489130000,
"label": "Label 1",
"metadata": "a56b34aa-2f6f-4e24-b73a-c2ed23f0ac91",
"shortcut": false,
"notificationTypeMask": 0,
"notificationCondition": "NEVER",
"actions": [
{
"deviceURL": "io://1234-5678-1234/13880042",
"commands": [
{
"type": 1,
"name": "setHeatingLevel",
"parameters": ["eco"]
}
]
}
],
"oid": "0a0589bb-9471-4667-a2a9-4602beb2a2e8"
},
{
"creationTime": 1763214463000,
"lastUpdateTime": 1763214463000,
"label": "Label 2",
"metadata": "f6206578-b730-4f66-b322-e8d0a5625407",
"shortcut": false,
"notificationTypeMask": 0,
"notificationCondition": "NEVER",
"actions": [
{
"deviceURL": "io://1234-5678-1234/15581081",
"commands": [
{
"type": 1,
"name": "setHeatingLevel",
"parameters": ["comfort"]
}
]
}
],
"oid": "50d39fc3-9368-49c9-bcbf-c74f3ce1678a"
}
]
26 changes: 26 additions & 0 deletions tests/components/overkiz/fixtures/scenarios/tahoma_switch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"creationTime": 1766929020000,
"lastUpdateTime": 1766929020000,
"label": "I'm arriving",
"metadata": "{\"tahoma\":{\"version\":1,\"icon\":\"at_home\",\"template\":\"arriving\"}}",
"shortcut": false,
"notificationTypeMask": 16,
"notificationCondition": "ON_ERROR",
"notificationText": "Your scene I'm arriving could not be played correctly due to an error in one of your products.",
"notificationTitle": "[$[setupLabel]] : Impossible to play the scene I'm arriving",
"actions": [
{
"deviceURL": "rts://1234-5678-1234/16756006",
"commands": [
{
"type": 1,
"name": "open",
"parameters": [1]
}
]
}
],
"oid": "d1b689e1-4087-473d-b726-d3b24770856f"
}
]
151 changes: 151 additions & 0 deletions tests/components/overkiz/snapshots/test_scene.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# serializer version: 1
# name: test_scene_entities_snapshot[scenarios/cozytouch.json][scene.label_1-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'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.label_1',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Label 1',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Label 1',
'platform': 'overkiz',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '0a0589bb-9471-4667-a2a9-4602beb2a2e8',
'unit_of_measurement': None,
})
# ---
# name: test_scene_entities_snapshot[scenarios/cozytouch.json][scene.label_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Label 1',
}),
'context': <ANY>,
'entity_id': 'scene.label_1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_scene_entities_snapshot[scenarios/cozytouch.json][scene.label_2-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'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.label_2',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Label 2',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Label 2',
'platform': 'overkiz',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': '50d39fc3-9368-49c9-bcbf-c74f3ce1678a',
'unit_of_measurement': None,
})
# ---
# name: test_scene_entities_snapshot[scenarios/cozytouch.json][scene.label_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Label 2',
}),
'context': <ANY>,
'entity_id': 'scene.label_2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_scene_entities_snapshot[scenarios/tahoma_switch.json][scene.i_m_arriving-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'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.i_m_arriving',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': "I'm arriving",
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': "I'm arriving",
'platform': 'overkiz',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'd1b689e1-4087-473d-b726-d3b24770856f',
'unit_of_measurement': None,
})
# ---
# name: test_scene_entities_snapshot[scenarios/tahoma_switch.json][scene.i_m_arriving-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': "I'm arriving",
}),
'context': <ANY>,
'entity_id': 'scene.i_m_arriving',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
128 changes: 128 additions & 0 deletions tests/components/overkiz/test_scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""Tests for the Overkiz scene platform."""

from collections.abc import Generator
from unittest.mock import AsyncMock, patch

import humps
from pyoverkiz.models import Scenario
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.overkiz.const import DOMAIN
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 .conftest import MockOverkizClient, SetupOverkizIntegration

from tests.common import load_json_array_fixture, snapshot_platform

SCENARIO_FIXTURES = [
"scenarios/cozytouch.json",
"scenarios/tahoma_switch.json",
]


def load_scenarios_fixture(fixture: str) -> list[Scenario]:
"""Load scenario fixture and return Scenario objects."""
data = load_json_array_fixture(fixture, DOMAIN)
return [Scenario(**humps.decamelize(s)) for s in data]


@pytest.fixture(autouse=True)
def fixture_platforms() -> Generator[None]:
"""Limit platforms to scene only."""
with patch("homeassistant.components.overkiz.PLATFORMS", [Platform.SCENE]):
yield


@pytest.mark.parametrize("fixture", SCENARIO_FIXTURES)
async def test_scene_entities_snapshot(
hass: HomeAssistant,
setup_overkiz_integration: SetupOverkizIntegration,
entity_registry: er.EntityRegistry,
mock_client: MockOverkizClient,
snapshot: SnapshotAssertion,
fixture: str,
) -> None:
"""Test scene entities via snapshot for each fixture."""
scenarios = load_scenarios_fixture(fixture)
mock_client.get_scenarios = AsyncMock(return_value=scenarios)

config_entry = await setup_overkiz_integration()

await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)


async def test_scene_activate(
hass: HomeAssistant,
setup_overkiz_integration: SetupOverkizIntegration,
mock_client: MockOverkizClient,
) -> None:
"""Test activating a scene calls execute_scenario with the correct OID."""
scenarios = load_scenarios_fixture("scenarios/tahoma_switch.json")
mock_client.get_scenarios = AsyncMock(return_value=scenarios)
mock_client.execute_scenario = AsyncMock(return_value="exec-1")

await setup_overkiz_integration()

await hass.services.async_call(
SCENE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "scene.i_m_arriving"},
blocking=True,
)

mock_client.execute_scenario.assert_awaited_once_with(
"d1b689e1-4087-473d-b726-d3b24770856f"
)


async def test_scene_activate_multiple(
hass: HomeAssistant,
setup_overkiz_integration: SetupOverkizIntegration,
mock_client: MockOverkizClient,
) -> None:
"""Test activating different scenes uses the correct OID for each."""
scenarios = load_scenarios_fixture("scenarios/cozytouch.json")
mock_client.get_scenarios = AsyncMock(return_value=scenarios)
mock_client.execute_scenario = AsyncMock(return_value="exec-1")

await setup_overkiz_integration()

await hass.services.async_call(
SCENE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "scene.label_1"},
blocking=True,
)

mock_client.execute_scenario.assert_awaited_once_with(
"0a0589bb-9471-4667-a2a9-4602beb2a2e8"
)

mock_client.execute_scenario.reset_mock()

await hass.services.async_call(
SCENE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "scene.label_2"},
blocking=True,
)

mock_client.execute_scenario.assert_awaited_once_with(
"50d39fc3-9368-49c9-bcbf-c74f3ce1678a"
)


async def test_no_scenes_when_empty(
hass: HomeAssistant,
setup_overkiz_integration: SetupOverkizIntegration,
mock_client: MockOverkizClient,
) -> None:
"""Test no scene entities are created when there are no scenarios."""
await setup_overkiz_integration()

states = hass.states.async_entity_ids(SCENE_DOMAIN)
assert len(states) == 0