"""Test the Insteon Scenes APIs.""" import json import os from unittest.mock import AsyncMock, patch from pyinsteon.constants import ResponseStatus import pyinsteon.managers.scene_manager import pytest from homeassistant.components.insteon.api import async_load_api, scenes from homeassistant.components.insteon.const import ID, TYPE from homeassistant.core import HomeAssistant from .mock_devices import MockDevices from tests.common import load_fixture from tests.typing import WebSocketGenerator @pytest.fixture(name="scene_data", scope="session") def aldb_data_fixture(): """Load the controller state fixture data.""" return json.loads(load_fixture("insteon/scene_data.json")) @pytest.fixture(name="remove_json") def remove_insteon_devices_json(hass): """Fixture to remove insteon_devices.json at the end of the test.""" yield file = os.path.join(hass.config.config_dir, "insteon_devices.json") if os.path.exists(file): os.remove(file) def _scene_to_array(scene): """Convert a scene object to a dictionary.""" scene_list = [] for device, links in scene["devices"].items(): for link in links: link_dict = {} link_dict["address"] = device.id link_dict["data1"] = link.data1 link_dict["data2"] = link.data2 link_dict["data3"] = link.data3 scene_list.append(link_dict) return scene_list async def _setup(hass, hass_ws_client, scene_data): """Set up tests.""" ws_client = await hass_ws_client(hass) devices = MockDevices() await devices.async_load() async_load_api(hass) for device in scene_data: addr = device["address"] aldb = device["aldb"] devices.fill_aldb(addr, aldb) return ws_client, devices # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_get_scenes( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data ) -> None: """Test getting all Insteon scenes.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) with patch.object(pyinsteon.managers.scene_manager, "devices", devices): await ws_client.send_json({ID: 1, TYPE: "insteon/scenes/get"}) msg = await ws_client.receive_json() result = msg["result"] assert len(result) == 1 assert len(result["20"]) == 3 # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_get_scene( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data ) -> None: """Test getting an Insteon scene.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) with patch.object(pyinsteon.managers.scene_manager, "devices", devices): await ws_client.send_json({ID: 1, TYPE: "insteon/scene/get", "scene_id": 20}) msg = await ws_client.receive_json() result = msg["result"] assert len(result["devices"]) == 3 # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_save_scene( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data, remove_json ) -> None: """Test saving an Insteon scene.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) mock_add_or_update_scene = AsyncMock(return_value=(20, ResponseStatus.SUCCESS)) with patch.object( pyinsteon.managers.scene_manager, "devices", devices ), patch.object(scenes, "async_add_or_update_scene", mock_add_or_update_scene): scene = await pyinsteon.managers.scene_manager.async_get_scene(20) scene["devices"]["1a1a1a"] = [] links = _scene_to_array(scene) await ws_client.send_json( { ID: 1, TYPE: "insteon/scene/save", "scene_id": 20, "name": "Some scene name", "links": links, } ) msg = await ws_client.receive_json() result = msg["result"] assert result["result"] assert result["scene_id"] == 20 # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_save_new_scene( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data, remove_json ) -> None: """Test saving a new Insteon scene.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) mock_add_or_update_scene = AsyncMock(return_value=(21, ResponseStatus.SUCCESS)) with patch.object( pyinsteon.managers.scene_manager, "devices", devices ), patch.object(scenes, "async_add_or_update_scene", mock_add_or_update_scene): scene = await pyinsteon.managers.scene_manager.async_get_scene(20) scene["devices"]["1a1a1a"] = [] links = _scene_to_array(scene) await ws_client.send_json( { ID: 1, TYPE: "insteon/scene/save", "scene_id": -1, "name": "Some scene name", "links": links, } ) msg = await ws_client.receive_json() result = msg["result"] assert result["result"] assert result["scene_id"] == 21 # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_save_scene_error( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data, remove_json ) -> None: """Test saving an Insteon scene with error.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) mock_add_or_update_scene = AsyncMock(return_value=(20, ResponseStatus.FAILURE)) with patch.object( pyinsteon.managers.scene_manager, "devices", devices ), patch.object(scenes, "async_add_or_update_scene", mock_add_or_update_scene): scene = await pyinsteon.managers.scene_manager.async_get_scene(20) scene["devices"]["1a1a1a"] = [] links = _scene_to_array(scene) await ws_client.send_json( { ID: 1, TYPE: "insteon/scene/save", "scene_id": 20, "name": "Some scene name", "links": links, } ) msg = await ws_client.receive_json() result = msg["result"] assert not result["result"] assert result["scene_id"] == 20 # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) async def test_delete_scene( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, scene_data, remove_json ) -> None: """Test delete an Insteon scene.""" ws_client, devices = await _setup(hass, hass_ws_client, scene_data) mock_delete_scene = AsyncMock(return_value=ResponseStatus.SUCCESS) with patch.object( pyinsteon.managers.scene_manager, "devices", devices ), patch.object(scenes, "async_delete_scene", mock_delete_scene): await ws_client.send_json( { ID: 1, TYPE: "insteon/scene/delete", "scene_id": 20, } ) msg = await ws_client.receive_json() result = msg["result"] assert result["result"] assert result["scene_id"] == 20