core/tests/components/mqtt/conftest.py

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