mirror of
https://github.com/home-assistant/core.git
synced 2026-07-04 05:05:38 +01:00
144 lines
4.1 KiB
Python
144 lines
4.1 KiB
Python
"""Tests for the syncthing integration setup and client."""
|
|
|
|
import asyncio
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from aiosyncthing.exceptions import SyncthingError
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
import pytest
|
|
|
|
from homeassistant.components.syncthing.const import (
|
|
DOMAIN,
|
|
EVENTS,
|
|
RECONNECT_INTERVAL,
|
|
SERVER_AVAILABLE,
|
|
SERVER_UNAVAILABLE,
|
|
)
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers import dispatcher
|
|
|
|
from . import SERVER_ID
|
|
|
|
from tests.common import (
|
|
MockConfigEntry,
|
|
async_fire_time_changed,
|
|
load_json_object_fixture,
|
|
)
|
|
|
|
|
|
async def test_syncthing_client_reconnect_on_error(
|
|
hass: HomeAssistant,
|
|
entry: MockConfigEntry,
|
|
mock_syncthing_client: MagicMock,
|
|
freezer: FrozenDateTimeFactory,
|
|
) -> None:
|
|
"""Test SyncthingClient reconnects when server becomes unavailable."""
|
|
call_count = 0
|
|
|
|
async def mock_listen():
|
|
"""Mock listen that raises error first, then succeeds."""
|
|
nonlocal call_count
|
|
call_count += 1
|
|
if call_count == 1:
|
|
raise SyncthingError("Connection lost")
|
|
while True:
|
|
yield await hass.async_add_executor_job(
|
|
load_json_object_fixture, "state_changed_event.json", DOMAIN
|
|
)
|
|
|
|
mock_syncthing_client.events.last_seen_id = 10
|
|
mock_syncthing_client.events.listen = mock_listen
|
|
|
|
server_unavailable_calls = []
|
|
server_available_calls = []
|
|
|
|
async def server_unavailable_handler() -> None:
|
|
"""Handle server unavailable signal."""
|
|
server_unavailable_calls.append(True)
|
|
|
|
async def server_available_handler() -> None:
|
|
"""Handle server available signal."""
|
|
server_available_calls.append(True)
|
|
|
|
dispatcher.async_dispatcher_connect(
|
|
hass,
|
|
f"{SERVER_UNAVAILABLE}-{SERVER_ID}",
|
|
server_unavailable_handler,
|
|
)
|
|
dispatcher.async_dispatcher_connect(
|
|
hass,
|
|
f"{SERVER_AVAILABLE}-{SERVER_ID}",
|
|
server_available_handler,
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.components.syncthing.aiosyncthing.Syncthing",
|
|
autospec=True,
|
|
) as mock_class:
|
|
mock_class.return_value = mock_syncthing_client
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(server_unavailable_calls) >= 1
|
|
assert len(server_available_calls) == 0
|
|
|
|
freezer.tick(RECONNECT_INTERVAL)
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(server_available_calls) >= 1
|
|
|
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"event_fixture",
|
|
[
|
|
"folder_summary_event.json",
|
|
"state_changed_event.json",
|
|
"folder_paused_event.json",
|
|
],
|
|
)
|
|
async def test_client_dispatches_event(
|
|
hass: HomeAssistant,
|
|
entry: MockConfigEntry,
|
|
mock_syncthing_client: MagicMock,
|
|
event_fixture: str,
|
|
) -> None:
|
|
"""Test SyncthingClient dispatches the expected signal for syncthing events."""
|
|
event = await hass.async_add_executor_job(
|
|
load_json_object_fixture, event_fixture, DOMAIN
|
|
)
|
|
|
|
async def mock_listen():
|
|
yield event
|
|
await asyncio.Event().wait()
|
|
|
|
mock_syncthing_client.events.listen = mock_listen
|
|
mock_syncthing_client.events.last_seen_id = 10
|
|
|
|
folder = event["data"].get("folder") or event["data"]["id"]
|
|
signal = f"{EVENTS[event['type']]}-{SERVER_ID}-{folder}"
|
|
|
|
received = asyncio.Event()
|
|
captured: list[dict] = []
|
|
|
|
@callback
|
|
def handler(received_event: dict) -> None:
|
|
captured.append(received_event)
|
|
received.set()
|
|
|
|
dispatcher.async_dispatcher_connect(hass, signal, handler)
|
|
with patch(
|
|
"homeassistant.components.syncthing.aiosyncthing.Syncthing",
|
|
autospec=True,
|
|
) as mock_class:
|
|
mock_class.return_value = mock_syncthing_client
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
|
|
async with asyncio.timeout(5):
|
|
await received.wait()
|
|
|
|
assert captured == [event]
|