mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Use server name as entry title in Jellyfin (#79965)
This commit is contained in:
parent
ef719cf7ef
commit
84acb416b8
@ -20,17 +20,17 @@ from .const import CLIENT_VERSION, USER_AGENT, USER_APP_NAME
|
||||
|
||||
async def validate_input(
|
||||
hass: HomeAssistant, user_input: dict[str, Any], client: JellyfinClient
|
||||
) -> str:
|
||||
) -> tuple[str, dict[str, Any]]:
|
||||
"""Validate that the provided url and credentials can be used to connect."""
|
||||
url = user_input[CONF_URL]
|
||||
username = user_input[CONF_USERNAME]
|
||||
password = user_input[CONF_PASSWORD]
|
||||
|
||||
userid = await hass.async_add_executor_job(
|
||||
user_id, connect_result = await hass.async_add_executor_job(
|
||||
_connect, client, url, username, password
|
||||
)
|
||||
|
||||
return userid
|
||||
return (user_id, connect_result)
|
||||
|
||||
|
||||
def create_client(device_id: str, device_name: str | None = None) -> JellyfinClient:
|
||||
@ -47,21 +47,30 @@ def create_client(device_id: str, device_name: str | None = None) -> JellyfinCli
|
||||
return client
|
||||
|
||||
|
||||
def _connect(client: JellyfinClient, url: str, username: str, password: str) -> str:
|
||||
def _connect(
|
||||
client: JellyfinClient, url: str, username: str, password: str
|
||||
) -> tuple[str, dict[str, Any]]:
|
||||
"""Connect to the Jellyfin server and assert that the user can login."""
|
||||
client.config.data["auth.ssl"] = url.startswith("https")
|
||||
|
||||
_connect_to_address(client.auth, url)
|
||||
connect_result = _connect_to_address(client.auth, url)
|
||||
|
||||
_login(client.auth, url, username, password)
|
||||
return _get_id(client.jellyfin)
|
||||
|
||||
return (_get_user_id(client.jellyfin), connect_result)
|
||||
|
||||
|
||||
def _connect_to_address(connection_manager: ConnectionManager, url: str) -> None:
|
||||
def _connect_to_address(
|
||||
connection_manager: ConnectionManager, url: str
|
||||
) -> dict[str, Any]:
|
||||
"""Connect to the Jellyfin server."""
|
||||
state = connection_manager.connect_to_address(url)
|
||||
if state["State"] != CONNECTION_STATE["ServerSignIn"]:
|
||||
result: dict[str, Any] = connection_manager.connect_to_address(url)
|
||||
|
||||
if result["State"] != CONNECTION_STATE["ServerSignIn"]:
|
||||
raise CannotConnect
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _login(
|
||||
connection_manager: ConnectionManager,
|
||||
@ -76,7 +85,7 @@ def _login(
|
||||
raise InvalidAuth
|
||||
|
||||
|
||||
def _get_id(api: API) -> str:
|
||||
def _get_user_id(api: API) -> str:
|
||||
"""Set the unique userid from a Jellyfin server."""
|
||||
settings: dict[str, Any] = api.get_user_settings()
|
||||
userid: str = settings["Id"]
|
||||
|
@ -54,7 +54,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
||||
client = create_client(device_id=self.client_device_id)
|
||||
try:
|
||||
userid = await validate_input(self.hass, user_input, client)
|
||||
user_id, connect_result = await validate_input(
|
||||
self.hass, user_input, client
|
||||
)
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
except InvalidAuth:
|
||||
@ -63,11 +65,18 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
errors["base"] = "unknown"
|
||||
_LOGGER.exception(ex)
|
||||
else:
|
||||
await self.async_set_unique_id(userid)
|
||||
entry_title = user_input[CONF_URL]
|
||||
|
||||
server_info: dict[str, Any] = connect_result["Servers"][0]
|
||||
|
||||
if server_name := server_info.get("Name"):
|
||||
entry_title = server_name
|
||||
|
||||
await self.async_set_unique_id(user_id)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_URL],
|
||||
title=entry_title,
|
||||
data={CONF_CLIENT_DEVICE_ID: self.client_device_id, **user_input},
|
||||
)
|
||||
|
||||
|
@ -1 +1,17 @@
|
||||
"""Tests for the jellyfin integration."""
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import load_fixture
|
||||
|
||||
|
||||
def load_json_fixture(filename: str) -> Any:
|
||||
"""Load JSON fixture on-demand."""
|
||||
return json.loads(load_fixture(f"jellyfin/{filename}"))
|
||||
|
||||
|
||||
async def async_load_json_fixture(hass: HomeAssistant, filename: str) -> Any:
|
||||
"""Load JSON fixture on-demand asynchronously."""
|
||||
return await hass.async_add_executor_job(load_json_fixture, filename)
|
||||
|
@ -10,11 +10,7 @@ from jellyfin_apiclient_python.configuration import Config
|
||||
from jellyfin_apiclient_python.connection_manager import ConnectionManager
|
||||
import pytest
|
||||
|
||||
from .const import (
|
||||
MOCK_SUCCESFUL_CONNECTION_STATE,
|
||||
MOCK_SUCCESFUL_LOGIN_RESPONSE,
|
||||
MOCK_USER_SETTINGS,
|
||||
)
|
||||
from . import load_json_fixture
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -40,8 +36,10 @@ def mock_client_device_id() -> Generator[None, MagicMock, None]:
|
||||
def mock_auth() -> MagicMock:
|
||||
"""Return a mocked ConnectionManager."""
|
||||
jf_auth = create_autospec(ConnectionManager)
|
||||
jf_auth.connect_to_address.return_value = MOCK_SUCCESFUL_CONNECTION_STATE
|
||||
jf_auth.login.return_value = MOCK_SUCCESFUL_LOGIN_RESPONSE
|
||||
jf_auth.connect_to_address.return_value = load_json_fixture(
|
||||
"auth-connect-address.json"
|
||||
)
|
||||
jf_auth.login.return_value = load_json_fixture("auth-login.json")
|
||||
|
||||
return jf_auth
|
||||
|
||||
@ -50,7 +48,7 @@ def mock_auth() -> MagicMock:
|
||||
def mock_api() -> MagicMock:
|
||||
"""Return a mocked API."""
|
||||
jf_api = create_autospec(API)
|
||||
jf_api.get_user_settings.return_value = MOCK_USER_SETTINGS
|
||||
jf_api.get_user_settings.return_value = load_json_fixture("get-user-settings.json")
|
||||
|
||||
return jf_api
|
||||
|
||||
|
@ -2,16 +2,6 @@
|
||||
|
||||
from typing import Final
|
||||
|
||||
from jellyfin_apiclient_python.connection_manager import CONNECTION_STATE
|
||||
|
||||
TEST_URL: Final = "https://example.com"
|
||||
TEST_USERNAME: Final = "test-username"
|
||||
TEST_PASSWORD: Final = "test-password"
|
||||
|
||||
MOCK_SUCCESFUL_CONNECTION_STATE: Final = {"State": CONNECTION_STATE["ServerSignIn"]}
|
||||
MOCK_SUCCESFUL_LOGIN_RESPONSE: Final = {"AccessToken": "Test"}
|
||||
|
||||
MOCK_UNSUCCESFUL_CONNECTION_STATE: Final = {"State": CONNECTION_STATE["Unavailable"]}
|
||||
MOCK_UNSUCCESFUL_LOGIN_RESPONSE: Final = {""}
|
||||
|
||||
MOCK_USER_SETTINGS: Final = {"Id": "123"}
|
||||
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"State": 0
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"State": 2,
|
||||
"Servers": [{ "Id": "SERVER-UUID", "Name": "JELLYFIN-SERVER" }]
|
||||
}
|
@ -0,0 +1 @@
|
||||
{}
|
1844
tests/components/jellyfin/fixtures/auth-login.json
Normal file
1844
tests/components/jellyfin/fixtures/auth-login.json
Normal file
File diff suppressed because it is too large
Load Diff
19
tests/components/jellyfin/fixtures/get-user-settings.json
Normal file
19
tests/components/jellyfin/fixtures/get-user-settings.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Id": "string",
|
||||
"ViewType": "string",
|
||||
"SortBy": "string",
|
||||
"IndexBy": "string",
|
||||
"RememberIndexing": true,
|
||||
"PrimaryImageHeight": 0,
|
||||
"PrimaryImageWidth": 0,
|
||||
"CustomPrefs": {
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"ScrollDirection": "Horizontal",
|
||||
"ShowBackdrop": true,
|
||||
"RememberSorting": true,
|
||||
"SortOrder": "Ascending",
|
||||
"ShowSidebar": true,
|
||||
"Client": "emby"
|
||||
}
|
@ -6,14 +6,8 @@ from homeassistant.components.jellyfin.const import CONF_CLIENT_DEVICE_ID, DOMAI
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import (
|
||||
MOCK_SUCCESFUL_LOGIN_RESPONSE,
|
||||
MOCK_UNSUCCESFUL_CONNECTION_STATE,
|
||||
MOCK_UNSUCCESFUL_LOGIN_RESPONSE,
|
||||
TEST_PASSWORD,
|
||||
TEST_URL,
|
||||
TEST_USERNAME,
|
||||
)
|
||||
from . import async_load_json_fixture
|
||||
from .const import TEST_PASSWORD, TEST_URL, TEST_USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -55,7 +49,7 @@ async def test_form(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2["type"] == "create_entry"
|
||||
assert result2["title"] == TEST_URL
|
||||
assert result2["title"] == "JELLYFIN-SERVER"
|
||||
assert result2["data"] == {
|
||||
CONF_CLIENT_DEVICE_ID: "TEST-UUID",
|
||||
CONF_URL: TEST_URL,
|
||||
@ -82,7 +76,9 @@ async def test_form_cannot_connect(
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
mock_client.auth.connect_to_address.return_value = MOCK_UNSUCCESFUL_CONNECTION_STATE
|
||||
mock_client.auth.connect_to_address.return_value = await async_load_json_fixture(
|
||||
hass, "auth-connect-address-failure.json"
|
||||
)
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@ -113,7 +109,9 @@ async def test_form_invalid_auth(
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
mock_client.auth.login.return_value = MOCK_UNSUCCESFUL_LOGIN_RESPONSE
|
||||
mock_client.auth.login.return_value = await async_load_json_fixture(
|
||||
hass, "auth-login-failure.json"
|
||||
)
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@ -174,7 +172,9 @@ async def test_form_persists_device_id_on_error(
|
||||
assert result["errors"] == {}
|
||||
|
||||
mock_client_device_id.return_value = "TEST-UUID-1"
|
||||
mock_client.auth.login.return_value = MOCK_UNSUCCESFUL_LOGIN_RESPONSE
|
||||
mock_client.auth.login.return_value = await async_load_json_fixture(
|
||||
hass, "auth-login-failure.json"
|
||||
)
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@ -190,7 +190,9 @@ async def test_form_persists_device_id_on_error(
|
||||
assert result2["errors"] == {"base": "invalid_auth"}
|
||||
|
||||
mock_client_device_id.return_value = "TEST-UUID-2"
|
||||
mock_client.auth.login.return_value = MOCK_SUCCESFUL_LOGIN_RESPONSE
|
||||
mock_client.auth.login.return_value = await async_load_json_fixture(
|
||||
hass, "auth-login.json"
|
||||
)
|
||||
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user