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/pjlink/media_player.py
homeassistant/components/plaato/*
homeassistant/components/plex/__init__.py
homeassistant/components/plex/media_player.py
homeassistant/components/plex/sensor.py
homeassistant/components/plex/server.py
homeassistant/components/plugwise/*
homeassistant/components/plum_lightpad/*
homeassistant/components/pocketcasts/sensor.py

View File

@ -333,6 +333,7 @@ class PlexMediaPlayer(MediaPlayerDevice):
def force_idle(self):
"""Force client to idle."""
self._player_state = STATE_IDLE
self._state = STATE_IDLE
self.session = None
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."""
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 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},
}
from .const import DEFAULT_DATA, MOCK_SERVERS, MOCK_USERS
class MockResource:
@ -64,10 +47,11 @@ class MockPlexAccount:
class MockPlexSystemAccount:
"""Mock a PlexSystemAccount instance."""
def __init__(self):
def __init__(self, index):
"""Initialize the object."""
self.name = "Dummy"
self.accountID = 1
# Start accountIDs at 1 to set proper owner.
self.name = list(MOCK_USERS)[index]
self.accountID = index + 1
class MockPlexServer:
@ -76,68 +60,179 @@ class MockPlexServer:
def __init__(
self,
index=0,
ssl=True,
load_users=True,
num_users=len(MOCK_MONITORED_USERS),
ignore_new_users=False,
config_entry=None,
num_users=len(MOCK_USERS),
session_type="video",
):
"""Initialize the object."""
host = MOCK_SERVERS[index][CONF_HOST]
port = MOCK_SERVERS[index][CONF_PORT]
self.friendlyName = MOCK_SERVERS[index][ # pylint: disable=invalid-name
CONF_SERVER
if config_entry:
self._data = config_entry.data
else:
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
]
prefix = "https" if ssl else "http"
self._baseurl = f"{prefix}://{host}:{port}"
self._systemAccount = MockPlexSystemAccount()
self._ignore_new_users = ignore_new_users
self._load_users = load_users
self._num_users = num_users
def clear_clients(self):
"""Clear all active PlexClients."""
self._clients = []
def clear_sessions(self):
"""Clear all active PlexSessions."""
self._sessions = []
def clients(self):
"""Mock the clients method."""
return self._clients
def sessions(self):
"""Mock the sessions method."""
return self._sessions
def systemAccounts(self):
"""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
def accounts(self):
"""Mock the accounts property."""
return set(["a", "b", "c"])
@property
def owner(self):
"""Mock the owner property."""
return "a"
@property
def url_in_use(self):
"""Return URL used by PlexServer."""
return self._baseurl
return set(MOCK_USERS)
@property
def version(self):
"""Mock version of PlexServer."""
return "1.0"
@property
def option_monitored_users(self):
"""Mock loaded config option for monitored users."""
userdict = dict(itertools.islice(MOCK_MONITORED_USERS.items(), self._num_users))
return userdict if self._load_users else {}
class MockPlexClient:
"""Mock a PlexClient instance."""
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
def option_ignore_new_shared_users(self):
"""Mock loaded config option for ignoring new users."""
return self._ignore_new_users
def device(self):
"""Mock the device attribute."""
return "DEVICE"
@property
def option_show_all_controls(self):
"""Mock loaded config option for showing all controls."""
return False
def platform(self):
"""Mock the platform attribute."""
return "PLATFORM"
@property
def option_use_episode_art(self):
"""Mock loaded config option for using episode art."""
return False
def product(self):
"""Mock the product attribute."""
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."""
import copy
from unittest.mock import patch
import asynctest
from asynctest import patch
import plexapi.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.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.helpers.dispatcher import async_dispatcher_send
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
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):
"""Test when provided credentials are rejected."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch(
"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"
):
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):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": "import"},
data={
CONF_TOKEN: MOCK_TOKEN,
@ -82,16 +73,10 @@ async def test_import_success(hass):
assert result["type"] == "create_entry"
assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== mock_plex_server.machineIdentifier
)
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
assert result["data"][CONF_SERVER] == mock_plex_server.friendlyName
assert result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
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
):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": "import"},
data={
CONF_TOKEN: MOCK_TOKEN,
@ -116,14 +101,14 @@ async def test_unknown_exception(hass):
"""Test when an unknown exception is encountered."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
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"
), 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"])
assert result["type"] == "external"
@ -141,14 +126,14 @@ async def test_no_servers_found(hass):
await async_setup_component(hass, "http", {"http": {}})
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch(
"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
):
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": {}})
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch("plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount()), patch(
"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
):
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"])
assert result["type"] == "create_entry"
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 (
result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== mock_plex_server.machineIdentifier
result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
)
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
assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
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": {}})
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
), patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexauth.PlexAuth.initiate_auth"
), asynctest.patch(
), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
):
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"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER]
},
result["flow_id"], user_input={CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER]},
)
assert result["type"] == "create_entry"
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 (
result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== mock_plex_server.machineIdentifier
result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
)
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
assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
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": {}})
MockConfigEntry(
domain=config_flow.DOMAIN,
domain=DOMAIN,
data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][
config_flow.CONF_SERVER_IDENTIFIER
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][CONF_SERVER_IDENTIFIER],
CONF_SERVER: MOCK_SERVERS[1][CONF_SERVER],
},
).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch(
"plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
), patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexauth.PlexAuth.initiate_auth"
), asynctest.patch(
), patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
):
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"])
assert result["type"] == "create_entry"
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 (
result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== mock_plex_server.machineIdentifier
result["data"][CONF_SERVER_IDENTIFIER] == mock_plex_server.machineIdentifier
)
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
assert result["data"][PLEX_SERVER_CONFIG][CONF_URL] == mock_plex_server._baseurl
assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
async def test_already_configured(hass):
@ -313,23 +277,19 @@ async def test_already_configured(hass):
mock_plex_server = MockPlexServer()
MockConfigEntry(
domain=config_flow.DOMAIN,
domain=DOMAIN,
data={
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER],
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][
config_flow.CONF_SERVER_IDENTIFIER
],
CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER],
CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][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)
with patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
):
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"plexauth.PlexAuth.initiate_auth"
), patch("plexauth.PlexAuth.token", return_value=MOCK_TOKEN):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": "import"},
data={
CONF_TOKEN: MOCK_TOKEN,
@ -346,34 +306,30 @@ async def test_all_available_servers_configured(hass):
await async_setup_component(hass, "http", {"http": {}})
MockConfigEntry(
domain=config_flow.DOMAIN,
domain=DOMAIN,
data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][
config_flow.CONF_SERVER_IDENTIFIER
],
config_flow.CONF_SERVER: MOCK_SERVERS[0][config_flow.CONF_SERVER],
CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][CONF_SERVER_IDENTIFIER],
CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER],
},
).add_to_hass(hass)
MockConfigEntry(
domain=config_flow.DOMAIN,
domain=DOMAIN,
data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][
config_flow.CONF_SERVER_IDENTIFIER
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][CONF_SERVER_IDENTIFIER],
CONF_SERVER: MOCK_SERVERS[1][CONF_SERVER],
},
).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
with patch(
"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
):
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):
"""Test config options flow selection."""
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}
}
mock_plex_server = MockPlexServer()
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVER_ID},
domain=DOMAIN,
data=DEFAULT_DATA,
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(
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["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),
CONF_USE_EPISODE_ART: True,
CONF_IGNORE_NEW_SHARED_USERS: True,
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: {
MP_DOMAIN: {
CONF_USE_EPISODE_ART: True,
CONF_IGNORE_NEW_SHARED_USERS: True,
CONF_MONITORED_USERS: {
user: {"enabled": True} for user in mock_plex_server.accounts
},
}
}
async def test_option_flow_loading_saved_users(hass):
"""Test config options flow selection when loading existing user config."""
async def test_option_flow_new_users_available(hass, caplog):
"""Test config options multiselect defaults when new Plex users are seen."""
mock_plex_server = MockPlexServer(load_users=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}
}
OPTIONS_OWNER_ONLY = copy.deepcopy(DEFAULT_OPTIONS)
OPTIONS_OWNER_ONLY[MP_DOMAIN][CONF_MONITORED_USERS] = {"Owner": {"enabled": True}}
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVER_ID},
options=DEFAULT_OPTIONS,
domain=DOMAIN,
data=DEFAULT_DATA,
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(
entry.entry_id, context={"source": "test"}, data=None
)
assert result["type"] == "form"
assert result["step_id"] == "plex_mp_settings"
multiselect_defaults = result["data_schema"].schema["monitored_users"].options
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_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
},
}
}
assert "[Owner]" in multiselect_defaults["Owner"]
for user in new_users:
assert "[New]" in multiselect_defaults[user]
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": {}})
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
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
):
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": {}})
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
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
):
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(
"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
):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": "import"},
data={CONF_TOKEN: MOCK_TOKEN},
DOMAIN, context={"source": "import"}, data={CONF_TOKEN: MOCK_TOKEN},
)
assert result["type"] == "abort"
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"