Skip to content

Commit ba14fd2

Browse files
committed
coverage
1 parent 65e6722 commit ba14fd2

File tree

7 files changed

+49
-22
lines changed

7 files changed

+49
-22
lines changed

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ async def __aenter__(self) -> CombinedWebsocketGateways:
418418
await client_gateway.clients.listen()
419419
await ws_gateway.async_block_till_done()
420420
await client_gateway.async_initialize()
421+
assert client_gateway.state is not None
421422

422423
self.combined_gateways = CombinedWebsocketGateways(
423424
self.zha_data, ws_gateway, client_gateway

tests/websocket/test_client_controller.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ async def test_ws_client_gateway_devices(
178178
await zha_gateway.async_block_till_done()
179179
assert len(ws_client_gateway.devices) == 2
180180

181+
# test client gateway device removal
182+
await ws_client_gateway.async_remove_device(zha_device.ieee)
183+
await zha_gateway.async_block_till_done()
184+
assert len(ws_client_gateway.devices) == 1
185+
186+
# let's add it back
187+
zha_device = await join_zigpy_device(zha_gateway, zigpy_device)
188+
await zha_gateway.async_block_till_done()
189+
assert len(ws_client_gateway.devices) == 2
190+
181191
# we removed and joined the device again so lets get the entity again
182192
client_device = ws_client_gateway.devices.get(zha_device.ieee)
183193
assert client_device is not None
@@ -398,6 +408,15 @@ async def test_ws_client_gateway_groups(
398408
assert client_device1.ieee in response.members_by_ieee
399409
assert client_device2.ieee in response.members_by_ieee
400410

411+
group_from_ws_client_gateway = ws_client_gateway.get_group(response.group_id)
412+
assert group_from_ws_client_gateway is not None
413+
assert group_from_ws_client_gateway.group_id == response.group_id
414+
assert group_from_ws_client_gateway.name == response.name
415+
assert (
416+
group_from_ws_client_gateway.info_object.members_by_ieee
417+
== response.members_by_ieee
418+
)
419+
401420
# test remove member from group from ws_client_gateway
402421
response = await ws_client_gateway.groups_helper.remove_group_members(
403422
response,

tests/websocket/test_websocket_server_client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
from __future__ import annotations
44

5+
from unittest.mock import patch
6+
57
import pytest
68

79
from tests.conftest import CombinedWebsocketGateways
810
from zha.application.gateway import WebSocketClientGateway, WebSocketServerGateway
911
from zha.application.helpers import ZHAData
12+
from zha.websocket import ZHAWebSocketException
1013
from zha.websocket.client.client import Client
1114
from zha.websocket.client.helpers import ClientHelper
1215

@@ -44,6 +47,13 @@ async def test_server_client_connect_disconnect(
4447
assert not gateway.is_serving
4548
assert gateway._ws_server is None
4649

50+
with (
51+
pytest.raises(ZHAWebSocketException),
52+
patch("zha.websocket.client.client.Client.connect", side_effect=TimeoutError),
53+
):
54+
async with WebSocketClientGateway(zha_data) as client_gateway:
55+
assert client_gateway.client.connected
56+
4757

4858
async def test_client_helper_disconnect(
4959
zha_data: ZHAData,

zha/application/gateway.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
gather_with_limited_concurrency,
7979
)
8080
from zha.event import EventBase
81+
from zha.websocket import ZHAWebSocketException
8182
from zha.websocket.client.client import Client
8283
from zha.websocket.client.helpers import (
8384
AlarmControlPanelHelper,
@@ -113,10 +114,6 @@
113114

114115
if TYPE_CHECKING:
115116
from zha.application.platforms.events import EntityStateChangedEvent
116-
from zha.websocket.server.api.model import (
117-
WebSocketCommand,
118-
WebSocketCommandResponse,
119-
)
120117
from zha.zigbee.model import ExtendedDeviceInfo, ZHAEvent
121118

122119
BLOCK_LOG_TIMEOUT: Final[int] = 60
@@ -913,10 +910,10 @@ def __init__(self, config: ZHAData) -> None:
913910
self._client: Client = Client(
914911
self._ws_server_url, aiohttp_session=config.ws_client_config.aiohttp_session
915912
)
913+
self._state: State
916914
self._devices: dict[EUI64, WebSocketClientDevice] = {}
917915
self._groups: dict[int, WebSocketClientGroup] = {}
918916
self.coordinator_zha_device: WebSocketClientDevice = None # type: ignore[assignment]
919-
self._state: State
920917
self.lights: LightHelper = LightHelper(self._client)
921918
self.switches: SwitchHelper = SwitchHelper(self._client)
922919
self.sirens: SirenHelper = SirenHelper(self._client)
@@ -965,9 +962,10 @@ async def connect(self) -> None:
965962
try:
966963
async with timeout(CONNECT_TIMEOUT):
967964
await self._client.connect()
968-
except Exception as err:
965+
except TimeoutError as err:
969966
_LOGGER.exception("Unable to connect to the ZHA wss", exc_info=err)
970-
raise err
967+
await self._client.disconnect()
968+
raise ZHAWebSocketException from err
971969

972970
async def disconnect(self) -> None:
973971
"""Disconnect from the websocket server."""
@@ -992,10 +990,6 @@ def create_and_track_task(self, coroutine: Coroutine) -> asyncio.Task:
992990
task.add_done_callback(self._tasks.remove)
993991
return task
994992

995-
async def send_command(self, command: WebSocketCommand) -> WebSocketCommandResponse:
996-
"""Send a command and get a response."""
997-
return await self._client.async_send_command(command)
998-
999993
async def load_devices(self) -> None:
1000994
"""Restore ZHA devices from zigpy application state."""
1001995
response_devices = await self.devices_helper.get_devices()
@@ -1104,7 +1098,7 @@ def handle_state_changed(self, event: EntityStateChangedEvent) -> None:
11041098
def handle_zha_event(self, event: ZHAEvent) -> None:
11051099
"""Handle a zha_event from the websocket server."""
11061100
_LOGGER.debug("zha_event: %s", event)
1107-
device = self.devices.get(event.device.ieee)
1101+
device = self.devices.get(event.device_ieee)
11081102
if device is None:
11091103
_LOGGER.warning("Received zha_event from unknown device: %s", event)
11101104
return

zha/websocket/client/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ async def disconnect(self) -> None:
163163

164164
self._listen_task = None
165165

166-
assert self._client is not None
167-
await self._client.close()
166+
if self._client is not None:
167+
await self._client.close()
168168

169169
if self._close_aiohttp_session:
170170
await self.aiohttp_session.close()

zha/websocket/server/client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ async def disconnect(
247247
gateway: WebSocketServerGateway, client: Client, command: WebSocketCommand
248248
) -> None:
249249
"""Disconnect the client."""
250-
client.disconnect()
251250
gateway.client_manager.remove_client(client)
252251

253252

zha/zigbee/device.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -681,14 +681,18 @@ def update_available(
681681

682682
def emit_zha_event(self, event_data: dict[str, str | int]) -> None: # pylint: disable=unused-argument
683683
"""Relay events directly."""
684-
self.emit(
685-
ZHA_EVENT,
686-
ZHAEvent(
687-
device_ieee=self.ieee,
688-
unique_id=str(self.ieee),
689-
data=event_data,
690-
),
684+
event: ZHAEvent = ZHAEvent(
685+
device_ieee=self.ieee,
686+
unique_id=str(self.ieee),
687+
data=event_data,
691688
)
689+
self.emit(ZHA_EVENT, event)
690+
691+
# pylint: disable=import-outside-toplevel
692+
from zha.application.gateway import WebSocketServerGateway
693+
694+
if isinstance(self.gateway, WebSocketServerGateway):
695+
self.gateway.emit(ZHA_EVENT, event)
692696

693697
async def _async_became_available(self) -> None:
694698
"""Update device availability and signal entities."""

0 commit comments

Comments
 (0)