From 70da08499add6d3ce7b6320623390842c365a4dd Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Mon, 31 Jan 2022 16:59:18 -0600 Subject: [PATCH] Refactor sonarr tests (#64886) --- tests/components/sonarr/__init__.py | 243 +----------------- tests/components/sonarr/conftest.py | 159 ++++++++++++ tests/components/sonarr/fixtures/app.json | 28 ++ .../sonarr/fixtures/system-status.json | 18 -- tests/components/sonarr/test_config_flow.py | 121 ++++----- tests/components/sonarr/test_init.py | 61 +++-- tests/components/sonarr/test_sensor.py | 39 +-- 7 files changed, 310 insertions(+), 359 deletions(-) create mode 100644 tests/components/sonarr/conftest.py create mode 100644 tests/components/sonarr/fixtures/app.json delete mode 100644 tests/components/sonarr/fixtures/system-status.json diff --git a/tests/components/sonarr/__init__.py b/tests/components/sonarr/__init__.py index 8172cb4e0dd..cd3fb8f795a 100644 --- a/tests/components/sonarr/__init__.py +++ b/tests/components/sonarr/__init__.py @@ -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, - ) diff --git a/tests/components/sonarr/conftest.py b/tests/components/sonarr/conftest.py new file mode 100644 index 00000000000..a03ae7532d4 --- /dev/null +++ b/tests/components/sonarr/conftest.py @@ -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 diff --git a/tests/components/sonarr/fixtures/app.json b/tests/components/sonarr/fixtures/app.json new file mode 100644 index 00000000000..e9ce88b233e --- /dev/null +++ b/tests/components/sonarr/fixtures/app.json @@ -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 + } + ] +} diff --git a/tests/components/sonarr/fixtures/system-status.json b/tests/components/sonarr/fixtures/system-status.json deleted file mode 100644 index c3969df08fe..00000000000 --- a/tests/components/sonarr/fixtures/system-status.json +++ /dev/null @@ -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": "" -} diff --git a/tests/components/sonarr/test_config_flow.py b/tests/components/sonarr/test_config_flow.py index 87b38e52742..52e7b9b61ca 100644 --- a/tests/components/sonarr/test_config_flow.py +++ b/tests/components/sonarr/test_config_flow.py @@ -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 diff --git a/tests/components/sonarr/test_init.py b/tests/components/sonarr/test_init.py index 39d9b7fc24e..3a59f5d7cca 100644 --- a/tests/components/sonarr/test_init.py +++ b/tests/components/sonarr/test_init.py @@ -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] diff --git a/tests/components/sonarr/test_sensor.py b/tests/components/sonarr/test_sensor.py index f68920e4e4f..8acf7d5b2c8 100644 --- a/tests/components/sonarr/test_sensor.py +++ b/tests/components/sonarr/test_sensor.py @@ -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):