124 lines
3.7 KiB
Python
124 lines
3.7 KiB
Python
"""Test fixtures for mqtt component."""
|
|
|
|
import asyncio
|
|
from collections.abc import AsyncGenerator, Generator
|
|
from random import getrandbits
|
|
from typing import Any
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from homeassistant.components import mqtt
|
|
from homeassistant.components.mqtt.models import MessageCallbackType, ReceiveMessage
|
|
from homeassistant.components.mqtt.util import EnsureJobAfterCooldown
|
|
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
|
from homeassistant.core import HomeAssistant, callback
|
|
|
|
from tests.common import MockConfigEntry
|
|
from tests.typing import MqttMockPahoClient
|
|
|
|
ENTRY_DEFAULT_BIRTH_MESSAGE = {
|
|
mqtt.CONF_BROKER: "mock-broker",
|
|
mqtt.CONF_BIRTH_MESSAGE: {
|
|
mqtt.ATTR_TOPIC: "homeassistant/status",
|
|
mqtt.ATTR_PAYLOAD: "online",
|
|
mqtt.ATTR_QOS: 0,
|
|
mqtt.ATTR_RETAIN: False,
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def patch_hass_config(mock_hass_config: None) -> None:
|
|
"""Patch configuration.yaml."""
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_dir_prefix() -> str:
|
|
"""Set an alternate temp dir prefix."""
|
|
return "test"
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_temp_dir(temp_dir_prefix: str) -> Generator[str]:
|
|
"""Mock the certificate temp directory."""
|
|
with patch(
|
|
# Patch temp dir name to avoid tests fail running in parallel
|
|
"homeassistant.components.mqtt.util.TEMP_DIR_NAME",
|
|
f"home-assistant-mqtt-{temp_dir_prefix}-{getrandbits(10):03x}",
|
|
) as mocked_temp_dir:
|
|
yield mocked_temp_dir
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_debouncer(hass: HomeAssistant) -> Generator[asyncio.Event]:
|
|
"""Mock EnsureJobAfterCooldown.
|
|
|
|
Returns an asyncio.Event that allows to await the debouncer task to be finished.
|
|
"""
|
|
task_done = asyncio.Event()
|
|
|
|
class MockDeboncer(EnsureJobAfterCooldown):
|
|
"""Mock the MQTT client (un)subscribe debouncer."""
|
|
|
|
async def _async_job(self) -> None:
|
|
"""Execute after a cooldown period."""
|
|
await super()._async_job()
|
|
task_done.set()
|
|
|
|
# We mock the import of EnsureJobAfterCooldown in client.py
|
|
with patch(
|
|
"homeassistant.components.mqtt.client.EnsureJobAfterCooldown", MockDeboncer
|
|
):
|
|
yield task_done
|
|
|
|
|
|
@pytest.fixture
|
|
async def setup_with_birth_msg_client_mock(
|
|
hass: HomeAssistant,
|
|
mqtt_config_entry_data: dict[str, Any] | None,
|
|
mqtt_client_mock: MqttMockPahoClient,
|
|
) -> AsyncGenerator[MqttMockPahoClient]:
|
|
"""Test sending birth message."""
|
|
birth = asyncio.Event()
|
|
with (
|
|
patch("homeassistant.components.mqtt.client.INITIAL_SUBSCRIBE_COOLDOWN", 0.0),
|
|
patch("homeassistant.components.mqtt.client.DISCOVERY_COOLDOWN", 0.0),
|
|
patch("homeassistant.components.mqtt.client.SUBSCRIBE_COOLDOWN", 0.0),
|
|
):
|
|
entry = MockConfigEntry(
|
|
domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}
|
|
)
|
|
entry.add_to_hass(hass)
|
|
hass.config.components.add(mqtt.DOMAIN)
|
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
|
|
|
|
@callback
|
|
def wait_birth(msg: ReceiveMessage) -> None:
|
|
"""Handle birth message."""
|
|
birth.set()
|
|
|
|
await mqtt.async_subscribe(hass, "homeassistant/status", wait_birth)
|
|
await hass.async_block_till_done()
|
|
await birth.wait()
|
|
yield mqtt_client_mock
|
|
|
|
|
|
@pytest.fixture
|
|
def recorded_calls() -> list[ReceiveMessage]:
|
|
"""Fixture to hold recorded calls."""
|
|
return []
|
|
|
|
|
|
@pytest.fixture
|
|
def record_calls(recorded_calls: list[ReceiveMessage]) -> MessageCallbackType:
|
|
"""Fixture to record calls."""
|
|
|
|
@callback
|
|
def record_calls(msg: ReceiveMessage) -> None:
|
|
"""Record calls."""
|
|
recorded_calls.append(msg)
|
|
|
|
return record_calls
|