"""Tests for the Roku component.""" import re from socket import gaierror as SocketGIAError from homeassistant.components.roku.const import DOMAIN from homeassistant.components.ssdp import ( ATTR_SSDP_LOCATION, ATTR_UPNP_FRIENDLY_NAME, ATTR_UPNP_SERIAL, ) from homeassistant.const import CONF_HOST, CONF_ID, CONF_NAME from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry, load_fixture from tests.test_util.aiohttp import AiohttpClientMocker NAME = "Roku 3" NAME_ROKUTV = '58" Onn Roku TV' HOST = "192.168.1.160" SSDP_LOCATION = "http://192.168.1.160/" UPNP_FRIENDLY_NAME = "My Roku 3" UPNP_SERIAL = "1GU48T017973" MOCK_SSDP_DISCOVERY_INFO = { ATTR_SSDP_LOCATION: SSDP_LOCATION, ATTR_UPNP_FRIENDLY_NAME: UPNP_FRIENDLY_NAME, ATTR_UPNP_SERIAL: UPNP_SERIAL, } HOMEKIT_HOST = "192.168.1.161" MOCK_HOMEKIT_DISCOVERY_INFO = { CONF_NAME: "onn._hap._tcp.local.", CONF_HOST: HOMEKIT_HOST, "properties": { CONF_ID: "2d:97:da:ee:dc:99", }, } def mock_connection( aioclient_mock: AiohttpClientMocker, device: str = "roku3", app: str = "roku", host: str = HOST, power: bool = True, media_state: str = "close", error: bool = False, server_error: bool = False, ) -> None: """Mock the Roku connection.""" roku_url = f"http://{host}:8060" if error: mock_connection_error( aioclient_mock=aioclient_mock, device=device, app=app, host=host ) return if server_error: mock_connection_server_error( aioclient_mock=aioclient_mock, device=device, app=app, host=host ) return info_fixture = f"roku/{device}-device-info.xml" if not power: info_fixture = f"roku/{device}-device-info-power-off.xml" aioclient_mock.get( f"{roku_url}/query/device-info", text=load_fixture(info_fixture), headers={"Content-Type": "text/xml"}, ) apps_fixture = "roku/apps.xml" if device == "rokutv": apps_fixture = "roku/apps-tv.xml" aioclient_mock.get( f"{roku_url}/query/apps", text=load_fixture(apps_fixture), headers={"Content-Type": "text/xml"}, ) aioclient_mock.get( f"{roku_url}/query/active-app", text=load_fixture(f"roku/active-app-{app}.xml"), headers={"Content-Type": "text/xml"}, ) aioclient_mock.get( f"{roku_url}/query/tv-active-channel", text=load_fixture("roku/rokutv-tv-active-channel.xml"), headers={"Content-Type": "text/xml"}, ) aioclient_mock.get( f"{roku_url}/query/tv-channels", text=load_fixture("roku/rokutv-tv-channels.xml"), headers={"Content-Type": "text/xml"}, ) aioclient_mock.get( f"{roku_url}/query/media-player", text=load_fixture(f"roku/media-player-{media_state}.xml"), headers={"Content-Type": "text/xml"}, ) aioclient_mock.post( re.compile(f"{roku_url}/keypress/.*"), text="OK", ) aioclient_mock.post( re.compile(f"{roku_url}/launch/.*"), text="OK", ) aioclient_mock.post(f"{roku_url}/search", text="OK") def mock_connection_error( aioclient_mock: AiohttpClientMocker, device: str = "roku3", app: str = "roku", host: str = HOST, ) -> None: """Mock the Roku connection error.""" roku_url = f"http://{host}:8060" aioclient_mock.get(f"{roku_url}/query/device-info", exc=SocketGIAError) aioclient_mock.get(f"{roku_url}/query/apps", exc=SocketGIAError) aioclient_mock.get(f"{roku_url}/query/active-app", exc=SocketGIAError) aioclient_mock.get(f"{roku_url}/query/tv-active-channel", exc=SocketGIAError) aioclient_mock.get(f"{roku_url}/query/tv-channels", exc=SocketGIAError) aioclient_mock.post(re.compile(f"{roku_url}/keypress/.*"), exc=SocketGIAError) aioclient_mock.post(re.compile(f"{roku_url}/launch/.*"), exc=SocketGIAError) aioclient_mock.post(f"{roku_url}/search", exc=SocketGIAError) def mock_connection_server_error( aioclient_mock: AiohttpClientMocker, device: str = "roku3", app: str = "roku", host: str = HOST, ) -> None: """Mock the Roku server error.""" roku_url = f"http://{host}:8060" aioclient_mock.get(f"{roku_url}/query/device-info", status=500) aioclient_mock.get(f"{roku_url}/query/apps", status=500) aioclient_mock.get(f"{roku_url}/query/active-app", status=500) aioclient_mock.get(f"{roku_url}/query/tv-active-channel", status=500) aioclient_mock.get(f"{roku_url}/query/tv-channels", status=500) aioclient_mock.post(re.compile(f"{roku_url}/keypress/.*"), status=500) aioclient_mock.post(re.compile(f"{roku_url}/launch/.*"), status=500) aioclient_mock.post(f"{roku_url}/search", status=500) async def setup_integration( hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, device: str = "roku3", app: str = "roku", host: str = HOST, unique_id: str = UPNP_SERIAL, error: bool = False, power: bool = True, media_state: str = "close", server_error: bool = False, skip_entry_setup: bool = False, ) -> MockConfigEntry: """Set up the Roku integration in Home Assistant.""" entry = MockConfigEntry(domain=DOMAIN, unique_id=unique_id, data={CONF_HOST: host}) entry.add_to_hass(hass) if not skip_entry_setup: mock_connection( aioclient_mock, device, app=app, host=host, error=error, power=power, media_state=media_state, server_error=server_error, ) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() return entry