Rewrite and add Plex tests (#32633)

* Rewrite and add Plex tests

* Remove unnecessary mocks

* Explicitly import constants for readability
This commit is contained in:
jjlawren 2020-03-11 11:37:02 -05:00 committed by GitHub
parent f7ddbc7e1e
commit 44c7743351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 788 additions and 289 deletions

View File

@ -542,10 +542,8 @@ omit =
homeassistant/components/pioneer/media_player.py homeassistant/components/pioneer/media_player.py
homeassistant/components/pjlink/media_player.py homeassistant/components/pjlink/media_player.py
homeassistant/components/plaato/* homeassistant/components/plaato/*
homeassistant/components/plex/__init__.py
homeassistant/components/plex/media_player.py homeassistant/components/plex/media_player.py
homeassistant/components/plex/sensor.py homeassistant/components/plex/sensor.py
homeassistant/components/plex/server.py
homeassistant/components/plugwise/* homeassistant/components/plugwise/*
homeassistant/components/plum_lightpad/* homeassistant/components/plum_lightpad/*
homeassistant/components/pocketcasts/sensor.py homeassistant/components/pocketcasts/sensor.py

View File

@ -333,6 +333,7 @@ class PlexMediaPlayer(MediaPlayerDevice):
def force_idle(self): def force_idle(self):
"""Force client to idle.""" """Force client to idle."""
self._player_state = STATE_IDLE
self._state = STATE_IDLE self._state = STATE_IDLE
self.session = None self.session = None
self._clear_media_details() self._clear_media_details()

View File

@ -0,0 +1,52 @@
"""Constants used by Plex tests."""
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.plex import const
from homeassistant.const import (
CONF_HOST,
CONF_PORT,
CONF_TOKEN,
CONF_URL,
CONF_VERIFY_SSL,
)
MOCK_SERVERS = [
{
CONF_HOST: "1.2.3.4",
CONF_PORT: 32400,
const.CONF_SERVER: "Plex Server 1",
const.CONF_SERVER_IDENTIFIER: "unique_id_123",
},
{
CONF_HOST: "4.3.2.1",
CONF_PORT: 32400,
const.CONF_SERVER: "Plex Server 2",
const.CONF_SERVER_IDENTIFIER: "unique_id_456",
},
]
MOCK_USERS = {
"Owner": {"enabled": True},
"b": {"enabled": True},
"c": {"enabled": True},
}
MOCK_TOKEN = "secret_token"
DEFAULT_DATA = {
const.CONF_SERVER: MOCK_SERVERS[0][const.CONF_SERVER],
const.PLEX_SERVER_CONFIG: {
const.CONF_CLIENT_IDENTIFIER: "00000000-0000-0000-0000-000000000000",
CONF_TOKEN: MOCK_TOKEN,
CONF_URL: f"https://{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}",
CONF_VERIFY_SSL: True,
},
const.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][const.CONF_SERVER_IDENTIFIER],
}
DEFAULT_OPTIONS = {
MP_DOMAIN: {
const.CONF_IGNORE_NEW_SHARED_USERS: False,
const.CONF_MONITORED_USERS: MOCK_USERS,
const.CONF_USE_EPISODE_ART: False,
}
}

View File

@ -1,29 +1,12 @@
"""Mock classes used in tests.""" """Mock classes used in tests."""
import itertools from homeassistant.components.plex.const import (
CONF_SERVER,
CONF_SERVER_IDENTIFIER,
PLEX_SERVER_CONFIG,
)
from homeassistant.const import CONF_URL
from homeassistant.components.plex.const import CONF_SERVER, CONF_SERVER_IDENTIFIER from .const import DEFAULT_DATA, MOCK_SERVERS, MOCK_USERS
from homeassistant.const import CONF_HOST, CONF_PORT
MOCK_SERVERS = [
{
CONF_HOST: "1.2.3.4",
CONF_PORT: 32400,
CONF_SERVER: "Plex Server 1",
CONF_SERVER_IDENTIFIER: "unique_id_123",
},
{
CONF_HOST: "4.3.2.1",
CONF_PORT: 32400,
CONF_SERVER: "Plex Server 2",
CONF_SERVER_IDENTIFIER: "unique_id_456",
},
]
MOCK_MONITORED_USERS = {
"a": {"enabled": True},
"b": {"enabled": False},
"c": {"enabled": True},
}
class MockResource: class MockResource:
@ -64,10 +47,11 @@ class MockPlexAccount:
class MockPlexSystemAccount: class MockPlexSystemAccount:
"""Mock a PlexSystemAccount instance.""" """Mock a PlexSystemAccount instance."""
def __init__(self): def __init__(self, index):
"""Initialize the object.""" """Initialize the object."""
self.name = "Dummy" # Start accountIDs at 1 to set proper owner.
self.accountID = 1 self.name = list(MOCK_USERS)[index]
self.accountID = index + 1
class MockPlexServer: class MockPlexServer:
@ -76,68 +60,179 @@ class MockPlexServer:
def __init__( def __init__(
self, self,
index=0, index=0,
ssl=True, config_entry=None,
load_users=True, num_users=len(MOCK_USERS),
num_users=len(MOCK_MONITORED_USERS), session_type="video",
ignore_new_users=False,
): ):
"""Initialize the object.""" """Initialize the object."""
host = MOCK_SERVERS[index][CONF_HOST] if config_entry:
port = MOCK_SERVERS[index][CONF_PORT] self._data = config_entry.data
self.friendlyName = MOCK_SERVERS[index][ # pylint: disable=invalid-name else:
CONF_SERVER self._data = DEFAULT_DATA
self._baseurl = self._data[PLEX_SERVER_CONFIG][CONF_URL]
self.friendlyName = self._data[CONF_SERVER]
self.machineIdentifier = self._data[CONF_SERVER_IDENTIFIER]
self._systemAccounts = list(map(MockPlexSystemAccount, range(num_users)))
self._clients = []
self._sessions = []
self.set_clients(num_users)
self.set_sessions(num_users, session_type)
def set_clients(self, num_clients):
"""Set up mock PlexClients for this PlexServer."""
self._clients = [MockPlexClient(self._baseurl, x) for x in range(num_clients)]
def set_sessions(self, num_sessions, session_type):
"""Set up mock PlexSessions for this PlexServer."""
self._sessions = [
MockPlexSession(self._clients[x], mediatype=session_type, index=x)
for x in range(num_sessions)
] ]
self.machineIdentifier = MOCK_SERVERS[index][ # pylint: disable=invalid-name
CONF_SERVER_IDENTIFIER def clear_clients(self):
] """Clear all active PlexClients."""
prefix = "https" if ssl else "http" self._clients = []
self._baseurl = f"{prefix}://{host}:{port}"
self._systemAccount = MockPlexSystemAccount() def clear_sessions(self):
self._ignore_new_users = ignore_new_users """Clear all active PlexSessions."""
self._load_users = load_users self._sessions = []
self._num_users = num_users
def clients(self):
"""Mock the clients method."""
return self._clients
def sessions(self):
"""Mock the sessions method."""
return self._sessions
def systemAccounts(self): def systemAccounts(self):
"""Mock the systemAccounts lookup method.""" """Mock the systemAccounts lookup method."""
return [self._systemAccount] return self._systemAccounts
def url(self, path, includeToken=False):
"""Mock method to generate a server URL."""
return f"{self._baseurl}{path}"
@property @property
def accounts(self): def accounts(self):
"""Mock the accounts property.""" """Mock the accounts property."""
return set(["a", "b", "c"]) return set(MOCK_USERS)
@property
def owner(self):
"""Mock the owner property."""
return "a"
@property
def url_in_use(self):
"""Return URL used by PlexServer."""
return self._baseurl
@property @property
def version(self): def version(self):
"""Mock version of PlexServer.""" """Mock version of PlexServer."""
return "1.0" return "1.0"
@property
def option_monitored_users(self): class MockPlexClient:
"""Mock loaded config option for monitored users.""" """Mock a PlexClient instance."""
userdict = dict(itertools.islice(MOCK_MONITORED_USERS.items(), self._num_users))
return userdict if self._load_users else {} def __init__(self, url, index=0):
"""Initialize the object."""
self.machineIdentifier = f"client-{index+1}"
self._baseurl = url
def url(self, key):
"""Mock the url method."""
return f"{self._baseurl}{key}"
@property @property
def option_ignore_new_shared_users(self): def device(self):
"""Mock loaded config option for ignoring new users.""" """Mock the device attribute."""
return self._ignore_new_users return "DEVICE"
@property @property
def option_show_all_controls(self): def platform(self):
"""Mock loaded config option for showing all controls.""" """Mock the platform attribute."""
return False return "PLATFORM"
@property @property
def option_use_episode_art(self): def product(self):
"""Mock loaded config option for using episode art.""" """Mock the product attribute."""
return False return "PRODUCT"
@property
def protocolCapabilities(self):
"""Mock the protocolCapabilities attribute."""
return ["player"]
@property
def state(self):
"""Mock the state attribute."""
return "playing"
@property
def title(self):
"""Mock the title attribute."""
return "TITLE"
@property
def version(self):
"""Mock the version attribute."""
return "1.0"
class MockPlexSession:
"""Mock a PlexServer.sessions() instance."""
def __init__(self, player, mediatype, index=0):
"""Initialize the object."""
self.TYPE = mediatype
self.usernames = [list(MOCK_USERS)[index]]
self.players = [player]
self._section = MockPlexLibrarySection()
@property
def duration(self):
"""Mock the duration attribute."""
return 10000000
@property
def ratingKey(self):
"""Mock the ratingKey attribute."""
return 123
def section(self):
"""Mock the section method."""
return self._section
@property
def summary(self):
"""Mock the summary attribute."""
return "SUMMARY"
@property
def thumbUrl(self):
"""Mock the thumbUrl attribute."""
return "http://1.2.3.4/thumb"
@property
def title(self):
"""Mock the title attribute."""
return "TITLE"
@property
def type(self):
"""Mock the type attribute."""
return "movie"
@property
def viewOffset(self):
"""Mock the viewOffset attribute."""
return 0
@property
def year(self):
"""Mock the year attribute."""
return 2020
class MockPlexLibrarySection:
"""Mock a Plex LibrarySection instance."""
def __init__(self, library="Movies"):
"""Initialize the object."""
self.title = library

View File

@ -1,55 +1,46 @@
"""Tests for Plex config flow.""" """Tests for Plex config flow."""
import copy import copy
from unittest.mock import patch
import asynctest from asynctest import patch
import plexapi.exceptions import plexapi.exceptions
import requests.exceptions import requests.exceptions
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.plex import config_flow from homeassistant.components.plex import config_flow
from homeassistant.components.plex.const import (
CONF_IGNORE_NEW_SHARED_USERS,
CONF_MONITORED_USERS,
CONF_SERVER,
CONF_SERVER_IDENTIFIER,
CONF_USE_EPISODE_ART,
DOMAIN,
PLEX_SERVER_CONFIG,
PLEX_UPDATE_PLATFORMS_SIGNAL,
SERVERS,
)
from homeassistant.config_entries import ENTRY_STATE_LOADED
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TOKEN, CONF_URL from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TOKEN, CONF_URL
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from .mock_classes import MOCK_SERVERS, MockPlexAccount, MockPlexServer from .const import DEFAULT_DATA, DEFAULT_OPTIONS, MOCK_SERVERS, MOCK_TOKEN
from .mock_classes import MockPlexAccount, MockPlexServer
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
MOCK_TOKEN = "secret_token"
MOCK_FILE_CONTENTS = {
f"{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}": {
"ssl": False,
"token": MOCK_TOKEN,
"verify": True,
}
}
DEFAULT_OPTIONS = {
config_flow.MP_DOMAIN: {
config_flow.CONF_USE_EPISODE_ART: False,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: False,
}
}
def init_config_flow(hass):
"""Init a configuration flow."""
flow = config_flow.PlexFlowHandler()
flow.hass = hass
return flow
async def test_bad_credentials(hass): async def test_bad_credentials(hass):
"""Test when provided credentials are rejected.""" """Test when provided credentials are rejected."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", side_effect=plexapi.exceptions.Unauthorized "plexapi.myplex.MyPlexAccount", side_effect=plexapi.exceptions.Unauthorized
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value="BAD TOKEN" "plexauth.PlexAuth.token", return_value="BAD TOKEN"
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -72,7 +63,7 @@ async def test_import_success(hass):
with patch("plexapi.server.PlexServer", return_value=mock_plex_server): with patch("plexapi.server.PlexServer", return_value=mock_plex_server):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, DOMAIN,
context={"source": "import"}, context={"source": "import"},
data={ data={
CONF_TOKEN: MOCK_TOKEN, CONF_TOKEN: MOCK_TOKEN,
@ -82,16 +73,10 @@ async def test_import_success(hass):
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == mock_plex_server.friendlyName assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName assert result["data"][CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
result["data"][config_flow.CONF_SERVER_IDENTIFIER] assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
== mock_plex_server.machineIdentifier assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
)
assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL]
== mock_plex_server.url_in_use
)
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
async def test_import_bad_hostname(hass): async def test_import_bad_hostname(hass):
@ -101,7 +86,7 @@ async def test_import_bad_hostname(hass):
"plexapi.server.PlexServer", side_effect=requests.exceptions.ConnectionError "plexapi.server.PlexServer", side_effect=requests.exceptions.ConnectionError
): ):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, DOMAIN,
context={"source": "import"}, context={"source": "import"},
data={ data={
CONF_TOKEN: MOCK_TOKEN, CONF_TOKEN: MOCK_TOKEN,
@ -116,14 +101,14 @@ async def test_unknown_exception(hass):
"""Test when an unknown exception is encountered.""" """Test when an unknown exception is encountered."""
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch("plexapi.myplex.MyPlexAccount", side_effect=Exception), asynctest.patch( with patch("plexapi.myplex.MyPlexAccount", side_effect=Exception), patch(
"plexauth.PlexAuth.initiate_auth" "plexauth.PlexAuth.initiate_auth"
), asynctest.patch("plexauth.PlexAuth.token", return_value="MOCK_TOKEN"): ), patch("plexauth.PlexAuth.token", return_value="MOCK_TOKEN"):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external" assert result["type"] == "external"
@ -141,14 +126,14 @@ async def test_no_servers_found(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=0) "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=0)
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -171,14 +156,14 @@ async def test_single_available_server(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch("plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount()), patch( with patch("plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount()), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server "plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -190,16 +175,12 @@ async def test_single_available_server(hass):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == mock_plex_server.friendlyName assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName assert result["data"][CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
== mock_plex_server.machineIdentifier
) )
assert ( assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
== mock_plex_server.url_in_use
)
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
async def test_multiple_servers_with_selection(hass): async def test_multiple_servers_with_selection(hass):
@ -210,18 +191,16 @@ async def test_multiple_servers_with_selection(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2) "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), patch( ), patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
"plexauth.PlexAuth.initiate_auth" "plexauth.PlexAuth.initiate_auth"
), asynctest.patch( ), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -235,23 +214,16 @@ async def test_multiple_servers_with_selection(hass):
assert result["step_id"] == "select_server" assert result["step_id"] == "select_server"
result = await hass.config_entries.flow.async_configure( result = await hass.config_entries.flow.async_configure(
result["flow_id"], result["flow_id"], user_input={CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER]},
user_input={
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER]
},
) )
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == mock_plex_server.friendlyName assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName assert result["data"][CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
== mock_plex_server.machineIdentifier
) )
assert ( assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
== mock_plex_server.url_in_use
)
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
async def test_adding_last_unconfigured_server(hass): async def test_adding_last_unconfigured_server(hass):
@ -262,28 +234,24 @@ async def test_adding_last_unconfigured_server(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][ CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][CONF_SERVER_IDENTIFIER],
config_flow.CONF_SERVER_IDENTIFIER CONF_SERVER: MOCK_SERVERS[1][CONF_SERVER],
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
}, },
).add_to_hass(hass) ).add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2) "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), patch( ), patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
"plexauth.PlexAuth.initiate_auth" "plexauth.PlexAuth.initiate_auth"
), asynctest.patch( ), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -295,16 +263,12 @@ async def test_adding_last_unconfigured_server(hass):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == mock_plex_server.friendlyName assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName assert result["data"][CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
== mock_plex_server.machineIdentifier
) )
assert ( assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
== mock_plex_server.url_in_use
)
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
async def test_already_configured(hass): async def test_already_configured(hass):
@ -313,23 +277,19 @@ async def test_already_configured(hass):
mock_plex_server = MockPlexServer() mock_plex_server = MockPlexServer()
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={ data={
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER], CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER],
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][ CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][CONF_SERVER_IDENTIFIER],
config_flow.CONF_SERVER_IDENTIFIER
],
}, },
unique_id=MOCK_SERVERS[0][config_flow.CONF_SERVER_IDENTIFIER], unique_id=MOCK_SERVERS[0][CONF_SERVER_IDENTIFIER],
).add_to_hass(hass) ).add_to_hass(hass)
with patch( with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server "plexauth.PlexAuth.initiate_auth"
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.token", return_value=MOCK_TOKEN):
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, DOMAIN,
context={"source": "import"}, context={"source": "import"},
data={ data={
CONF_TOKEN: MOCK_TOKEN, CONF_TOKEN: MOCK_TOKEN,
@ -346,34 +306,30 @@ async def test_all_available_servers_configured(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][ CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][CONF_SERVER_IDENTIFIER],
config_flow.CONF_SERVER_IDENTIFIER CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER],
],
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER],
}, },
).add_to_hass(hass) ).add_to_hass(hass)
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][ CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][CONF_SERVER_IDENTIFIER],
config_flow.CONF_SERVER_IDENTIFIER CONF_SERVER: MOCK_SERVERS[1][CONF_SERVER],
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
}, },
).add_to_hass(hass) ).add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2) "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -389,20 +345,26 @@ async def test_all_available_servers_configured(hass):
async def test_option_flow(hass): async def test_option_flow(hass):
"""Test config options flow selection.""" """Test config options flow selection."""
mock_plex_server = MockPlexServer()
mock_plex_server = MockPlexServer(load_users=False)
MOCK_SERVER_ID = MOCK_SERVERS[0][config_flow.CONF_SERVER_IDENTIFIER]
hass.data[config_flow.DOMAIN] = {
config_flow.SERVERS: {MOCK_SERVER_ID: mock_plex_server}
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVER_ID}, data=DEFAULT_DATA,
options=DEFAULT_OPTIONS, options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
) )
entry.add_to_hass(hass)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert mock_listen.called
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
result = await hass.config_entries.options.async_init( result = await hass.config_entries.options.async_init(
entry.entry_id, context={"source": "test"}, data=None entry.entry_id, context={"source": "test"}, data=None
@ -413,112 +375,69 @@ async def test_option_flow(hass):
result = await hass.config_entries.options.async_configure( result = await hass.config_entries.options.async_configure(
result["flow_id"], result["flow_id"],
user_input={ user_input={
config_flow.CONF_USE_EPISODE_ART: True, CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True, CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: list(mock_plex_server.accounts), CONF_MONITORED_USERS: list(mock_plex_server.accounts),
}, },
) )
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["data"] == { assert result["data"] == {
config_flow.MP_DOMAIN: { MP_DOMAIN: {
config_flow.CONF_USE_EPISODE_ART: True, CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True, CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: { CONF_MONITORED_USERS: {
user: {"enabled": True} for user in mock_plex_server.accounts user: {"enabled": True} for user in mock_plex_server.accounts
}, },
} }
} }
async def test_option_flow_loading_saved_users(hass): async def test_option_flow_new_users_available(hass, caplog):
"""Test config options flow selection when loading existing user config.""" """Test config options multiselect defaults when new Plex users are seen."""
mock_plex_server = MockPlexServer(load_users=True) OPTIONS_OWNER_ONLY = copy.deepcopy(DEFAULT_OPTIONS)
OPTIONS_OWNER_ONLY[MP_DOMAIN][CONF_MONITORED_USERS] = {"Owner": {"enabled": True}}
MOCK_SERVER_ID = MOCK_SERVERS[0][config_flow.CONF_SERVER_IDENTIFIER]
hass.data[config_flow.DOMAIN] = {
config_flow.SERVERS: {MOCK_SERVER_ID: mock_plex_server}
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, domain=DOMAIN,
data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVER_ID}, data=DEFAULT_DATA,
options=DEFAULT_OPTIONS, options=OPTIONS_OWNER_ONLY,
unique_id=DEFAULT_DATA["server_id"],
) )
entry.add_to_hass(hass)
mock_plex_server = MockPlexServer(config_entry=entry)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
server_id = mock_plex_server.machineIdentifier
async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
monitored_users = hass.data[DOMAIN][SERVERS][server_id].option_monitored_users
new_users = [x for x in mock_plex_server.accounts if x not in monitored_users]
assert len(monitored_users) == 1
assert len(new_users) == 2
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))
result = await hass.config_entries.options.async_init( result = await hass.config_entries.options.async_init(
entry.entry_id, context={"source": "test"}, data=None entry.entry_id, context={"source": "test"}, data=None
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "plex_mp_settings" assert result["step_id"] == "plex_mp_settings"
multiselect_defaults = result["data_schema"].schema["monitored_users"].options
result = await hass.config_entries.options.async_configure( assert "[Owner]" in multiselect_defaults["Owner"]
result["flow_id"], for user in new_users:
user_input={ assert "[New]" in multiselect_defaults[user]
config_flow.CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: list(mock_plex_server.accounts),
},
)
assert result["type"] == "create_entry"
assert result["data"] == {
config_flow.MP_DOMAIN: {
config_flow.CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: {
user: {"enabled": True} for user in mock_plex_server.accounts
},
}
}
async def test_option_flow_new_users_available(hass):
"""Test config options flow selection when new Plex accounts available."""
mock_plex_server = MockPlexServer(load_users=True, num_users=2)
MOCK_SERVER_ID = MOCK_SERVERS[0][config_flow.CONF_SERVER_IDENTIFIER]
hass.data[config_flow.DOMAIN] = {
config_flow.SERVERS: {MOCK_SERVER_ID: mock_plex_server}
}
OPTIONS_WITH_USERS = copy.deepcopy(DEFAULT_OPTIONS)
OPTIONS_WITH_USERS[config_flow.MP_DOMAIN][config_flow.CONF_MONITORED_USERS] = {
"a": {"enabled": True}
}
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVER_ID},
options=OPTIONS_WITH_USERS,
)
entry.add_to_hass(hass)
result = await hass.config_entries.options.async_init(
entry.entry_id, context={"source": "test"}, data=None
)
assert result["type"] == "form"
assert result["step_id"] == "plex_mp_settings"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
config_flow.CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: list(mock_plex_server.accounts),
},
)
assert result["type"] == "create_entry"
assert result["data"] == {
config_flow.MP_DOMAIN: {
config_flow.CONF_USE_EPISODE_ART: True,
config_flow.CONF_IGNORE_NEW_SHARED_USERS: True,
config_flow.CONF_MONITORED_USERS: {
user: {"enabled": True} for user in mock_plex_server.accounts
},
}
}
async def test_external_timed_out(hass): async def test_external_timed_out(hass):
@ -527,12 +446,12 @@ async def test_external_timed_out(hass):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( with patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=None "plexauth.PlexAuth.token", return_value=None
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -552,12 +471,12 @@ async def test_callback_view(hass, aiohttp_client):
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"} DOMAIN, context={"source": "user"}
) )
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( with patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"]) result = await hass.config_entries.flow.async_configure(result["flow_id"])
@ -575,13 +494,11 @@ async def test_multiple_servers_with_import(hass):
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2) "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), patch("plexauth.PlexAuth.initiate_auth"), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, DOMAIN, context={"source": "import"}, data={CONF_TOKEN: MOCK_TOKEN},
context={"source": "import"},
data={CONF_TOKEN: MOCK_TOKEN},
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "non-interactive" assert result["reason"] == "non-interactive"

View File

@ -0,0 +1,302 @@
"""Tests for Plex setup."""
import copy
from datetime import timedelta
from asynctest import patch
import plexapi
import requests
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
import homeassistant.components.plex.const as const
from homeassistant.config_entries import (
ENTRY_STATE_LOADED,
ENTRY_STATE_NOT_LOADED,
ENTRY_STATE_SETUP_ERROR,
ENTRY_STATE_SETUP_RETRY,
)
from homeassistant.const import (
CONF_HOST,
CONF_PORT,
CONF_SSL,
CONF_TOKEN,
CONF_VERIFY_SSL,
)
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from .const import DEFAULT_DATA, DEFAULT_OPTIONS, MOCK_SERVERS, MOCK_TOKEN
from .mock_classes import MockPlexServer
from tests.common import MockConfigEntry, async_fire_time_changed
async def test_setup_with_config(hass):
"""Test setup component with config."""
config = {
const.DOMAIN: {
CONF_HOST: MOCK_SERVERS[0][CONF_HOST],
CONF_PORT: MOCK_SERVERS[0][CONF_PORT],
CONF_TOKEN: MOCK_TOKEN,
CONF_SSL: True,
CONF_VERIFY_SSL: True,
MP_DOMAIN: {
const.CONF_IGNORE_NEW_SHARED_USERS: False,
const.CONF_USE_EPISODE_ART: False,
},
},
}
mock_plex_server = MockPlexServer()
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
assert await async_setup_component(hass, const.DOMAIN, config) is True
await hass.async_block_till_done()
assert mock_listen.called
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
entry = hass.config_entries.async_entries(const.DOMAIN)[0]
assert entry.state == ENTRY_STATE_LOADED
server_id = mock_plex_server.machineIdentifier
loaded_server = hass.data[const.DOMAIN][const.SERVERS][server_id]
assert loaded_server.plex_server == mock_plex_server
assert server_id in hass.data[const.DOMAIN][const.DISPATCHERS]
assert server_id in hass.data[const.DOMAIN][const.WEBSOCKETS]
assert (
hass.data[const.DOMAIN][const.PLATFORMS_COMPLETED][server_id] == const.PLATFORMS
)
async def test_setup_with_config_entry(hass):
"""Test setup component with config."""
mock_plex_server = MockPlexServer()
entry = MockConfigEntry(
domain=const.DOMAIN,
data=DEFAULT_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert mock_listen.called
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
server_id = mock_plex_server.machineIdentifier
loaded_server = hass.data[const.DOMAIN][const.SERVERS][server_id]
assert loaded_server.plex_server == mock_plex_server
assert server_id in hass.data[const.DOMAIN][const.DISPATCHERS]
assert server_id in hass.data[const.DOMAIN][const.WEBSOCKETS]
assert (
hass.data[const.DOMAIN][const.PLATFORMS_COMPLETED][server_id] == const.PLATFORMS
)
async_dispatcher_send(hass, const.PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))
async_dispatcher_send(hass, const.PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
with patch.object(
mock_plex_server, "clients", side_effect=plexapi.exceptions.BadRequest
):
async_dispatcher_send(
hass, const.PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id)
)
await hass.async_block_till_done()
with patch.object(
mock_plex_server, "clients", side_effect=requests.exceptions.RequestException
):
async_dispatcher_send(
hass, const.PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id)
)
await hass.async_block_till_done()
async def test_set_config_entry_unique_id(hass):
"""Test updating missing unique_id from config entry."""
mock_plex_server = MockPlexServer()
entry = MockConfigEntry(
domain=const.DOMAIN, data=DEFAULT_DATA, options=DEFAULT_OPTIONS, unique_id=None,
)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert mock_listen.called
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
assert (
hass.config_entries.async_entries(const.DOMAIN)[0].unique_id
== mock_plex_server.machineIdentifier
)
async def test_setup_config_entry_with_error(hass):
"""Test setup component from config entry with errors."""
entry = MockConfigEntry(
domain=const.DOMAIN,
data=DEFAULT_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
with patch(
"homeassistant.components.plex.PlexServer.connect",
side_effect=requests.exceptions.ConnectionError,
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id) is False
await hass.async_block_till_done()
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_SETUP_RETRY
with patch(
"homeassistant.components.plex.PlexServer.connect",
side_effect=plexapi.exceptions.BadRequest,
):
next_update = dt_util.utcnow() + timedelta(seconds=30)
async_fire_time_changed(hass, next_update)
await hass.async_block_till_done()
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_SETUP_ERROR
async def test_setup_with_insecure_config_entry(hass):
"""Test setup component with config."""
mock_plex_server = MockPlexServer()
INSECURE_DATA = copy.deepcopy(DEFAULT_DATA)
INSECURE_DATA[const.PLEX_SERVER_CONFIG][CONF_VERIFY_SSL] = False
entry = MockConfigEntry(
domain=const.DOMAIN,
data=INSECURE_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert mock_listen.called
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
async def test_unload_config_entry(hass):
"""Test unloading a config entry."""
mock_plex_server = MockPlexServer()
entry = MockConfigEntry(
domain=const.DOMAIN,
data=DEFAULT_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
entry.add_to_hass(hass)
config_entries = hass.config_entries.async_entries(const.DOMAIN)
assert len(config_entries) == 1
assert entry is config_entries[0]
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
) as mock_listen:
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert mock_listen.called
assert entry.state == ENTRY_STATE_LOADED
server_id = mock_plex_server.machineIdentifier
loaded_server = hass.data[const.DOMAIN][const.SERVERS][server_id]
assert loaded_server.plex_server == mock_plex_server
assert server_id in hass.data[const.DOMAIN][const.DISPATCHERS]
assert server_id in hass.data[const.DOMAIN][const.WEBSOCKETS]
assert (
hass.data[const.DOMAIN][const.PLATFORMS_COMPLETED][server_id] == const.PLATFORMS
)
with patch("homeassistant.components.plex.PlexWebsocket.close") as mock_close:
await hass.config_entries.async_unload(entry.entry_id)
assert mock_close.called
assert entry.state == ENTRY_STATE_NOT_LOADED
assert server_id not in hass.data[const.DOMAIN][const.SERVERS]
assert server_id not in hass.data[const.DOMAIN][const.DISPATCHERS]
assert server_id not in hass.data[const.DOMAIN][const.WEBSOCKETS]
async def test_setup_with_photo_session(hass):
"""Test setup component with config."""
mock_plex_server = MockPlexServer(session_type="photo")
entry = MockConfigEntry(
domain=const.DOMAIN,
data=DEFAULT_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert len(hass.config_entries.async_entries(const.DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
server_id = mock_plex_server.machineIdentifier
async_dispatcher_send(hass, const.PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
media_player = hass.states.get("media_player.plex_product_title")
assert media_player.state == "idle"
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))

View File

@ -0,0 +1,134 @@
"""Tests for Plex server."""
import copy
from asynctest import patch
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.plex.const import (
CONF_IGNORE_NEW_SHARED_USERS,
CONF_MONITORED_USERS,
DOMAIN,
PLEX_UPDATE_PLATFORMS_SIGNAL,
SERVERS,
)
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import DEFAULT_DATA, DEFAULT_OPTIONS
from .mock_classes import MockPlexServer
from tests.common import MockConfigEntry
async def test_new_users_available(hass):
"""Test setting up when new users available on Plex server."""
MONITORED_USERS = {"Owner": {"enabled": True}}
OPTIONS_WITH_USERS = copy.deepcopy(DEFAULT_OPTIONS)
OPTIONS_WITH_USERS[MP_DOMAIN][CONF_MONITORED_USERS] = MONITORED_USERS
entry = MockConfigEntry(
domain=DOMAIN,
data=DEFAULT_DATA,
options=OPTIONS_WITH_USERS,
unique_id=DEFAULT_DATA["server_id"],
)
mock_plex_server = MockPlexServer(config_entry=entry)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
server_id = mock_plex_server.machineIdentifier
async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
monitored_users = hass.data[DOMAIN][SERVERS][server_id].option_monitored_users
ignored_users = [x for x in monitored_users if not monitored_users[x]["enabled"]]
assert len(monitored_users) == 1
assert len(ignored_users) == 0
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))
async def test_new_ignored_users_available(hass, caplog):
"""Test setting up when new users available on Plex server but are ignored."""
MONITORED_USERS = {"Owner": {"enabled": True}}
OPTIONS_WITH_USERS = copy.deepcopy(DEFAULT_OPTIONS)
OPTIONS_WITH_USERS[MP_DOMAIN][CONF_MONITORED_USERS] = MONITORED_USERS
OPTIONS_WITH_USERS[MP_DOMAIN][CONF_IGNORE_NEW_SHARED_USERS] = True
entry = MockConfigEntry(
domain=DOMAIN,
data=DEFAULT_DATA,
options=OPTIONS_WITH_USERS,
unique_id=DEFAULT_DATA["server_id"],
)
mock_plex_server = MockPlexServer(config_entry=entry)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
server_id = mock_plex_server.machineIdentifier
async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
monitored_users = hass.data[DOMAIN][SERVERS][server_id].option_monitored_users
ignored_users = [x for x in mock_plex_server.accounts if x not in monitored_users]
assert len(monitored_users) == 1
assert len(ignored_users) == 2
for ignored_user in ignored_users:
assert f"Ignoring Plex client owned by {ignored_user}" in caplog.text
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))
async def test_mark_sessions_idle(hass):
"""Test marking media_players as idle when sessions end."""
entry = MockConfigEntry(
domain=DOMAIN,
data=DEFAULT_DATA,
options=DEFAULT_OPTIONS,
unique_id=DEFAULT_DATA["server_id"],
)
mock_plex_server = MockPlexServer(config_entry=entry)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.PlexWebsocket.listen"
):
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
server_id = mock_plex_server.machineIdentifier
async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == str(len(mock_plex_server.accounts))
mock_plex_server.clear_clients()
mock_plex_server.clear_sessions()
async_dispatcher_send(hass, PLEX_UPDATE_PLATFORMS_SIGNAL.format(server_id))
await hass.async_block_till_done()
sensor = hass.states.get("sensor.plex_plex_server_1")
assert sensor.state == "0"