mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Refactor sonarr tests (#64886)
This commit is contained in:
parent
0f88790303
commit
70da08499a
@ -1,244 +1,13 @@
|
||||
"""Tests for the Sonarr component."""
|
||||
from http import HTTPStatus
|
||||
from socket import gaierror as SocketGIAError
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.sonarr.const import (
|
||||
CONF_BASE_PATH,
|
||||
CONF_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS,
|
||||
DEFAULT_UPCOMING_DAYS,
|
||||
DEFAULT_WANTED_MAX_ITEMS,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_VERIFY_SSL,
|
||||
CONTENT_TYPE_JSON,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
HOST = "192.168.1.189"
|
||||
PORT = 8989
|
||||
BASE_PATH = "/api"
|
||||
API_KEY = "MOCK_API_KEY"
|
||||
from homeassistant.components.sonarr.const import CONF_BASE_PATH
|
||||
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT, CONF_SSL
|
||||
|
||||
MOCK_REAUTH_INPUT = {CONF_API_KEY: "test-api-key-reauth"}
|
||||
|
||||
MOCK_USER_INPUT = {
|
||||
CONF_HOST: HOST,
|
||||
CONF_PORT: PORT,
|
||||
CONF_BASE_PATH: BASE_PATH,
|
||||
CONF_HOST: "192.168.1.189",
|
||||
CONF_PORT: 8989,
|
||||
CONF_BASE_PATH: "/api",
|
||||
CONF_SSL: False,
|
||||
CONF_API_KEY: API_KEY,
|
||||
CONF_API_KEY: "MOCK_API_KEY",
|
||||
}
|
||||
|
||||
|
||||
def mock_connection(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: str = PORT,
|
||||
base_path: str = BASE_PATH,
|
||||
error: bool = False,
|
||||
invalid_auth: bool = False,
|
||||
server_error: bool = False,
|
||||
) -> None:
|
||||
"""Mock Sonarr connection."""
|
||||
if error:
|
||||
mock_connection_error(
|
||||
aioclient_mock,
|
||||
host=host,
|
||||
port=port,
|
||||
base_path=base_path,
|
||||
)
|
||||
return
|
||||
|
||||
if invalid_auth:
|
||||
mock_connection_invalid_auth(
|
||||
aioclient_mock,
|
||||
host=host,
|
||||
port=port,
|
||||
base_path=base_path,
|
||||
)
|
||||
return
|
||||
|
||||
if server_error:
|
||||
mock_connection_server_error(
|
||||
aioclient_mock,
|
||||
host=host,
|
||||
port=port,
|
||||
base_path=base_path,
|
||||
)
|
||||
return
|
||||
|
||||
sonarr_url = f"http://{host}:{port}{base_path}"
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/system/status",
|
||||
text=load_fixture("sonarr/system-status.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/diskspace",
|
||||
text=load_fixture("sonarr/diskspace.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/calendar",
|
||||
text=load_fixture("sonarr/calendar.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/command",
|
||||
text=load_fixture("sonarr/command.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/queue",
|
||||
text=load_fixture("sonarr/queue.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/series",
|
||||
text=load_fixture("sonarr/series.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/wanted/missing",
|
||||
text=load_fixture("sonarr/wanted-missing.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
|
||||
|
||||
def mock_connection_error(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: str = PORT,
|
||||
base_path: str = BASE_PATH,
|
||||
) -> None:
|
||||
"""Mock Sonarr connection errors."""
|
||||
sonarr_url = f"http://{host}:{port}{base_path}"
|
||||
|
||||
aioclient_mock.get(f"{sonarr_url}/system/status", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/diskspace", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/calendar", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/command", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/queue", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/series", exc=SocketGIAError)
|
||||
aioclient_mock.get(f"{sonarr_url}/missing/wanted", exc=SocketGIAError)
|
||||
|
||||
|
||||
def mock_connection_invalid_auth(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: str = PORT,
|
||||
base_path: str = BASE_PATH,
|
||||
) -> None:
|
||||
"""Mock Sonarr invalid auth errors."""
|
||||
sonarr_url = f"http://{host}:{port}{base_path}"
|
||||
|
||||
aioclient_mock.get(f"{sonarr_url}/system/status", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/diskspace", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/calendar", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/command", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/queue", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/series", status=HTTPStatus.FORBIDDEN)
|
||||
aioclient_mock.get(f"{sonarr_url}/missing/wanted", status=HTTPStatus.FORBIDDEN)
|
||||
|
||||
|
||||
def mock_connection_server_error(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: str = PORT,
|
||||
base_path: str = BASE_PATH,
|
||||
) -> None:
|
||||
"""Mock Sonarr server errors."""
|
||||
sonarr_url = f"http://{host}:{port}{base_path}"
|
||||
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/system/status", status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/diskspace", status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/calendar", status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
aioclient_mock.get(f"{sonarr_url}/command", status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
aioclient_mock.get(f"{sonarr_url}/queue", status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
aioclient_mock.get(f"{sonarr_url}/series", status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
aioclient_mock.get(
|
||||
f"{sonarr_url}/missing/wanted", status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
|
||||
async def setup_integration(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: str = PORT,
|
||||
base_path: str = BASE_PATH,
|
||||
api_key: str = API_KEY,
|
||||
unique_id: str = None,
|
||||
skip_entry_setup: bool = False,
|
||||
connection_error: bool = False,
|
||||
invalid_auth: bool = False,
|
||||
server_error: bool = False,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Sonarr integration in Home Assistant."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=unique_id,
|
||||
data={
|
||||
CONF_HOST: host,
|
||||
CONF_PORT: port,
|
||||
CONF_BASE_PATH: base_path,
|
||||
CONF_SSL: False,
|
||||
CONF_VERIFY_SSL: False,
|
||||
CONF_API_KEY: api_key,
|
||||
CONF_UPCOMING_DAYS: DEFAULT_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS: DEFAULT_WANTED_MAX_ITEMS,
|
||||
},
|
||||
options={
|
||||
CONF_UPCOMING_DAYS: DEFAULT_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS: DEFAULT_WANTED_MAX_ITEMS,
|
||||
},
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_connection(
|
||||
aioclient_mock,
|
||||
host=host,
|
||||
port=port,
|
||||
base_path=base_path,
|
||||
error=connection_error,
|
||||
invalid_auth=invalid_auth,
|
||||
server_error=server_error,
|
||||
)
|
||||
|
||||
if not skip_entry_setup:
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
def _patch_async_setup_entry(return_value=True):
|
||||
"""Patch the async entry setup of sonarr."""
|
||||
return patch(
|
||||
"homeassistant.components.sonarr.async_setup_entry",
|
||||
return_value=return_value,
|
||||
)
|
||||
|
159
tests/components/sonarr/conftest.py
Normal file
159
tests/components/sonarr/conftest.py
Normal file
@ -0,0 +1,159 @@
|
||||
"""Fixtures for Sonarr integration tests."""
|
||||
from collections.abc import Generator
|
||||
import json
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from sonarr.models import (
|
||||
Application,
|
||||
CommandItem,
|
||||
Episode,
|
||||
QueueItem,
|
||||
SeriesItem,
|
||||
WantedResults,
|
||||
)
|
||||
|
||||
from homeassistant.components.sonarr.const import (
|
||||
CONF_BASE_PATH,
|
||||
CONF_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS,
|
||||
DEFAULT_UPCOMING_DAYS,
|
||||
DEFAULT_WANTED_MAX_ITEMS,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_VERIFY_SSL,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
|
||||
|
||||
def sonarr_calendar():
|
||||
"""Generate a response for the calendar method."""
|
||||
results = json.loads(load_fixture("sonarr/calendar.json"))
|
||||
return [Episode.from_dict(result) for result in results]
|
||||
|
||||
|
||||
def sonarr_commands():
|
||||
"""Generate a response for the commands method."""
|
||||
results = json.loads(load_fixture("sonarr/command.json"))
|
||||
return [CommandItem.from_dict(result) for result in results]
|
||||
|
||||
|
||||
def sonarr_queue():
|
||||
"""Generate a response for the queue method."""
|
||||
results = json.loads(load_fixture("sonarr/queue.json"))
|
||||
return [QueueItem.from_dict(result) for result in results]
|
||||
|
||||
|
||||
def sonarr_series():
|
||||
"""Generate a response for the series method."""
|
||||
results = json.loads(load_fixture("sonarr/series.json"))
|
||||
return [SeriesItem.from_dict(result) for result in results]
|
||||
|
||||
|
||||
def sonarr_wanted():
|
||||
"""Generate a response for the wanted method."""
|
||||
results = json.loads(load_fixture("sonarr/wanted-missing.json"))
|
||||
return WantedResults.from_dict(results)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Return the default mocked config entry."""
|
||||
return MockConfigEntry(
|
||||
title="Sonarr",
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: "192.168.1.189",
|
||||
CONF_PORT: 8989,
|
||||
CONF_BASE_PATH: "/api",
|
||||
CONF_SSL: False,
|
||||
CONF_VERIFY_SSL: False,
|
||||
CONF_API_KEY: "MOCK_API_KEY",
|
||||
CONF_UPCOMING_DAYS: DEFAULT_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS: DEFAULT_WANTED_MAX_ITEMS,
|
||||
},
|
||||
options={
|
||||
CONF_UPCOMING_DAYS: DEFAULT_UPCOMING_DAYS,
|
||||
CONF_WANTED_MAX_ITEMS: DEFAULT_WANTED_MAX_ITEMS,
|
||||
},
|
||||
unique_id=None,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[None, None, None]:
|
||||
"""Mock setting up a config entry."""
|
||||
with patch("homeassistant.components.sonarr.async_setup_entry", return_value=True):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_sonarr_config_flow(
|
||||
request: pytest.FixtureRequest,
|
||||
) -> Generator[None, MagicMock, None]:
|
||||
"""Return a mocked Sonarr client."""
|
||||
fixture: str = "sonarr/app.json"
|
||||
if hasattr(request, "param") and request.param:
|
||||
fixture = request.param
|
||||
|
||||
app = Application(json.loads(load_fixture(fixture)))
|
||||
with patch(
|
||||
"homeassistant.components.sonarr.config_flow.Sonarr", autospec=True
|
||||
) as sonarr_mock:
|
||||
client = sonarr_mock.return_value
|
||||
client.host = "192.168.1.189"
|
||||
client.port = 8989
|
||||
client.base_path = "/api"
|
||||
client.tls = False
|
||||
client.app = app
|
||||
client.update.return_value = app
|
||||
client.calendar.return_value = sonarr_calendar()
|
||||
client.commands.return_value = sonarr_commands()
|
||||
client.queue.return_value = sonarr_queue()
|
||||
client.series.return_value = sonarr_series()
|
||||
client.wanted.return_value = sonarr_wanted()
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_sonarr(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||
"""Return a mocked Sonarr client."""
|
||||
fixture: str = "sonarr/app.json"
|
||||
if hasattr(request, "param") and request.param:
|
||||
fixture = request.param
|
||||
|
||||
app = Application(json.loads(load_fixture(fixture)))
|
||||
with patch("homeassistant.components.sonarr.Sonarr", autospec=True) as sonarr_mock:
|
||||
client = sonarr_mock.return_value
|
||||
client.host = "192.168.1.189"
|
||||
client.port = 8989
|
||||
client.base_path = "/api"
|
||||
client.tls = False
|
||||
client.app = app
|
||||
client.update.return_value = app
|
||||
client.calendar.return_value = sonarr_calendar()
|
||||
client.commands.return_value = sonarr_commands()
|
||||
client.queue.return_value = sonarr_queue()
|
||||
client.series.return_value = sonarr_series()
|
||||
client.wanted.return_value = sonarr_wanted()
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_integration(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_sonarr: MagicMock
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Sonarr integration for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return mock_config_entry
|
28
tests/components/sonarr/fixtures/app.json
Normal file
28
tests/components/sonarr/fixtures/app.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"info": {
|
||||
"version": "2.0.0.1121",
|
||||
"buildTime": "2014-02-08T20:49:36.5560392Z",
|
||||
"isDebug": false,
|
||||
"isProduction": true,
|
||||
"isAdmin": true,
|
||||
"isUserInteractive": false,
|
||||
"startupPath": "C:\\ProgramData\\NzbDrone\\bin",
|
||||
"appData": "C:\\ProgramData\\NzbDrone",
|
||||
"osVersion": "6.2.9200.0",
|
||||
"isMono": false,
|
||||
"isLinux": false,
|
||||
"isWindows": true,
|
||||
"branch": "develop",
|
||||
"authentication": false,
|
||||
"startOfWeek": 0,
|
||||
"urlBase": ""
|
||||
},
|
||||
"diskspace": [
|
||||
{
|
||||
"path": "C:\\",
|
||||
"label": "",
|
||||
"freeSpace": 282500067328,
|
||||
"totalSpace": 499738734592
|
||||
}
|
||||
]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0.1121",
|
||||
"buildTime": "2014-02-08T20:49:36.5560392Z",
|
||||
"isDebug": false,
|
||||
"isProduction": true,
|
||||
"isAdmin": true,
|
||||
"isUserInteractive": false,
|
||||
"startupPath": "C:\\ProgramData\\NzbDrone\\bin",
|
||||
"appData": "C:\\ProgramData\\NzbDrone",
|
||||
"osVersion": "6.2.9200.0",
|
||||
"isMono": false,
|
||||
"isLinux": false,
|
||||
"isWindows": true,
|
||||
"branch": "develop",
|
||||
"authentication": false,
|
||||
"startOfWeek": 0,
|
||||
"urlBase": ""
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
"""Test the Sonarr config flow."""
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from sonarr import SonarrAccessRestricted, SonarrError
|
||||
|
||||
from homeassistant.components.sonarr.const import (
|
||||
CONF_UPCOMING_DAYS,
|
||||
@ -17,17 +19,8 @@ from homeassistant.data_entry_flow import (
|
||||
RESULT_TYPE_FORM,
|
||||
)
|
||||
|
||||
from tests.components.sonarr import (
|
||||
HOST,
|
||||
MOCK_REAUTH_INPUT,
|
||||
MOCK_USER_INPUT,
|
||||
_patch_async_setup_entry,
|
||||
mock_connection,
|
||||
mock_connection_error,
|
||||
mock_connection_invalid_auth,
|
||||
setup_integration,
|
||||
)
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.sonarr import MOCK_REAUTH_INPUT, MOCK_USER_INPUT
|
||||
|
||||
|
||||
async def test_show_user_form(hass: HomeAssistant) -> None:
|
||||
@ -42,10 +35,10 @@ async def test_show_user_form(hass: HomeAssistant) -> None:
|
||||
|
||||
|
||||
async def test_cannot_connect(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant, mock_sonarr_config_flow: MagicMock
|
||||
) -> None:
|
||||
"""Test we show user form on connection error."""
|
||||
mock_connection_error(aioclient_mock)
|
||||
mock_sonarr_config_flow.update.side_effect = SonarrError
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -60,10 +53,10 @@ async def test_cannot_connect(
|
||||
|
||||
|
||||
async def test_invalid_auth(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant, mock_sonarr_config_flow: MagicMock
|
||||
) -> None:
|
||||
"""Test we show user form on invalid auth."""
|
||||
mock_connection_invalid_auth(aioclient_mock)
|
||||
mock_sonarr_config_flow.update.side_effect = SonarrAccessRestricted
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -78,30 +71,30 @@ async def test_invalid_auth(
|
||||
|
||||
|
||||
async def test_unknown_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant, mock_sonarr_config_flow: MagicMock
|
||||
) -> None:
|
||||
"""Test we show user form on unknown error."""
|
||||
mock_sonarr_config_flow.update.side_effect = Exception
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
with patch(
|
||||
"homeassistant.components.sonarr.config_flow.Sonarr.update",
|
||||
side_effect=Exception,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={CONF_SOURCE: SOURCE_USER},
|
||||
data=user_input,
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={CONF_SOURCE: SOURCE_USER},
|
||||
data=user_input,
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "unknown"
|
||||
|
||||
|
||||
async def test_full_reauth_flow_implementation(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_sonarr_config_flow: MagicMock,
|
||||
mock_setup_entry: None,
|
||||
init_integration: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the manual reauth flow from start to finish."""
|
||||
entry = await setup_integration(hass, aioclient_mock, skip_entry_setup=True)
|
||||
assert entry
|
||||
entry = init_integration
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
@ -124,26 +117,23 @@ async def test_full_reauth_flow_implementation(
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
user_input = MOCK_REAUTH_INPUT.copy()
|
||||
with _patch_async_setup_entry() as mock_setup_entry:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=user_input
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=user_input
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "reauth_successful"
|
||||
|
||||
assert entry.data[CONF_API_KEY] == "test-api-key-reauth"
|
||||
|
||||
mock_setup_entry.assert_called_once()
|
||||
|
||||
|
||||
async def test_full_user_flow_implementation(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_sonarr_config_flow: MagicMock,
|
||||
mock_setup_entry: None,
|
||||
) -> None:
|
||||
"""Test the full manual user flow from start to finish."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={CONF_SOURCE: SOURCE_USER},
|
||||
@ -154,25 +144,24 @@ async def test_full_user_flow_implementation(
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
|
||||
with _patch_async_setup_entry():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=user_input,
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=user_input,
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == HOST
|
||||
assert result["title"] == "192.168.1.189"
|
||||
|
||||
assert result["data"]
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
assert result["data"][CONF_HOST] == "192.168.1.189"
|
||||
|
||||
|
||||
async def test_full_user_flow_advanced_options(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_sonarr_config_flow: MagicMock,
|
||||
mock_setup_entry: None,
|
||||
) -> None:
|
||||
"""Test the full manual user flow with advanced options."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_USER, "show_advanced_options": True}
|
||||
)
|
||||
@ -185,24 +174,27 @@ async def test_full_user_flow_advanced_options(
|
||||
CONF_VERIFY_SSL: True,
|
||||
}
|
||||
|
||||
with _patch_async_setup_entry():
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=user_input,
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input=user_input,
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == HOST
|
||||
assert result["title"] == "192.168.1.189"
|
||||
|
||||
assert result["data"]
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
assert result["data"][CONF_HOST] == "192.168.1.189"
|
||||
assert result["data"][CONF_VERIFY_SSL]
|
||||
|
||||
|
||||
async def test_options_flow(hass, aioclient_mock: AiohttpClientMocker):
|
||||
@patch("homeassistant.components.sonarr.PLATFORMS", [])
|
||||
async def test_options_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: None,
|
||||
init_integration: MockConfigEntry,
|
||||
):
|
||||
"""Test updating options."""
|
||||
with patch("homeassistant.components.sonarr.PLATFORMS", []):
|
||||
entry = await setup_integration(hass, aioclient_mock)
|
||||
entry = init_integration
|
||||
|
||||
assert entry.options[CONF_UPCOMING_DAYS] == DEFAULT_UPCOMING_DAYS
|
||||
assert entry.options[CONF_WANTED_MAX_ITEMS] == DEFAULT_WANTED_MAX_ITEMS
|
||||
@ -212,12 +204,11 @@ async def test_options_flow(hass, aioclient_mock: AiohttpClientMocker):
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
with _patch_async_setup_entry():
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_UPCOMING_DAYS: 2, CONF_WANTED_MAX_ITEMS: 100},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_UPCOMING_DAYS: 2, CONF_WANTED_MAX_ITEMS: 100},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["data"][CONF_UPCOMING_DAYS] == 2
|
||||
|
@ -1,60 +1,79 @@
|
||||
"""Tests for the Sonsrr integration."""
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from sonarr import SonarrAccessRestricted, SonarrError
|
||||
|
||||
from homeassistant.components.sonarr.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
|
||||
from homeassistant.const import CONF_SOURCE
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.components.sonarr import setup_integration
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_config_entry_not_ready(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sonarr: MagicMock,
|
||||
) -> None:
|
||||
"""Test the configuration entry not ready."""
|
||||
entry = await setup_integration(hass, aioclient_mock, connection_error=True)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
mock_sonarr.update.side_effect = SonarrError
|
||||
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_config_entry_reauth(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sonarr: MagicMock,
|
||||
) -> None:
|
||||
"""Test the configuration entry needing to be re-authenticated."""
|
||||
with patch.object(hass.config_entries.flow, "async_init") as mock_flow_init:
|
||||
entry = await setup_integration(hass, aioclient_mock, invalid_auth=True)
|
||||
mock_sonarr.update.side_effect = SonarrAccessRestricted
|
||||
|
||||
assert entry.state is ConfigEntryState.SETUP_ERROR
|
||||
with patch.object(hass.config_entries.flow, "async_init") as mock_flow_init:
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
mock_flow_init.assert_called_once_with(
|
||||
DOMAIN,
|
||||
context={
|
||||
CONF_SOURCE: SOURCE_REAUTH,
|
||||
"entry_id": entry.entry_id,
|
||||
"unique_id": entry.unique_id,
|
||||
"title_placeholders": {"name": entry.title},
|
||||
"entry_id": mock_config_entry.entry_id,
|
||||
"unique_id": mock_config_entry.unique_id,
|
||||
"title_placeholders": {"name": mock_config_entry.title},
|
||||
},
|
||||
data=entry.data,
|
||||
data=mock_config_entry.data,
|
||||
)
|
||||
|
||||
|
||||
async def test_unload_config_entry(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sonarr: MagicMock,
|
||||
) -> None:
|
||||
"""Test the configuration entry unloading."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.sonarr.sensor.async_setup_entry",
|
||||
return_value=True,
|
||||
):
|
||||
entry = await setup_integration(hass, aioclient_mock)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.data[DOMAIN]
|
||||
assert entry.entry_id in hass.data[DOMAIN]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
assert mock_config_entry.entry_id in hass.data[DOMAIN]
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.entry_id not in hass.data[DOMAIN]
|
||||
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert mock_config_entry.entry_id not in hass.data[DOMAIN]
|
||||
|
@ -1,8 +1,9 @@
|
||||
"""Tests for the Sonarr sensor platform."""
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from sonarr import SonarrError
|
||||
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.components.sonarr.const import DOMAIN
|
||||
@ -16,18 +17,18 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.components.sonarr import mock_connection, setup_integration
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
UPCOMING_ENTITY_ID = f"{SENSOR_DOMAIN}.sonarr_upcoming"
|
||||
|
||||
|
||||
async def test_sensors(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sonarr: MagicMock,
|
||||
) -> None:
|
||||
"""Test the creation and values of the sensors."""
|
||||
entry = await setup_integration(hass, aioclient_mock, skip_entry_setup=True)
|
||||
entry = mock_config_entry
|
||||
registry = er.async_get(hass)
|
||||
|
||||
# Pre-create registry entries for disabled by default sensors
|
||||
@ -48,6 +49,7 @@ async def test_sensors(
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
@ -104,10 +106,11 @@ async def test_sensors(
|
||||
),
|
||||
)
|
||||
async def test_disabled_by_default_sensors(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, entity_id: str
|
||||
hass: HomeAssistant,
|
||||
init_integration: MockConfigEntry,
|
||||
entity_id: str,
|
||||
) -> None:
|
||||
"""Test the disabled by default sensors."""
|
||||
await setup_integration(hass, aioclient_mock)
|
||||
registry = er.async_get(hass)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
@ -120,19 +123,22 @@ async def test_disabled_by_default_sensors(
|
||||
|
||||
|
||||
async def test_availability(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_sonarr: MagicMock,
|
||||
) -> None:
|
||||
"""Test entity availability."""
|
||||
now = dt_util.utcnow()
|
||||
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=now):
|
||||
await setup_integration(hass, aioclient_mock)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(UPCOMING_ENTITY_ID).state == "1"
|
||||
|
||||
# state to unavailable
|
||||
aioclient_mock.clear_requests()
|
||||
mock_connection(aioclient_mock, error=True)
|
||||
mock_sonarr.calendar.side_effect = SonarrError
|
||||
|
||||
future = now + timedelta(minutes=1)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=future):
|
||||
@ -142,8 +148,7 @@ async def test_availability(
|
||||
assert hass.states.get(UPCOMING_ENTITY_ID).state == STATE_UNAVAILABLE
|
||||
|
||||
# state to available
|
||||
aioclient_mock.clear_requests()
|
||||
mock_connection(aioclient_mock)
|
||||
mock_sonarr.calendar.side_effect = None
|
||||
|
||||
future += timedelta(minutes=1)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=future):
|
||||
@ -153,8 +158,7 @@ async def test_availability(
|
||||
assert hass.states.get(UPCOMING_ENTITY_ID).state == "1"
|
||||
|
||||
# state to unavailable
|
||||
aioclient_mock.clear_requests()
|
||||
mock_connection(aioclient_mock, invalid_auth=True)
|
||||
mock_sonarr.calendar.side_effect = SonarrError
|
||||
|
||||
future += timedelta(minutes=1)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=future):
|
||||
@ -164,8 +168,7 @@ async def test_availability(
|
||||
assert hass.states.get(UPCOMING_ENTITY_ID).state == STATE_UNAVAILABLE
|
||||
|
||||
# state to available
|
||||
aioclient_mock.clear_requests()
|
||||
mock_connection(aioclient_mock)
|
||||
mock_sonarr.calendar.side_effect = None
|
||||
|
||||
future += timedelta(minutes=1)
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=future):
|
||||
|
Loading…
x
Reference in New Issue
Block a user