Marcel van der Veldt e2308fd15c
Add matter integration BETA (#83064)
* Add matter base (#79372)

Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>

* Add matter server add-on flow (#82698)

* Add matter server add-on flow

* Fix stale error argument

* Clean docstrings

* Use localhost as default address

* Add matter websocket api foundation (#82848)

* Add matter config entry add-on management (#82865)

* Use matter refactored server/client library (#83003)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Bump python-matter-server to 1.0.6 (#83059)

* Extend matter websocket api (#82948)

* Extend matter websocket api

* Finish docstring

* Fix pin type

* Adjust api after new client

* Adjust api to frontend for now

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2022-12-01 20:44:56 +01:00

147 lines
4.5 KiB
Python

"""Provide common test tools."""
from __future__ import annotations
import asyncio
from functools import cache
import json
import logging
from typing import TYPE_CHECKING, Any
from unittest.mock import Mock, patch
from matter_server.client import MatterClient
from matter_server.common.models.node import MatterNode
from matter_server.common.models.server_information import ServerInfo
import pytest
from tests.common import MockConfigEntry, load_fixture
if TYPE_CHECKING:
from homeassistant.core import HomeAssistant
MOCK_FABRIC_ID = 12341234
MOCK_COMPR_FABRIC_ID = 1234
# TEMP: Tests need to be fixed
pytestmark = pytest.mark.skip("all tests still WIP")
class MockClient(MatterClient):
"""Represent a mock Matter client."""
mock_client_disconnect: asyncio.Event
mock_commands: dict[type, Any] = {}
mock_sent_commands: list[dict[str, Any]] = []
def __init__(self) -> None:
"""Initialize the mock client."""
super().__init__("mock-url", None)
self.mock_commands: dict[type, Any] = {}
self.mock_sent_commands = []
self.server_info = ServerInfo(
fabric_id=MOCK_FABRIC_ID, compressed_fabric_id=MOCK_COMPR_FABRIC_ID
)
async def connect(self) -> None:
"""Connect to the Matter server."""
self.server_info = Mock(compressed_abric_d=MOCK_COMPR_FABRIC_ID)
async def listen(self, driver_ready: asyncio.Event) -> None:
"""Listen for events."""
driver_ready.set()
self.mock_client_disconnect = asyncio.Event()
await self.mock_client_disconnect.wait()
def mock_command(self, command_type: type, response: Any) -> None:
"""Mock a command."""
self.mock_commands[command_type] = response
async def async_send_command(
self,
command: str,
args: dict[str, Any],
require_schema: int | None = None,
) -> dict:
"""Send mock commands."""
if command == "device_controller.SendCommand" and (
(cmd_type := type(args.get("payload"))) in self.mock_commands
):
self.mock_sent_commands.append(args)
return self.mock_commands[cmd_type]
return await super().async_send_command(command, args, require_schema)
async def async_send_command_no_wait(
self, command: str, args: dict[str, Any], require_schema: int | None = None
) -> None:
"""Send a command without waiting for the response."""
if command == "SendCommand" and (
(cmd_type := type(args.get("payload"))) in self.mock_commands
):
self.mock_sent_commands.append(args)
return self.mock_commands[cmd_type]
return await super().async_send_command_no_wait(command, args, require_schema)
@pytest.fixture
async def mock_matter() -> Mock:
"""Mock matter fixture."""
return await get_mock_matter()
async def get_mock_matter() -> Mock:
"""Get mock Matter."""
return Mock(
adapter=Mock(logger=logging.getLogger("mock_matter")), client=MockClient()
)
@cache
def load_node_fixture(fixture: str) -> str:
"""Load a fixture."""
return load_fixture(f"matter/nodes/{fixture}.json")
def load_and_parse_node_fixture(fixture: str) -> dict[str, Any]:
"""Load and parse a node fixture."""
return json.loads(load_node_fixture(fixture))
async def setup_integration_with_node_fixture(
hass: HomeAssistant, hass_storage: dict[str, Any], node_fixture: str
) -> MatterNode:
"""Set up Matter integration with fixture as node."""
node_data = load_and_parse_node_fixture(node_fixture)
node = MatterNode(
await get_mock_matter(),
node_data,
)
config_entry = MockConfigEntry(
domain="matter", data={"url": "http://mock-matter-server-url"}
)
config_entry.add_to_hass(hass)
storage_key = f"matter_{config_entry.entry_id}"
hass_storage[storage_key] = {
"version": 1,
"minor_version": 0,
"key": storage_key,
"data": {
"compressed_fabric_id": MOCK_COMPR_FABRIC_ID,
"next_node_id": 4339,
"nodes": {str(node.node_id): node_data},
},
}
with patch(
"matter_server.client.matter.Client", return_value=node.matter.client
), patch(
"matter_server.client.model.node.MatterDeviceTypeInstance.subscribe_updates",
), patch(
"matter_server.client.model.node.MatterDeviceTypeInstance.update_attributes"
):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return node