215 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
"""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="module")
 | 
						|
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
 |