mirror of https://github.com/home-assistant/core
183 lines
6.5 KiB
Python
183 lines
6.5 KiB
Python
"""Fixtures for DLNA DMS tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import AsyncGenerator, Generator
|
|
from typing import Final, cast
|
|
from unittest.mock import AsyncMock, MagicMock, Mock, create_autospec, patch, seal
|
|
|
|
from async_upnp_client.client import UpnpDevice, UpnpService
|
|
from async_upnp_client.utils import absolute_url
|
|
import pytest
|
|
|
|
from homeassistant.components.dlna_dms.const import (
|
|
CONF_SOURCE_ID,
|
|
CONFIG_VERSION,
|
|
DOMAIN,
|
|
)
|
|
from homeassistant.components.dlna_dms.dms import DlnaDmsData
|
|
from homeassistant.const import CONF_DEVICE_ID, CONF_URL
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
MOCK_DEVICE_HOST: Final = "192.88.99.21"
|
|
MOCK_DEVICE_BASE_URL: Final = f"http://{MOCK_DEVICE_HOST}"
|
|
MOCK_DEVICE_LOCATION: Final = MOCK_DEVICE_BASE_URL + "/dms_description.xml"
|
|
MOCK_DEVICE_NAME: Final = "Test Server Device"
|
|
MOCK_DEVICE_TYPE: Final = "urn:schemas-upnp-org:device:MediaServer:1"
|
|
MOCK_DEVICE_UDN: Final = "uuid:7bf34520-f034-4fa2-8d2d-2f709d4221ef"
|
|
MOCK_DEVICE_USN: Final = f"{MOCK_DEVICE_UDN}::{MOCK_DEVICE_TYPE}"
|
|
MOCK_SOURCE_ID: Final = "test_server_device"
|
|
|
|
LOCAL_IP: Final = "192.88.99.1"
|
|
EVENT_CALLBACK_URL: Final = "http://192.88.99.1/notify"
|
|
|
|
NEW_DEVICE_LOCATION: Final = "http://192.88.99.7" + "/dmr_description.xml"
|
|
|
|
|
|
@pytest.fixture
|
|
async def setup_media_source(hass: HomeAssistant) -> None:
|
|
"""Set up media source."""
|
|
assert await async_setup_component(hass, "media_source", {})
|
|
|
|
|
|
@pytest.fixture
|
|
def upnp_factory_mock() -> Generator[Mock]:
|
|
"""Mock the UpnpFactory class to construct DMS-style UPnP devices."""
|
|
with patch(
|
|
"homeassistant.components.dlna_dms.dms.UpnpFactory",
|
|
autospec=True,
|
|
spec_set=True,
|
|
) as upnp_factory:
|
|
upnp_device = create_autospec(UpnpDevice, instance=True)
|
|
upnp_device.name = MOCK_DEVICE_NAME
|
|
upnp_device.udn = MOCK_DEVICE_UDN
|
|
upnp_device.device_url = MOCK_DEVICE_LOCATION
|
|
upnp_device.device_type = MOCK_DEVICE_TYPE
|
|
upnp_device.available = True
|
|
upnp_device.parent_device = None
|
|
upnp_device.root_device = upnp_device
|
|
upnp_device.all_devices = [upnp_device]
|
|
upnp_device.services = {
|
|
"urn:schemas-upnp-org:service:ContentDirectory:1": create_autospec(
|
|
UpnpService,
|
|
instance=True,
|
|
service_type="urn:schemas-upnp-org:service:ContentDirectory:1",
|
|
service_id="urn:upnp-org:serviceId:ContentDirectory",
|
|
),
|
|
"urn:schemas-upnp-org:service:ConnectionManager:1": create_autospec(
|
|
UpnpService,
|
|
instance=True,
|
|
service_type="urn:schemas-upnp-org:service:ConnectionManager:1",
|
|
service_id="urn:upnp-org:serviceId:ConnectionManager",
|
|
),
|
|
}
|
|
seal(upnp_device)
|
|
upnp_factory_instance = upnp_factory.return_value
|
|
upnp_factory_instance.async_create_device.return_value = upnp_device
|
|
|
|
yield upnp_factory_instance
|
|
|
|
|
|
@pytest.fixture(autouse=True, scope="module")
|
|
def aiohttp_session_requester_mock() -> Generator[Mock]:
|
|
"""Mock the AiohttpSessionRequester to prevent network use."""
|
|
with patch(
|
|
"homeassistant.components.dlna_dms.dms.AiohttpSessionRequester", autospec=True
|
|
) as requester_mock:
|
|
requester_mock.return_value = mock = AsyncMock()
|
|
mock.async_http_request.return_value.body = MagicMock()
|
|
yield requester_mock
|
|
|
|
|
|
@pytest.fixture
|
|
def config_entry_mock() -> MockConfigEntry:
|
|
"""Mock a config entry for this platform."""
|
|
return MockConfigEntry(
|
|
unique_id=MOCK_DEVICE_USN,
|
|
domain=DOMAIN,
|
|
version=CONFIG_VERSION,
|
|
data={
|
|
CONF_URL: MOCK_DEVICE_LOCATION,
|
|
CONF_DEVICE_ID: MOCK_DEVICE_USN,
|
|
CONF_SOURCE_ID: MOCK_SOURCE_ID,
|
|
},
|
|
title=MOCK_DEVICE_NAME,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def dms_device_mock(upnp_factory_mock: Mock) -> Generator[Mock]:
|
|
"""Mock the async_upnp_client DMS device, initially connected."""
|
|
with patch(
|
|
"homeassistant.components.dlna_dms.dms.DmsDevice", autospec=True
|
|
) as constructor:
|
|
device = constructor.return_value
|
|
device.on_event = None
|
|
device.profile_device = upnp_factory_mock.async_create_device.return_value
|
|
device.icon = MOCK_DEVICE_BASE_URL + "/icon.jpg"
|
|
device.udn = "device_udn"
|
|
device.manufacturer = "device_manufacturer"
|
|
device.model_name = "device_model_name"
|
|
device.name = "device_name"
|
|
device.get_absolute_url.side_effect = lambda url: absolute_url(
|
|
MOCK_DEVICE_BASE_URL, url
|
|
)
|
|
|
|
yield device
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def ssdp_scanner_mock() -> Generator[Mock]:
|
|
"""Mock the SSDP Scanner."""
|
|
with patch("homeassistant.components.ssdp.Scanner", autospec=True) as mock_scanner:
|
|
reg_callback = mock_scanner.return_value.async_register_callback
|
|
reg_callback.return_value = Mock(return_value=None)
|
|
yield mock_scanner.return_value
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def ssdp_server_mock() -> Generator[None]:
|
|
"""Mock the SSDP Server."""
|
|
with patch("homeassistant.components.ssdp.Server", autospec=True):
|
|
yield
|
|
|
|
|
|
@pytest.fixture
|
|
async def device_source_mock(
|
|
hass: HomeAssistant,
|
|
config_entry_mock: MockConfigEntry,
|
|
ssdp_scanner_mock: Mock,
|
|
dms_device_mock: Mock,
|
|
) -> AsyncGenerator[None]:
|
|
"""Fixture to set up a DmsDeviceSource in a connected state and cleanup at completion."""
|
|
config_entry_mock.add_to_hass(hass)
|
|
assert await hass.config_entries.async_setup(config_entry_mock.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
# Check the DmsDeviceSource has registered all needed listeners
|
|
assert len(config_entry_mock.update_listeners) == 0
|
|
assert ssdp_scanner_mock.async_register_callback.await_count == 2
|
|
assert ssdp_scanner_mock.async_register_callback.return_value.call_count == 0
|
|
|
|
# Run the test
|
|
yield None
|
|
|
|
# Unload config entry to clean up
|
|
assert await hass.config_entries.async_remove(config_entry_mock.entry_id) == {
|
|
"require_restart": False
|
|
}
|
|
|
|
# Check DmsDeviceSource has cleaned up its resources
|
|
assert not config_entry_mock.update_listeners
|
|
assert (
|
|
ssdp_scanner_mock.async_register_callback.await_count
|
|
== ssdp_scanner_mock.async_register_callback.return_value.call_count
|
|
)
|
|
|
|
domain_data = cast(DlnaDmsData, hass.data[DOMAIN])
|
|
assert MOCK_DEVICE_USN not in domain_data.devices
|
|
assert MOCK_SOURCE_ID not in domain_data.sources
|