mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Add config entry to go2rtc (#129436)
* Add config entry to go2rtc * Address review comments * Remove config entry if go2rtc is not configured * Allow importing default_config * Address review comment
This commit is contained in:
parent
24829bc44f
commit
db81edfb2b
@ -3,7 +3,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError
|
||||||
from go2rtc_client import Go2RtcRestClient
|
from go2rtc_client import Go2RtcRestClient
|
||||||
|
from go2rtc_client.exceptions import Go2RtcClientError
|
||||||
from go2rtc_client.ws import (
|
from go2rtc_client.ws import (
|
||||||
Go2RtcWsClient,
|
Go2RtcWsClient,
|
||||||
ReceiveMessages,
|
ReceiveMessages,
|
||||||
@ -24,11 +26,15 @@ from homeassistant.components.camera import (
|
|||||||
WebRTCSendMessage,
|
WebRTCSendMessage,
|
||||||
async_register_webrtc_provider,
|
async_register_webrtc_provider,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.default_config import DOMAIN as DEFAULT_CONFIG_DOMAIN
|
||||||
|
from homeassistant.config_entries import SOURCE_SYSTEM, ConfigEntry
|
||||||
from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import Event, HomeAssistant, callback
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
from homeassistant.helpers import config_validation as cv, discovery_flow
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
from homeassistant.util.hass_dict import HassKey
|
||||||
from homeassistant.util.package import is_docker_env
|
from homeassistant.util.package import is_docker_env
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
@ -72,15 +78,24 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
extra=vol.ALLOW_EXTRA,
|
extra=vol.ALLOW_EXTRA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_DATA_GO2RTC: HassKey[str] = HassKey(DOMAIN)
|
||||||
|
_RETRYABLE_ERRORS = (ClientConnectionError, ServerConnectionError)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up WebRTC."""
|
"""Set up WebRTC."""
|
||||||
url: str | None = None
|
url: str | None = None
|
||||||
|
if DOMAIN not in config and DEFAULT_CONFIG_DOMAIN not in config:
|
||||||
|
await _remove_go2rtc_entries(hass)
|
||||||
|
return True
|
||||||
|
|
||||||
if not (configured_by_user := DOMAIN in config) or not (
|
if not (configured_by_user := DOMAIN in config) or not (
|
||||||
url := config[DOMAIN].get(CONF_URL)
|
url := config[DOMAIN].get(CONF_URL)
|
||||||
):
|
):
|
||||||
if not is_docker_env():
|
if not is_docker_env():
|
||||||
if not configured_by_user:
|
if not configured_by_user:
|
||||||
|
# Remove config entry if it exists
|
||||||
|
await _remove_go2rtc_entries(hass)
|
||||||
return True
|
return True
|
||||||
_LOGGER.warning("Go2rtc URL required in non-docker installs")
|
_LOGGER.warning("Go2rtc URL required in non-docker installs")
|
||||||
return False
|
return False
|
||||||
@ -99,12 +114,36 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
|
|
||||||
url = "http://localhost:1984/"
|
url = "http://localhost:1984/"
|
||||||
|
|
||||||
|
hass.data[_DATA_GO2RTC] = url
|
||||||
|
discovery_flow.async_create_flow(
|
||||||
|
hass, DOMAIN, context={"source": SOURCE_SYSTEM}, data={}
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def _remove_go2rtc_entries(hass: HomeAssistant) -> None:
|
||||||
|
"""Remove go2rtc config entries, if any."""
|
||||||
|
for entry in hass.config_entries.async_entries(DOMAIN):
|
||||||
|
await hass.config_entries.async_remove(entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Set up go2rtc from a config entry."""
|
||||||
|
url = hass.data[_DATA_GO2RTC]
|
||||||
|
|
||||||
# Validate the server URL
|
# Validate the server URL
|
||||||
try:
|
try:
|
||||||
client = Go2RtcRestClient(async_get_clientsession(hass), url)
|
client = Go2RtcRestClient(async_get_clientsession(hass), url)
|
||||||
await client.streams.list()
|
await client.streams.list()
|
||||||
except Exception: # noqa: BLE001
|
except Go2RtcClientError as err:
|
||||||
_LOGGER.warning("Could not connect to go2rtc instance on %s", url)
|
if isinstance(err.__cause__, _RETRYABLE_ERRORS):
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not connect to go2rtc instance on {url}"
|
||||||
|
) from err
|
||||||
|
_LOGGER.warning("Could not connect to go2rtc instance on %s (%s)", url, err)
|
||||||
|
return False
|
||||||
|
except Exception as err: # noqa: BLE001
|
||||||
|
_LOGGER.warning("Could not connect to go2rtc instance on %s (%s)", url, err)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
provider = WebRTCProvider(hass, url)
|
provider = WebRTCProvider(hass, url)
|
||||||
@ -112,6 +151,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Unload a go2rtc config entry."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _get_binary(hass: HomeAssistant) -> str | None:
|
async def _get_binary(hass: HomeAssistant) -> str | None:
|
||||||
"""Return the binary path if found."""
|
"""Return the binary path if found."""
|
||||||
return await hass.async_add_executor_job(shutil.which, "go2rtc")
|
return await hass.async_add_executor_job(shutil.which, "go2rtc")
|
||||||
|
21
homeassistant/components/go2rtc/config_flow.py
Normal file
21
homeassistant/components/go2rtc/config_flow.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
"""Config flow for the go2rtc integration."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
class CloudConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow for the go2rtc integration."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
async def async_step_system(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> ConfigFlowResult:
|
||||||
|
"""Handle the system step."""
|
||||||
|
return self.async_create_entry(title="go2rtc", data={})
|
@ -7,5 +7,6 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/go2rtc",
|
"documentation": "https://www.home-assistant.io/integrations/go2rtc",
|
||||||
"integration_type": "system",
|
"integration_type": "system",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["go2rtc-client==0.0.1b3"]
|
"requirements": ["go2rtc-client==0.0.1b3"],
|
||||||
|
"single_config_entry": true
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,7 @@ ALLOWED_USED_COMPONENTS = {
|
|||||||
"alert",
|
"alert",
|
||||||
"automation",
|
"automation",
|
||||||
"conversation",
|
"conversation",
|
||||||
|
"default_config",
|
||||||
"device_automation",
|
"device_automation",
|
||||||
"frontend",
|
"frontend",
|
||||||
"group",
|
"group",
|
||||||
|
45
tests/components/go2rtc/test_config_flow.py
Normal file
45
tests/components/go2rtc/test_config_flow.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""Test the Home Assistant Cloud config flow."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from homeassistant.components.go2rtc.const import DOMAIN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_flow(hass: HomeAssistant) -> None:
|
||||||
|
"""Test create cloud entry."""
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.go2rtc.async_setup", return_value=True
|
||||||
|
) as mock_setup,
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.go2rtc.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry,
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": "system"}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
assert result["title"] == "go2rtc"
|
||||||
|
assert result["data"] == {}
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(mock_setup.mock_calls) == 1
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_multiple_entries(hass: HomeAssistant) -> None:
|
||||||
|
"""Test creating multiple cloud entries."""
|
||||||
|
config_entry = MockConfigEntry(domain=DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": "system"}
|
||||||
|
)
|
||||||
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
assert result["reason"] == "single_instance_allowed"
|
@ -5,7 +5,9 @@ import logging
|
|||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
from unittest.mock import AsyncMock, Mock, patch
|
from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
|
from aiohttp.client_exceptions import ClientConnectionError, ServerConnectionError
|
||||||
from go2rtc_client import Stream
|
from go2rtc_client import Stream
|
||||||
|
from go2rtc_client.exceptions import Go2RtcClientError
|
||||||
from go2rtc_client.models import Producer
|
from go2rtc_client.models import Producer
|
||||||
from go2rtc_client.ws import (
|
from go2rtc_client.ws import (
|
||||||
ReceiveMessages,
|
ReceiveMessages,
|
||||||
@ -27,9 +29,10 @@ from homeassistant.components.camera import (
|
|||||||
WebRTCMessage,
|
WebRTCMessage,
|
||||||
WebRTCSendMessage,
|
WebRTCSendMessage,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.default_config import DOMAIN as DEFAULT_CONFIG_DOMAIN
|
||||||
from homeassistant.components.go2rtc import WebRTCProvider
|
from homeassistant.components.go2rtc import WebRTCProvider
|
||||||
from homeassistant.components.go2rtc.const import DOMAIN
|
from homeassistant.components.go2rtc.const import DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow
|
from homeassistant.config_entries import ConfigEntry, ConfigEntryState, ConfigFlow
|
||||||
from homeassistant.const import CONF_URL
|
from homeassistant.const import CONF_URL
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
@ -100,6 +103,21 @@ def mock_get_binary(go2rtc_binary) -> Generator[Mock]:
|
|||||||
yield mock_which
|
yield mock_which
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="has_go2rtc_entry")
|
||||||
|
def has_go2rtc_entry_fixture() -> bool:
|
||||||
|
"""Fixture to control if a go2rtc config entry should be created."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_go2rtc_entry(hass: HomeAssistant, has_go2rtc_entry: bool) -> None:
|
||||||
|
"""Mock a go2rtc onfig entry."""
|
||||||
|
if not has_go2rtc_entry:
|
||||||
|
return
|
||||||
|
config_entry = MockConfigEntry(domain=DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="is_docker_env")
|
@pytest.fixture(name="is_docker_env")
|
||||||
def is_docker_env_fixture() -> bool:
|
def is_docker_env_fixture() -> bool:
|
||||||
"""Fixture to provide is_docker_env return value."""
|
"""Fixture to provide is_docker_env return value."""
|
||||||
@ -187,7 +205,10 @@ async def _test_setup_and_signaling(
|
|||||||
assert camera.frontend_stream_type == StreamType.HLS
|
assert camera.frontend_stream_type == StreamType.HLS
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN, config)
|
assert await async_setup_component(hass, DOMAIN, config)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
config_entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
|
assert len(config_entries) == 1
|
||||||
|
assert config_entries[0].state == ConfigEntryState.LOADED
|
||||||
after_setup_fn()
|
after_setup_fn()
|
||||||
|
|
||||||
receive_message_callback = Mock(spec_set=WebRTCSendMessage)
|
receive_message_callback = Mock(spec_set=WebRTCSendMessage)
|
||||||
@ -239,8 +260,13 @@ async def _test_setup_and_signaling(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures(
|
@pytest.mark.usefixtures(
|
||||||
"init_test_integration", "mock_get_binary", "mock_is_docker_env"
|
"init_test_integration",
|
||||||
|
"mock_get_binary",
|
||||||
|
"mock_is_docker_env",
|
||||||
|
"mock_go2rtc_entry",
|
||||||
)
|
)
|
||||||
|
@pytest.mark.parametrize("config", [{DOMAIN: {}}, {DEFAULT_CONFIG_DOMAIN: {}}])
|
||||||
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
async def test_setup_go_binary(
|
async def test_setup_go_binary(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
rest_client: AsyncMock,
|
rest_client: AsyncMock,
|
||||||
@ -249,21 +275,25 @@ async def test_setup_go_binary(
|
|||||||
server_start: Mock,
|
server_start: Mock,
|
||||||
server_stop: Mock,
|
server_stop: Mock,
|
||||||
init_test_integration: MockCamera,
|
init_test_integration: MockCamera,
|
||||||
|
has_go2rtc_entry: bool,
|
||||||
|
config: ConfigType,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the go2rtc config entry with binary."""
|
"""Test the go2rtc config entry with binary."""
|
||||||
|
assert (len(hass.config_entries.async_entries(DOMAIN)) == 1) == has_go2rtc_entry
|
||||||
|
|
||||||
def after_setup() -> None:
|
def after_setup() -> None:
|
||||||
server.assert_called_once_with(hass, "/usr/bin/go2rtc")
|
server.assert_called_once_with(hass, "/usr/bin/go2rtc")
|
||||||
server_start.assert_called_once()
|
server_start.assert_called_once()
|
||||||
|
|
||||||
await _test_setup_and_signaling(
|
await _test_setup_and_signaling(
|
||||||
hass, rest_client, ws_client, {DOMAIN: {}}, after_setup, init_test_integration
|
hass, rest_client, ws_client, config, after_setup, init_test_integration
|
||||||
)
|
)
|
||||||
|
|
||||||
await hass.async_stop()
|
await hass.async_stop()
|
||||||
server_stop.assert_called_once()
|
server_stop.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_go2rtc_entry")
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("go2rtc_binary", "is_docker_env"),
|
("go2rtc_binary", "is_docker_env"),
|
||||||
[
|
[
|
||||||
@ -271,6 +301,7 @@ async def test_setup_go_binary(
|
|||||||
(None, False),
|
(None, False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
async def test_setup_go(
|
async def test_setup_go(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
rest_client: AsyncMock,
|
rest_client: AsyncMock,
|
||||||
@ -279,8 +310,11 @@ async def test_setup_go(
|
|||||||
init_test_integration: MockCamera,
|
init_test_integration: MockCamera,
|
||||||
mock_get_binary: Mock,
|
mock_get_binary: Mock,
|
||||||
mock_is_docker_env: Mock,
|
mock_is_docker_env: Mock,
|
||||||
|
has_go2rtc_entry: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test the go2rtc config entry without binary."""
|
"""Test the go2rtc config entry without binary."""
|
||||||
|
assert (len(hass.config_entries.async_entries(DOMAIN)) == 1) == has_go2rtc_entry
|
||||||
|
|
||||||
config = {DOMAIN: {CONF_URL: "http://localhost:1984/"}}
|
config = {DOMAIN: {CONF_URL: "http://localhost:1984/"}}
|
||||||
|
|
||||||
def after_setup() -> None:
|
def after_setup() -> None:
|
||||||
@ -431,6 +465,9 @@ async def test_close_session(
|
|||||||
|
|
||||||
ERR_BINARY_NOT_FOUND = "Could not find go2rtc docker binary"
|
ERR_BINARY_NOT_FOUND = "Could not find go2rtc docker binary"
|
||||||
ERR_CONNECT = "Could not connect to go2rtc instance"
|
ERR_CONNECT = "Could not connect to go2rtc instance"
|
||||||
|
ERR_CONNECT_RETRY = (
|
||||||
|
"Could not connect to go2rtc instance on http://localhost:1984/; Retrying"
|
||||||
|
)
|
||||||
ERR_INVALID_URL = "Invalid config for 'go2rtc': invalid url"
|
ERR_INVALID_URL = "Invalid config for 'go2rtc': invalid url"
|
||||||
ERR_URL_REQUIRED = "Go2rtc URL required in non-docker installs"
|
ERR_URL_REQUIRED = "Go2rtc URL required in non-docker installs"
|
||||||
|
|
||||||
@ -441,7 +478,10 @@ ERR_URL_REQUIRED = "Go2rtc URL required in non-docker installs"
|
|||||||
({}, None, False),
|
({}, None, False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("mock_get_binary", "mock_is_docker_env", "server")
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
|
@pytest.mark.usefixtures(
|
||||||
|
"mock_get_binary", "mock_go2rtc_entry", "mock_is_docker_env", "server"
|
||||||
|
)
|
||||||
async def test_non_user_setup_with_error(
|
async def test_non_user_setup_with_error(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
@ -450,28 +490,105 @@ async def test_non_user_setup_with_error(
|
|||||||
"""Test setup integration does not fail if not setup by user."""
|
"""Test setup integration does not fail if not setup by user."""
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN, config)
|
assert await async_setup_component(hass, DOMAIN, config)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
assert not hass.config_entries.async_entries(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("config", "go2rtc_binary", "is_docker_env", "expected_log_message"),
|
("config", "go2rtc_binary", "is_docker_env", "expected_log_message"),
|
||||||
[
|
[
|
||||||
({}, None, True, ERR_BINARY_NOT_FOUND),
|
({DEFAULT_CONFIG_DOMAIN: {}}, None, True, ERR_BINARY_NOT_FOUND),
|
||||||
({}, "/usr/bin/go2rtc", True, ERR_CONNECT),
|
|
||||||
({DOMAIN: {}}, None, False, ERR_URL_REQUIRED),
|
({DOMAIN: {}}, None, False, ERR_URL_REQUIRED),
|
||||||
({DOMAIN: {}}, None, True, ERR_BINARY_NOT_FOUND),
|
({DOMAIN: {}}, None, True, ERR_BINARY_NOT_FOUND),
|
||||||
({DOMAIN: {}}, "/usr/bin/go2rtc", True, ERR_CONNECT),
|
|
||||||
({DOMAIN: {CONF_URL: "invalid"}}, None, True, ERR_INVALID_URL),
|
({DOMAIN: {CONF_URL: "invalid"}}, None, True, ERR_INVALID_URL),
|
||||||
({DOMAIN: {CONF_URL: "http://localhost:1984/"}}, None, True, ERR_CONNECT),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("mock_get_binary", "mock_is_docker_env", "server")
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
async def test_setup_with_error(
|
@pytest.mark.usefixtures(
|
||||||
|
"mock_get_binary", "mock_go2rtc_entry", "mock_is_docker_env", "server"
|
||||||
|
)
|
||||||
|
async def test_setup_with_setup_error(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
has_go2rtc_entry: bool,
|
||||||
expected_log_message: str,
|
expected_log_message: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test setup integration fails."""
|
"""Test setup integration fails."""
|
||||||
|
|
||||||
assert not await async_setup_component(hass, DOMAIN, config)
|
assert not await async_setup_component(hass, DOMAIN, config)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
assert bool(hass.config_entries.async_entries(DOMAIN)) == has_go2rtc_entry
|
||||||
assert expected_log_message in caplog.text
|
assert expected_log_message in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("config", "go2rtc_binary", "is_docker_env", "expected_log_message"),
|
||||||
|
[
|
||||||
|
({DEFAULT_CONFIG_DOMAIN: {}}, "/usr/bin/go2rtc", True, ERR_CONNECT),
|
||||||
|
({DOMAIN: {}}, "/usr/bin/go2rtc", True, ERR_CONNECT),
|
||||||
|
({DOMAIN: {CONF_URL: "http://localhost:1984/"}}, None, True, ERR_CONNECT),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
|
@pytest.mark.usefixtures(
|
||||||
|
"mock_get_binary", "mock_go2rtc_entry", "mock_is_docker_env", "server"
|
||||||
|
)
|
||||||
|
async def test_setup_with_setup_entry_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
expected_log_message: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test setup integration entry fails."""
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, DOMAIN, config)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
config_entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
|
assert len(config_entries) == 1
|
||||||
|
assert config_entries[0].state == ConfigEntryState.SETUP_ERROR
|
||||||
|
assert expected_log_message in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("config", [{DOMAIN: {}}, {DEFAULT_CONFIG_DOMAIN: {}}])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("cause", "expected_config_entry_state", "expected_log_message"),
|
||||||
|
[
|
||||||
|
(ClientConnectionError(), ConfigEntryState.SETUP_RETRY, ERR_CONNECT_RETRY),
|
||||||
|
(ServerConnectionError(), ConfigEntryState.SETUP_RETRY, ERR_CONNECT_RETRY),
|
||||||
|
(None, ConfigEntryState.SETUP_ERROR, ERR_CONNECT),
|
||||||
|
(Exception(), ConfigEntryState.SETUP_ERROR, ERR_CONNECT),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize("has_go2rtc_entry", [True, False])
|
||||||
|
@pytest.mark.usefixtures(
|
||||||
|
"mock_get_binary", "mock_go2rtc_entry", "mock_is_docker_env", "server"
|
||||||
|
)
|
||||||
|
async def test_setup_with_retryable_setup_entry_error(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
rest_client: AsyncMock,
|
||||||
|
config: ConfigType,
|
||||||
|
cause: Exception,
|
||||||
|
expected_config_entry_state: ConfigEntryState,
|
||||||
|
expected_log_message: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test setup integration entry fails."""
|
||||||
|
go2rtc_error = Go2RtcClientError()
|
||||||
|
go2rtc_error.__cause__ = cause
|
||||||
|
rest_client.streams.list.side_effect = go2rtc_error
|
||||||
|
assert await async_setup_component(hass, DOMAIN, config)
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
config_entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
|
assert len(config_entries) == 1
|
||||||
|
assert config_entries[0].state == expected_config_entry_state
|
||||||
|
assert expected_log_message in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_entry_remove(hass: HomeAssistant) -> None:
|
||||||
|
"""Test config entry removed when neither default_config nor go2rtc is in config."""
|
||||||
|
config_entry = MockConfigEntry(domain=DOMAIN)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||||
|
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user