mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add tests to Lidarr (#79610)
* Add tests to Lidarr * fix js files * take out the trash * fix 3.9 * uno mas * fix fixture * ruff * Update const.py --------- Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
a26d95ec02
commit
866518c5a0
@ -629,9 +629,6 @@ omit =
|
|||||||
homeassistant/components/lg_netcast/media_player.py
|
homeassistant/components/lg_netcast/media_player.py
|
||||||
homeassistant/components/lg_soundbar/__init__.py
|
homeassistant/components/lg_soundbar/__init__.py
|
||||||
homeassistant/components/lg_soundbar/media_player.py
|
homeassistant/components/lg_soundbar/media_player.py
|
||||||
homeassistant/components/lidarr/__init__.py
|
|
||||||
homeassistant/components/lidarr/coordinator.py
|
|
||||||
homeassistant/components/lidarr/sensor.py
|
|
||||||
homeassistant/components/life360/__init__.py
|
homeassistant/components/life360/__init__.py
|
||||||
homeassistant/components/life360/coordinator.py
|
homeassistant/components/life360/coordinator.py
|
||||||
homeassistant/components/life360/device_tracker.py
|
homeassistant/components/life360/device_tracker.py
|
||||||
|
@ -4,3 +4,5 @@ azure-*.yml
|
|||||||
docs/source/_templates/*
|
docs/source/_templates/*
|
||||||
homeassistant/components/*/translations/*.json
|
homeassistant/components/*/translations/*.json
|
||||||
homeassistant/generated/*
|
homeassistant/generated/*
|
||||||
|
tests/components/lidarr/fixtures/initialize.js
|
||||||
|
tests/components/lidarr/fixtures/initialize-wrong.js
|
||||||
|
@ -17,8 +17,6 @@ BYTE_SIZES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
DEFAULT_DAYS = "1"
|
|
||||||
DEFAULT_HOST = "localhost"
|
|
||||||
DEFAULT_NAME = "Lidarr"
|
DEFAULT_NAME = "Lidarr"
|
||||||
DEFAULT_UNIT = UnitOfInformation.GIGABYTES
|
DEFAULT_UNIT = UnitOfInformation.GIGABYTES
|
||||||
DEFAULT_MAX_RECORDS = 20
|
DEFAULT_MAX_RECORDS = 20
|
||||||
|
@ -1,53 +1 @@
|
|||||||
"""Tests for the Lidarr component."""
|
"""Tests for the Lidarr component."""
|
||||||
from aiopyarr.lidarr_client import LidarrClient
|
|
||||||
|
|
||||||
from homeassistant.components.lidarr.const import DOMAIN
|
|
||||||
from homeassistant.const import (
|
|
||||||
CONF_API_KEY,
|
|
||||||
CONF_URL,
|
|
||||||
CONF_VERIFY_SSL,
|
|
||||||
CONTENT_TYPE_JSON,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, load_fixture
|
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
|
||||||
|
|
||||||
BASE_PATH = ""
|
|
||||||
API_KEY = "1234567890abcdef1234567890abcdef"
|
|
||||||
URL = "http://127.0.0.1:8686"
|
|
||||||
client = LidarrClient(session=async_get_clientsession, api_token=API_KEY, url=URL)
|
|
||||||
API_URL = f"{URL}/api/{client._host.api_ver}"
|
|
||||||
|
|
||||||
MOCK_REAUTH_INPUT = {CONF_API_KEY: "new_key"}
|
|
||||||
|
|
||||||
MOCK_USER_INPUT = {
|
|
||||||
CONF_URL: URL,
|
|
||||||
CONF_VERIFY_SSL: False,
|
|
||||||
}
|
|
||||||
|
|
||||||
CONF_DATA = MOCK_USER_INPUT | {CONF_API_KEY: API_KEY}
|
|
||||||
|
|
||||||
|
|
||||||
def mock_connection(
|
|
||||||
aioclient_mock: AiohttpClientMocker,
|
|
||||||
url: str = API_URL,
|
|
||||||
) -> None:
|
|
||||||
"""Mock lidarr connection."""
|
|
||||||
aioclient_mock.get(
|
|
||||||
f"{url}/system/status",
|
|
||||||
text=load_fixture("lidarr/system-status.json"),
|
|
||||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def create_entry(hass: HomeAssistant) -> MockConfigEntry:
|
|
||||||
"""Create Efergy entry in Home Assistant."""
|
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN,
|
|
||||||
data=CONF_DATA,
|
|
||||||
)
|
|
||||||
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
return entry
|
|
||||||
|
142
tests/components/lidarr/conftest.py
Normal file
142
tests/components/lidarr/conftest.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
"""Configure pytest for Lidarr tests."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Awaitable, Callable, Generator
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
from aiohttp.client_exceptions import ClientError
|
||||||
|
from aiopyarr.lidarr_client import LidarrClient
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.lidarr.const import DOMAIN
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_API_KEY,
|
||||||
|
CONF_URL,
|
||||||
|
CONF_VERIFY_SSL,
|
||||||
|
CONTENT_TYPE_JSON,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, load_fixture
|
||||||
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
|
URL = "http://127.0.0.1:8668"
|
||||||
|
API_KEY = "1234567890abcdef1234567890abcdef"
|
||||||
|
client = LidarrClient(session=async_get_clientsession, api_token=API_KEY, url=URL)
|
||||||
|
API_URL = f"{URL}/api/{client._host.api_ver}"
|
||||||
|
|
||||||
|
MOCK_INPUT = {CONF_URL: URL, CONF_VERIFY_SSL: False}
|
||||||
|
|
||||||
|
CONF_DATA = MOCK_INPUT | {CONF_API_KEY: API_KEY}
|
||||||
|
|
||||||
|
ComponentSetup = Callable[[], Awaitable[None]]
|
||||||
|
|
||||||
|
|
||||||
|
def mock_error(
|
||||||
|
aioclient_mock: AiohttpClientMocker, status: HTTPStatus | None = None
|
||||||
|
) -> None:
|
||||||
|
"""Mock an error."""
|
||||||
|
if status:
|
||||||
|
aioclient_mock.get(f"{API_URL}/queue", status=status)
|
||||||
|
aioclient_mock.get(f"{API_URL}/rootfolder", status=status)
|
||||||
|
aioclient_mock.get(f"{API_URL}/system/status", status=status)
|
||||||
|
aioclient_mock.get(f"{API_URL}/wanted/missing", status=status)
|
||||||
|
aioclient_mock.get(f"{API_URL}/queue", exc=ClientError)
|
||||||
|
aioclient_mock.get(f"{API_URL}/rootfolder", exc=ClientError)
|
||||||
|
aioclient_mock.get(f"{API_URL}/system/status", exc=ClientError)
|
||||||
|
aioclient_mock.get(f"{API_URL}/wanted/missing", exc=ClientError)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def cannot_connect(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock cannot connect error."""
|
||||||
|
mock_error(aioclient_mock, status=HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def invalid_auth(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock invalid authorization error."""
|
||||||
|
mock_error(aioclient_mock, status=HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def wrong_app(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock Lidarr wrong app."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{URL}/initialize.js",
|
||||||
|
text=load_fixture("lidarr/initialize-wrong.js"),
|
||||||
|
headers={"Content-Type": "application/javascript"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def zeroconf_failed(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock Lidarr zero configuration failure."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{URL}/initialize.js",
|
||||||
|
text="login-failed",
|
||||||
|
headers={"Content-Type": "application/javascript"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def unknown(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock Lidarr unknown error."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{URL}/initialize.js",
|
||||||
|
text="something went wrong",
|
||||||
|
headers={"Content-Type": "application/javascript"},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="connection")
|
||||||
|
def mock_connection(aioclient_mock: AiohttpClientMocker) -> None:
|
||||||
|
"""Mock Lidarr connection."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{URL}/initialize.js",
|
||||||
|
text=load_fixture("lidarr/initialize.js"),
|
||||||
|
headers={"Content-Type": "application/javascript"},
|
||||||
|
)
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{API_URL}/system/status",
|
||||||
|
text=load_fixture("lidarr/system-status.json"),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{API_URL}/queue",
|
||||||
|
text=load_fixture("lidarr/queue.json"),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{API_URL}/wanted/missing",
|
||||||
|
text=load_fixture("lidarr/wanted-missing.json"),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
aioclient_mock.get(
|
||||||
|
f"{API_URL}/rootfolder",
|
||||||
|
text=load_fixture("lidarr/rootfolder-linux.json"),
|
||||||
|
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="config_entry")
|
||||||
|
def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry:
|
||||||
|
"""Create Lidarr entry in Home Assistant."""
|
||||||
|
return MockConfigEntry(domain=DOMAIN, data=CONF_DATA)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="setup_integration")
|
||||||
|
async def mock_setup_integration(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
) -> Generator[ComponentSetup, None, None]:
|
||||||
|
"""Set up the lidarr integration in Home Assistant."""
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
async def func() -> None:
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
return func
|
12
tests/components/lidarr/fixtures/initialize-wrong.js
Normal file
12
tests/components/lidarr/fixtures/initialize-wrong.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
window.Radarr = {
|
||||||
|
apiRoot: '/api/v3',
|
||||||
|
apiKey: '1234567890abcdef1234567890abcdef',
|
||||||
|
release: '4.0.3.5849-develop',
|
||||||
|
version: '4.0.3.5849',
|
||||||
|
instanceName: 'Radarr',
|
||||||
|
branch: 'nightly',
|
||||||
|
analytics: true,
|
||||||
|
userHash: 'abcd1234',
|
||||||
|
urlBase: '',
|
||||||
|
isProduction: true
|
||||||
|
};
|
12
tests/components/lidarr/fixtures/initialize.js
Normal file
12
tests/components/lidarr/fixtures/initialize.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
window.Lidarr = {
|
||||||
|
apiRoot: '/api/v1',
|
||||||
|
apiKey: '1234567890abcdef1234567890abcdef',
|
||||||
|
release: '10.0.0.34882-develop',
|
||||||
|
version: '10.0.0.34882',
|
||||||
|
instanceName: 'Lidarr',
|
||||||
|
branch: 'nightly',
|
||||||
|
analytics: true,
|
||||||
|
userHash: 'abcd1234',
|
||||||
|
urlBase: '',
|
||||||
|
isProduction: true
|
||||||
|
};
|
57
tests/components/lidarr/fixtures/queue.json
Normal file
57
tests/components/lidarr/fixtures/queue.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"page": 1,
|
||||||
|
"pageSize": 20,
|
||||||
|
"sortKey": "timeleft",
|
||||||
|
"sortDirection": "default",
|
||||||
|
"totalRecords": 2,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"artistId": 1,
|
||||||
|
"albumId": 1,
|
||||||
|
"quality": {
|
||||||
|
"quality": { "id": 0, "name": "Unknown" },
|
||||||
|
"revision": { "version": 1, "real": 0, "isRepack": false }
|
||||||
|
},
|
||||||
|
"size": 1000000,
|
||||||
|
"title": "string",
|
||||||
|
"sizeleft": 100000,
|
||||||
|
"timeleft": "00:00:00",
|
||||||
|
"estimatedCompletionTime": "2020-09-26T18:47:46Z",
|
||||||
|
"status": "downloading",
|
||||||
|
"trackedDownloadStatus": "ok",
|
||||||
|
"trackedDownloadState": "downloading",
|
||||||
|
"statusMessages": [],
|
||||||
|
"downloadId": "string",
|
||||||
|
"protocol": "string",
|
||||||
|
"downloadClient": "testclient",
|
||||||
|
"indexer": "test",
|
||||||
|
"outputPath": "/downloads/string",
|
||||||
|
"downloadForced": false,
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"artistId": 1,
|
||||||
|
"albumId": 1,
|
||||||
|
"quality": {
|
||||||
|
"quality": { "id": 0, "name": "Unknown" },
|
||||||
|
"revision": { "version": 1, "real": 0, "isRepack": false }
|
||||||
|
},
|
||||||
|
"size": 2000000,
|
||||||
|
"title": "string2",
|
||||||
|
"sizeleft": 1000000,
|
||||||
|
"timeleft": "00:00:10",
|
||||||
|
"estimatedCompletionTime": "2020-09-26T18:47:46Z",
|
||||||
|
"status": "downloading",
|
||||||
|
"trackedDownloadStatus": "ok",
|
||||||
|
"trackedDownloadState": "downloading",
|
||||||
|
"statusMessages": [],
|
||||||
|
"downloadId": "string",
|
||||||
|
"protocol": "string",
|
||||||
|
"downloadClient": "testclient",
|
||||||
|
"indexer": "test",
|
||||||
|
"outputPath": "/downloads/string",
|
||||||
|
"downloadForced": false,
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
tests/components/lidarr/fixtures/rootfolder-linux.json
Normal file
15
tests/components/lidarr/fixtures/rootfolder-linux.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "/music/",
|
||||||
|
"path": "/music/",
|
||||||
|
"defaultMetadataProfileId": 1,
|
||||||
|
"defaultQualityProfileId": 1,
|
||||||
|
"defaultMonitorOption": "all",
|
||||||
|
"defaultNewItemMonitorOption": "all",
|
||||||
|
"defaultTags": [],
|
||||||
|
"accessible": true,
|
||||||
|
"freeSpace": 1000000000,
|
||||||
|
"totalSpace": 100000000000,
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
@ -5,8 +5,8 @@
|
|||||||
"isProduction": false,
|
"isProduction": false,
|
||||||
"isAdmin": false,
|
"isAdmin": false,
|
||||||
"isUserInteractive": true,
|
"isUserInteractive": true,
|
||||||
"startupPath": "C:\\ProgramData\\Radarr",
|
"startupPath": "C:\\ProgramData\\Lidarr",
|
||||||
"appData": "C:\\ProgramData\\Radarr",
|
"appData": "C:\\ProgramData\\Lidarr",
|
||||||
"osName": "Windows",
|
"osName": "Windows",
|
||||||
"osVersion": "10.0.18363.0",
|
"osVersion": "10.0.18363.0",
|
||||||
"isNetCore": true,
|
"isNetCore": true,
|
||||||
|
134
tests/components/lidarr/fixtures/wanted-missing.json
Normal file
134
tests/components/lidarr/fixtures/wanted-missing.json
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"page": 1,
|
||||||
|
"pageSize": 20,
|
||||||
|
"sortKey": "title",
|
||||||
|
"sortDirection": "default",
|
||||||
|
"totalRecords": 1,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"title": "test",
|
||||||
|
"disambiguation": "string",
|
||||||
|
"overview": "string",
|
||||||
|
"artistId": 0,
|
||||||
|
"foreignAlbumId": "string",
|
||||||
|
"monitored": true,
|
||||||
|
"anyReleaseOk": true,
|
||||||
|
"profileId": 1,
|
||||||
|
"duration": 0,
|
||||||
|
"albumType": "Album",
|
||||||
|
"secondaryTypes": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mediumCount": 1,
|
||||||
|
"ratings": {
|
||||||
|
"votes": 0,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"releaseDate": "1968-01-01T00:00:00Z",
|
||||||
|
"releases": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"albumId": 0,
|
||||||
|
"foreignReleaseId": "string",
|
||||||
|
"title": "string",
|
||||||
|
"status": "string",
|
||||||
|
"duration": 0,
|
||||||
|
"trackCount": 1,
|
||||||
|
"media": [
|
||||||
|
{
|
||||||
|
"mediumNumber": 1,
|
||||||
|
"mediumName": "Unknown",
|
||||||
|
"mediumFormat": "Unknown"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mediumCount": 1,
|
||||||
|
"disambiguation": "",
|
||||||
|
"country": ["string"],
|
||||||
|
"label": ["test"],
|
||||||
|
"format": "Unknown",
|
||||||
|
"monitored": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"genres": ["string"],
|
||||||
|
"media": [
|
||||||
|
{
|
||||||
|
"mediumNumber": 1,
|
||||||
|
"mediumName": "Unknown",
|
||||||
|
"mediumFormat": "Unknown"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"artist": {
|
||||||
|
"artistMetadataId": 0,
|
||||||
|
"status": "continuing",
|
||||||
|
"ended": false,
|
||||||
|
"artistName": "test",
|
||||||
|
"foreignArtistId": "string",
|
||||||
|
"tadbId": 0,
|
||||||
|
"discogsId": 0,
|
||||||
|
"overview": "string",
|
||||||
|
"artistType": "Group",
|
||||||
|
"disambiguation": "",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"url": "string",
|
||||||
|
"name": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
{
|
||||||
|
"url": "https://test.jpg",
|
||||||
|
"coverType": "fanart",
|
||||||
|
"extension": ".jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"path": "string",
|
||||||
|
"qualityProfileId": 1,
|
||||||
|
"metadataProfileId": 1,
|
||||||
|
"monitored": true,
|
||||||
|
"monitorNewItems": "all",
|
||||||
|
"genres": ["string"],
|
||||||
|
"cleanName": "string",
|
||||||
|
"sortName": "string",
|
||||||
|
"tags": [0],
|
||||||
|
"added": "2020-03-18T15:51:22Z",
|
||||||
|
"ratings": {
|
||||||
|
"votes": 0,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"albumCount": 0,
|
||||||
|
"trackFileCount": 0,
|
||||||
|
"trackCount": 0,
|
||||||
|
"totalTrackCount": 0,
|
||||||
|
"sizeOnDisk": 0,
|
||||||
|
"percentOfTracks": 0
|
||||||
|
},
|
||||||
|
"id": 0
|
||||||
|
},
|
||||||
|
"images": [
|
||||||
|
{
|
||||||
|
"url": "string",
|
||||||
|
"coverType": "poster"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"url": "string",
|
||||||
|
"name": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"statistics": {
|
||||||
|
"trackFileCount": 0,
|
||||||
|
"trackCount": 1,
|
||||||
|
"totalTrackCount": 1,
|
||||||
|
"sizeOnDisk": 0,
|
||||||
|
"percentOfTracks": 0
|
||||||
|
},
|
||||||
|
"grabbed": false,
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,138 +1,104 @@
|
|||||||
"""Test Lidarr config flow."""
|
"""Test Lidarr config flow."""
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from aiopyarr import exceptions
|
|
||||||
|
|
||||||
from homeassistant import data_entry_flow
|
from homeassistant import data_entry_flow
|
||||||
from homeassistant.components.lidarr.const import DEFAULT_NAME, DOMAIN
|
from homeassistant.components.lidarr.const import DEFAULT_NAME, DOMAIN
|
||||||
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_SOURCE
|
from homeassistant.const import CONF_API_KEY, CONF_SOURCE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from . import API_KEY, CONF_DATA, MOCK_USER_INPUT, create_entry, mock_connection
|
from .conftest import CONF_DATA, MOCK_INPUT, ComponentSetup
|
||||||
|
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
|
||||||
|
|
||||||
|
|
||||||
def _patch_client():
|
async def test_flow_user_form(hass: HomeAssistant, connection) -> None:
|
||||||
return patch(
|
|
||||||
"homeassistant.components.lidarr.config_flow.LidarrClient.async_get_system_status"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_user_form(
|
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
|
||||||
) -> None:
|
|
||||||
"""Test that the user set up form is served."""
|
"""Test that the user set up form is served."""
|
||||||
mock_connection(aioclient_mock)
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
)
|
)
|
||||||
with patch(
|
|
||||||
"homeassistant.components.lidarr.config_flow.LidarrClient.async_try_zeroconf",
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
return_value=("/api/v3", API_KEY, ""),
|
assert result["step_id"] == "user"
|
||||||
):
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input=MOCK_USER_INPUT,
|
user_input=MOCK_INPUT,
|
||||||
)
|
)
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result["title"] == DEFAULT_NAME
|
assert result["title"] == DEFAULT_NAME
|
||||||
assert result["data"] == CONF_DATA
|
assert result["data"] == CONF_DATA
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_user_invalid_auth(hass: HomeAssistant) -> None:
|
async def test_flow_user_invalid_auth(hass: HomeAssistant, invalid_auth) -> None:
|
||||||
"""Test invalid authentication."""
|
"""Test invalid authentication."""
|
||||||
with _patch_client() as client:
|
result = await hass.config_entries.flow.async_init(
|
||||||
client.side_effect = exceptions.ArrAuthenticationException
|
DOMAIN,
|
||||||
result = await hass.config_entries.flow.async_init(
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
DOMAIN,
|
data=CONF_DATA,
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
)
|
||||||
)
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
|
||||||
user_input=CONF_DATA,
|
|
||||||
)
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"]["base"] == "invalid_auth"
|
assert result["errors"]["base"] == "invalid_auth"
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_user_cannot_connect(hass: HomeAssistant) -> None:
|
async def test_flow_user_cannot_connect(hass: HomeAssistant, cannot_connect) -> None:
|
||||||
"""Test connection error."""
|
"""Test connection error."""
|
||||||
with _patch_client() as client:
|
result = await hass.config_entries.flow.async_init(
|
||||||
client.side_effect = exceptions.ArrConnectionException
|
DOMAIN,
|
||||||
result = await hass.config_entries.flow.async_init(
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
DOMAIN,
|
data=CONF_DATA,
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
)
|
||||||
)
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
|
||||||
result["flow_id"],
|
|
||||||
user_input=CONF_DATA,
|
|
||||||
)
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"]["base"] == "cannot_connect"
|
assert result["errors"]["base"] == "cannot_connect"
|
||||||
|
|
||||||
|
|
||||||
async def test_wrong_app(hass: HomeAssistant) -> None:
|
async def test_wrong_app(hass: HomeAssistant, wrong_app) -> None:
|
||||||
"""Test we show user form on wrong app."""
|
"""Test we show user form on wrong app."""
|
||||||
with patch(
|
result = await hass.config_entries.flow.async_init(
|
||||||
"homeassistant.components.lidarr.config_flow.LidarrClient.async_try_zeroconf",
|
DOMAIN,
|
||||||
side_effect=exceptions.ArrWrongAppException,
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
):
|
data=MOCK_INPUT,
|
||||||
result = await hass.config_entries.flow.async_init(
|
)
|
||||||
DOMAIN,
|
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
|
||||||
data=MOCK_USER_INPUT,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"]["base"] == "wrong_app"
|
assert result["errors"]["base"] == "wrong_app"
|
||||||
|
|
||||||
|
|
||||||
async def test_zero_conf_failure(hass: HomeAssistant) -> None:
|
async def test_zeroconf_failed(hass: HomeAssistant, zeroconf_failed) -> None:
|
||||||
"""Test we show user form on api key retrieval failure."""
|
"""Test we show user form on zeroconf failure."""
|
||||||
with patch(
|
result = await hass.config_entries.flow.async_init(
|
||||||
"homeassistant.components.lidarr.config_flow.LidarrClient.async_try_zeroconf",
|
DOMAIN,
|
||||||
side_effect=exceptions.ArrZeroConfException,
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
):
|
data=MOCK_INPUT,
|
||||||
result = await hass.config_entries.flow.async_init(
|
)
|
||||||
DOMAIN,
|
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
|
||||||
data=MOCK_USER_INPUT,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"]["base"] == "zeroconf_failed"
|
assert result["errors"]["base"] == "zeroconf_failed"
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_user_unknown_error(hass: HomeAssistant) -> None:
|
async def test_flow_user_unknown_error(hass: HomeAssistant, unknown) -> None:
|
||||||
"""Test unknown error."""
|
"""Test unknown error."""
|
||||||
with _patch_client() as client:
|
result = await hass.config_entries.flow.async_init(
|
||||||
client.side_effect = exceptions.ArrException
|
DOMAIN,
|
||||||
result = await hass.config_entries.flow.async_init(
|
context={CONF_SOURCE: SOURCE_USER},
|
||||||
DOMAIN,
|
)
|
||||||
context={CONF_SOURCE: SOURCE_USER},
|
result = await hass.config_entries.flow.async_configure(
|
||||||
)
|
result["flow_id"],
|
||||||
result = await hass.config_entries.flow.async_configure(
|
user_input=CONF_DATA,
|
||||||
result["flow_id"],
|
)
|
||||||
user_input=CONF_DATA,
|
|
||||||
)
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "user"
|
assert result["step_id"] == "user"
|
||||||
assert result["errors"]["base"] == "unknown"
|
assert result["errors"]["base"] == "unknown"
|
||||||
|
|
||||||
|
|
||||||
async def test_flow_reauth(
|
async def test_flow_reauth(
|
||||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
hass: HomeAssistant, setup_integration: ComponentSetup, connection
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test reauth."""
|
"""Test reauth."""
|
||||||
entry = create_entry(hass)
|
await setup_integration()
|
||||||
mock_connection(aioclient_mock)
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
context={
|
context={
|
||||||
|
61
tests/components/lidarr/test_init.py
Normal file
61
tests/components/lidarr/test_init.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
"""Test Lidarr integration."""
|
||||||
|
from homeassistant.components.lidarr.const import DEFAULT_NAME, DOMAIN
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
|
||||||
|
from .conftest import ComponentSetup
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup, connection
|
||||||
|
) -> None:
|
||||||
|
"""Test setup."""
|
||||||
|
await setup_integration()
|
||||||
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
assert entry.state == ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||||
|
assert not hass.data.get(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_setup_entry_not_ready(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup, cannot_connect
|
||||||
|
) -> None:
|
||||||
|
"""Test that it throws ConfigEntryNotReady when exception occurs during setup."""
|
||||||
|
await setup_integration()
|
||||||
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||||
|
assert entry.state == ConfigEntryState.SETUP_RETRY
|
||||||
|
assert not hass.data.get(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_setup_entry_auth_failed(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup, invalid_auth
|
||||||
|
) -> None:
|
||||||
|
"""Test that it throws ConfigEntryAuthFailed when authentication fails."""
|
||||||
|
await setup_integration()
|
||||||
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||||
|
assert entry.state == ConfigEntryState.SETUP_ERROR
|
||||||
|
assert not hass.data.get(DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_info(
|
||||||
|
hass: HomeAssistant, setup_integration: ComponentSetup, connection
|
||||||
|
) -> None:
|
||||||
|
"""Test device info."""
|
||||||
|
await setup_integration()
|
||||||
|
entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
device = device_registry.async_get_device({(DOMAIN, entry.entry_id)})
|
||||||
|
|
||||||
|
assert device.configuration_url == "http://127.0.0.1:8668"
|
||||||
|
assert device.identifiers == {(DOMAIN, entry.entry_id)}
|
||||||
|
assert device.manufacturer == DEFAULT_NAME
|
||||||
|
assert device.name == "Mock Title"
|
||||||
|
assert device.sw_version == "10.0.0.34882"
|
33
tests/components/lidarr/test_sensor.py
Normal file
33
tests/components/lidarr/test_sensor.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""The tests for Lidarr sensor platform."""
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import CONF_STATE_CLASS, SensorStateClass
|
||||||
|
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .conftest import ComponentSetup
|
||||||
|
|
||||||
|
|
||||||
|
async def test_sensors(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
setup_integration: ComponentSetup,
|
||||||
|
entity_registry_enabled_by_default: AsyncMock,
|
||||||
|
connection,
|
||||||
|
):
|
||||||
|
"""Test for successfully setting up the Lidarr platform."""
|
||||||
|
await setup_integration()
|
||||||
|
|
||||||
|
state = hass.states.get("sensor.mock_title_disk_space")
|
||||||
|
assert state.state == "0.93"
|
||||||
|
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "GB"
|
||||||
|
state = hass.states.get("sensor.mock_title_queue")
|
||||||
|
assert state.state == "2"
|
||||||
|
assert state.attributes.get("string") == "stopped"
|
||||||
|
assert state.attributes.get("string2") == "downloading"
|
||||||
|
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Albums"
|
||||||
|
assert state.attributes.get(CONF_STATE_CLASS) == SensorStateClass.TOTAL
|
||||||
|
state = hass.states.get("sensor.mock_title_wanted")
|
||||||
|
assert state.state == "1"
|
||||||
|
assert state.attributes.get("test") == "test"
|
||||||
|
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Albums"
|
||||||
|
assert state.attributes.get(CONF_STATE_CLASS) == SensorStateClass.TOTAL
|
Loading…
x
Reference in New Issue
Block a user