Skip to content

Commit

Permalink
Parametrize test, make mocked start_listening block
Browse files Browse the repository at this point in the history
  • Loading branch information
emontnemery committed Nov 11, 2024
1 parent 00f7075 commit 564f4d1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 44 deletions.
8 changes: 8 additions & 0 deletions tests/components/husqvarna_automower/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Test helpers for Husqvarna Automower."""

import asyncio
from collections.abc import Generator
import time
from unittest.mock import AsyncMock, patch
Expand Down Expand Up @@ -101,10 +102,17 @@ async def setup_credentials(hass: HomeAssistant) -> None:
def mock_automower_client(values) -> Generator[AsyncMock]:
"""Mock a Husqvarna Automower client."""

async def listen() -> None:
"""Mock listen."""
listen_block = asyncio.Event()
await listen_block.wait()
pytest.fail("Listen was not cancelled!")

mock = AsyncMock(spec=AutomowerSession)
mock.auth = AsyncMock(side_effect=ClientWebSocketResponse)
mock.commands = AsyncMock(spec_set=_MowerCommands)
mock.get_status.return_value = values
mock.start_listening = AsyncMock(side_effect=listen)

with patch(
"homeassistant.components.husqvarna_automower.AutomowerSession",
Expand Down
83 changes: 39 additions & 44 deletions tests/components/husqvarna_automower/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,80 +132,75 @@ async def test_update_failed(
@patch(
"homeassistant.components.husqvarna_automower.coordinator.DEFAULT_RECONNECT_TIME", 0
)
@pytest.mark.parametrize(
("method_path", "exception", "error_msg"),
[
(
["auth", "websocket_connect"],
HusqvarnaWSServerHandshakeError,
"Failed to connect to websocket.",
),
(
["start_listening"],
TimeoutException,
"Failed to listen to websocket.",
),
],
)
async def test_websocket_not_available(
hass: HomeAssistant,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
caplog: pytest.LogCaptureFixture,
freezer: FrozenDateTimeFactory,
method_path: list[str],
exception: type[Exception],
error_msg: str,
) -> None:
"""Test trying to reload the websocket."""
calls = []
mock_called = Event()
mock_stall = Event()
mock_side_effect: Exception | None = None

async def mock_function():
nonlocal mock_side_effect
mock_stall.clear()
mock_called.set()
await mock_stall.wait()
if side_effect := mock_side_effect:
mock_side_effect = None
raise side_effect

mock_automower_client.auth.websocket_connect.side_effect = mock_function

# Simulate a WebSocket handshake error
mock_side_effect = HusqvarnaWSServerHandshakeError("Boom")

# Setup integration and verify initial log error message
# Raise the first time the method is awaited
if not calls:
calls.append(None)
raise exception("Boom")
if mock_side_effect:
await mock_side_effect()

# Find the method to mock
mock = mock_automower_client
for itm in method_path:
mock = getattr(mock, itm)
mock_side_effect = mock.side_effect
mock.side_effect = mock_function

# Setup integration and verify log error message
await setup_integration(hass, mock_config_entry)
await mock_called.wait()
mock_called.clear()
assert mock_automower_client.auth.websocket_connect.call_count == 1
assert mock_automower_client.start_listening.call_count == 0
# Allow the exception to be raised
mock_stall.set()
assert mock.call_count == 1
await hass.async_block_till_done()
assert "Failed to connect to websocket. Trying to reconnect: Boom" in caplog.text
assert f"{error_msg} Trying to reconnect: Boom" in caplog.text

# Simulate a successful connection
caplog.clear()
await mock_called.wait()
mock_called.clear()
# Prepare for next subtest
mock_automower_client.auth.websocket_connect.side_effect = None
mock_automower_client.start_listening.side_effect = mock_function
# Check outcome
await hass.async_block_till_done()
assert mock_automower_client.auth.websocket_connect.call_count == 2
assert mock_automower_client.start_listening.call_count == 0
assert mock.call_count == 2
assert "Trying to reconnect: Boom" not in caplog.text
mock_stall.set()

# Simulate a start_listening TimeoutException
await mock_called.wait()
mock_called.clear()
mock_side_effect = TimeoutException("Boom")
assert mock_automower_client.auth.websocket_connect.call_count == 2
assert mock_automower_client.start_listening.call_count == 1
mock_stall.set()
await hass.async_block_till_done()
assert "Failed to listen to websocket. Trying to reconnect: Boom" in caplog.text

# Simulate a successful connection
caplog.clear()
await mock_called.wait()
mock_called.clear()
assert mock_automower_client.auth.websocket_connect.call_count == 3
assert mock_automower_client.start_listening.call_count == 2
mock_stall.set()
await hass.async_block_till_done()
assert "Trying to reconnect: Boom" not in caplog.text

# Simulate hass shutting down
await hass.async_stop()
assert mock_automower_client.auth.websocket_connect.call_count == 3
assert mock_automower_client.start_listening.call_count == 2
assert mock.call_count == 2


async def test_device_info(
Expand Down

0 comments on commit 564f4d1

Please sign in to comment.