Merge pull request #28073 from home-assistant/rc

0.100.3
This commit is contained in:
Paulus Schoutsen 2019-10-21 16:28:27 -07:00 committed by GitHub
commit cd00d556d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 253 additions and 266 deletions

View File

@ -37,12 +37,14 @@ stages:
vmImage: 'ubuntu-latest' vmImage: 'ubuntu-latest'
container: $[ variables['PythonMain'] ] container: $[ variables['PythonMain'] ]
steps: steps:
- script: | - template: templates/azp-step-cache.yaml@azure
python -m venv venv parameters:
keyfile: 'requirements_test.txt | homeassistant/package_constraints.txt'
build: |
python -m venv venv
. venv/bin/activate . venv/bin/activate
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
displayName: 'Setup Env'
- script: | - script: |
. venv/bin/activate . venv/bin/activate
flake8 homeassistant tests script flake8 homeassistant tests script
@ -52,12 +54,14 @@ stages:
vmImage: 'ubuntu-latest' vmImage: 'ubuntu-latest'
container: $[ variables['PythonMain'] ] container: $[ variables['PythonMain'] ]
steps: steps:
- script: | - template: templates/azp-step-cache.yaml@azure
python -m venv venv parameters:
keyfile: 'homeassistant/package_constraints.txt'
build: |
python -m venv venv
. venv/bin/activate . venv/bin/activate
pip install -e . pip install -e .
displayName: 'Setup Env'
- script: | - script: |
. venv/bin/activate . venv/bin/activate
python -m script.hassfest validate python -m script.hassfest validate
@ -71,12 +75,14 @@ stages:
vmImage: 'ubuntu-latest' vmImage: 'ubuntu-latest'
container: $[ variables['PythonMain'] ] container: $[ variables['PythonMain'] ]
steps: steps:
- script: | - template: templates/azp-step-cache.yaml@azure
python -m venv venv parameters:
keyfile: 'requirements_test.txt | homeassistant/package_constraints.txt'
build: |
python -m venv venv
. venv/bin/activate . venv/bin/activate
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
displayName: 'Setup Env'
- script: | - script: |
. venv/bin/activate . venv/bin/activate
./script/check_format ./script/check_format
@ -100,7 +106,7 @@ stages:
steps: steps:
- template: templates/azp-step-cache.yaml@azure - template: templates/azp-step-cache.yaml@azure
parameters: parameters:
keyfile: 'requirements_test_all.txt, .cache, homeassistant/package_constraints.txt' keyfile: 'requirements_test_all.txt | homeassistant/package_constraints.txt'
build: | build: |
set -e set -e
python -m venv venv python -m venv venv
@ -111,6 +117,10 @@ stages:
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing. # This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
# Find offending deps with `pipdeptree -r -p typing` # Find offending deps with `pipdeptree -r -p typing`
pip uninstall -y typing pip uninstall -y typing
- script: |
. venv/bin/activate
pip install -e .
displayName: 'Install Home Assistant'
- script: | - script: |
set -e set -e
@ -140,7 +150,7 @@ stages:
steps: steps:
- template: templates/azp-step-cache.yaml@azure - template: templates/azp-step-cache.yaml@azure
parameters: parameters:
keyfile: 'requirements_all.txt, requirements_test.txt, .cache, homeassistant/package_constraints.txt' keyfile: 'requirements_all.txt | requirements_test.txt | homeassistant/package_constraints.txt'
build: | build: |
set -e set -e
python -m venv venv python -m venv venv
@ -149,6 +159,10 @@ stages:
pip install -U pip setuptools pip install -U pip setuptools
pip install -r requirements_all.txt -c homeassistant/package_constraints.txt pip install -r requirements_all.txt -c homeassistant/package_constraints.txt
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
- script: |
. venv/bin/activate
pip install -e .
displayName: 'Install Home Assistant'
- script: | - script: |
. venv/bin/activate . venv/bin/activate
pylint homeassistant pylint homeassistant

View File

@ -1,5 +1,8 @@
"""Support for MyQ-Enabled Garage Doors.""" """Support for MyQ-Enabled Garage Doors."""
import logging import logging
from pymyq import login
from pymyq.errors import MyQError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.cover import ( from homeassistant.components.cover import (
@ -30,35 +33,29 @@ MYQ_TO_HASS = {
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
vol.Required(CONF_TYPE): cv.string,
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
# This parameter is no longer used; keeping it to avoid a breaking change in
# a hotfix, but in a future main release, this should be removed:
vol.Optional(CONF_TYPE): cv.string,
} }
) )
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the platform.""" """Set up the platform."""
from pymyq import login
from pymyq.errors import MyQError, UnsupportedBrandError
websession = aiohttp_client.async_get_clientsession(hass) websession = aiohttp_client.async_get_clientsession(hass)
username = config[CONF_USERNAME] username = config[CONF_USERNAME]
password = config[CONF_PASSWORD] password = config[CONF_PASSWORD]
brand = config[CONF_TYPE]
try: try:
myq = await login(username, password, brand, websession) myq = await login(username, password, websession)
except UnsupportedBrandError:
_LOGGER.error("Unsupported brand: %s", brand)
return
except MyQError as err: except MyQError as err:
_LOGGER.error("There was an error while logging in: %s", err) _LOGGER.error("There was an error while logging in: %s", err)
return return
devices = await myq.get_devices() async_add_entities([MyQDevice(device) for device in myq.covers.values()], True)
async_add_entities([MyQDevice(device) for device in devices], True)
class MyQDevice(CoverDevice): class MyQDevice(CoverDevice):

View File

@ -3,7 +3,7 @@
"name": "Myq", "name": "Myq",
"documentation": "https://www.home-assistant.io/integrations/myq", "documentation": "https://www.home-assistant.io/integrations/myq",
"requirements": [ "requirements": [
"pymyq==1.2.1" "pymyq==2.0.0"
], ],
"dependencies": [], "dependencies": [],
"codeowners": [] "codeowners": []

View File

@ -89,9 +89,10 @@ class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
_LOGGER.error("Invalid credentials provided, config not created") _LOGGER.error("Invalid credentials provided, config not created")
errors["base"] = "faulty_credentials" errors["base"] = "faulty_credentials"
except (plexapi.exceptions.NotFound, requests.exceptions.ConnectionError): except (plexapi.exceptions.NotFound, requests.exceptions.ConnectionError):
_LOGGER.error( server_identifier = (
"Plex server could not be reached: %s", server_config[CONF_URL] server_config.get(CONF_URL) or plex_server.server_choice or "Unknown"
) )
_LOGGER.error("Plex server could not be reached: %s", server_identifier)
errors["base"] = "not_found" errors["base"] = "not_found"
except ServerNotSpecified as available_servers: except ServerNotSpecified as available_servers:

View File

@ -39,11 +39,12 @@ class PlexServer:
self._server_name = server_config.get(CONF_SERVER) self._server_name = server_config.get(CONF_SERVER)
self._verify_ssl = server_config.get(CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL) self._verify_ssl = server_config.get(CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL)
self.options = options self.options = options
self.server_choice = None
def connect(self): def connect(self):
"""Connect to a Plex server directly, obtaining direct URL if necessary.""" """Connect to a Plex server directly, obtaining direct URL if necessary."""
def _set_missing_url(): def _connect_with_token():
account = plexapi.myplex.MyPlexAccount(token=self._token) account = plexapi.myplex.MyPlexAccount(token=self._token)
available_servers = [ available_servers = [
(x.name, x.clientIdentifier) (x.name, x.clientIdentifier)
@ -56,13 +57,10 @@ class PlexServer:
if not self._server_name and len(available_servers) > 1: if not self._server_name and len(available_servers) > 1:
raise ServerNotSpecified(available_servers) raise ServerNotSpecified(available_servers)
server_choice = ( self.server_choice = (
self._server_name if self._server_name else available_servers[0][0] self._server_name if self._server_name else available_servers[0][0]
) )
connections = account.resource(server_choice).connections self._plex_server = account.resource(self.server_choice).connect()
local_url = [x.httpuri for x in connections if x.local]
remote_url = [x.uri for x in connections if not x.local]
self._url = local_url[0] if local_url else remote_url[0]
def _connect_with_url(): def _connect_with_url():
session = None session = None
@ -73,10 +71,10 @@ class PlexServer:
self._url, self._token, session self._url, self._token, session
) )
if self._token and not self._url: if self._url:
_set_missing_url() _connect_with_url()
else:
_connect_with_url() _connect_with_token()
def clients(self): def clients(self):
"""Pass through clients call to plexapi.""" """Pass through clients call to plexapi."""

View File

@ -1,7 +1,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 100 MINOR_VERSION = 100
PATCH_VERSION = "2" PATCH_VERSION = "3"
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 6, 0) REQUIRED_PYTHON_VER = (3, 6, 0)

View File

@ -1316,7 +1316,7 @@ pymonoprice==0.3
pymusiccast==0.1.6 pymusiccast==0.1.6
# homeassistant.components.myq # homeassistant.components.myq
pymyq==1.2.1 pymyq==2.0.0
# homeassistant.components.mysensors # homeassistant.components.mysensors
pymysensors==0.18.0 pymysensors==0.18.0

View File

@ -1,35 +1,75 @@
"""Mock classes used in tests.""" """Mock classes used in tests."""
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.components.plex.const import CONF_SERVER, CONF_SERVER_IDENTIFIER
MOCK_HOST_1 = "1.2.3.4" MOCK_SERVERS = [
MOCK_PORT_1 = 32400 {
MOCK_HOST_2 = "4.3.2.1" CONF_HOST: "1.2.3.4",
MOCK_PORT_2 = 32400 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",
},
]
class MockAvailableServer: # pylint: disable=too-few-public-methods class MockResource:
"""Mock avilable server objects.""" """Mock a PlexAccount resource."""
def __init__(self, name, client_id): def __init__(self, index):
"""Initialize the object.""" """Initialize the object."""
self.name = name self.name = MOCK_SERVERS[index][CONF_SERVER]
self.clientIdentifier = client_id # pylint: disable=invalid-name self.clientIdentifier = MOCK_SERVERS[index][ # pylint: disable=invalid-name
CONF_SERVER_IDENTIFIER
]
self.provides = ["server"] self.provides = ["server"]
self._mock_plex_server = MockPlexServer(index)
def connect(self):
"""Mock the resource connect method."""
return self._mock_plex_server
class MockConnection: # pylint: disable=too-few-public-methods class MockPlexAccount:
"""Mock a single account resource connection object.""" """Mock a PlexAccount instance."""
def __init__(self, ssl): def __init__(self, servers=1):
"""Initialize the object.""" """Initialize the object."""
self._resources = []
for index in range(servers):
self._resources.append(MockResource(index))
def resource(self, name):
"""Mock the PlexAccount resource lookup method."""
return [x for x in self._resources if x.name == name][0]
def resources(self):
"""Mock the PlexAccount resources listing method."""
return self._resources
class MockPlexServer:
"""Mock a PlexServer instance."""
def __init__(self, index=0, ssl=True):
"""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
]
self.machineIdentifier = MOCK_SERVERS[index][ # pylint: disable=invalid-name
CONF_SERVER_IDENTIFIER
]
prefix = "https" if ssl else "http" prefix = "https" if ssl else "http"
self.httpuri = f"{prefix}://{MOCK_HOST_1}:{MOCK_PORT_1}" self._baseurl = f"{prefix}://{host}:{port}"
self.uri = "{prefix}://{MOCK_HOST_2}:{MOCK_PORT_2}"
self.local = True
@property
class MockConnections: # pylint: disable=too-few-public-methods def url_in_use(self):
"""Mock a list of resource connections.""" """Return URL used by PlexServer."""
return self._baseurl
def __init__(self, ssl=False):
"""Initialize the object."""
self.connections = [MockConnection(ssl)]

View File

@ -1,28 +1,26 @@
"""Tests for Plex config flow.""" """Tests for Plex config flow."""
from unittest.mock import MagicMock, Mock, patch, PropertyMock from unittest.mock import patch
import asynctest import asynctest
import plexapi.exceptions import plexapi.exceptions
import requests.exceptions import requests.exceptions
from homeassistant.components.plex import config_flow from homeassistant.components.plex import config_flow
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TOKEN, CONF_URL from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SSL, CONF_TOKEN, CONF_URL
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from .mock_classes import MOCK_HOST_1, MOCK_PORT_1, MockAvailableServer, MockConnections from .mock_classes import MOCK_SERVERS, MockPlexAccount, MockPlexServer
MOCK_NAME_1 = "Plex Server 1"
MOCK_ID_1 = "unique_id_123"
MOCK_NAME_2 = "Plex Server 2"
MOCK_ID_2 = "unique_id_456"
MOCK_TOKEN = "secret_token" MOCK_TOKEN = "secret_token"
MOCK_FILE_CONTENTS = { MOCK_FILE_CONTENTS = {
f"{MOCK_HOST_1}:{MOCK_PORT_1}": {"ssl": False, "token": MOCK_TOKEN, "verify": True} f"{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}": {
"ssl": False,
"token": MOCK_TOKEN,
"verify": True,
}
} }
MOCK_SERVER_1 = MockAvailableServer(MOCK_NAME_1, MOCK_ID_1)
MOCK_SERVER_2 = MockAvailableServer(MOCK_NAME_2, MOCK_ID_2)
DEFAULT_OPTIONS = { DEFAULT_OPTIONS = {
config_flow.MP_DOMAIN: { config_flow.MP_DOMAIN: {
@ -41,25 +39,21 @@ def init_config_flow(hass):
async def test_bad_credentials(hass): async def test_bad_credentials(hass):
"""Test when provided credentials are rejected.""" """Test when provided credentials are rejected."""
mock_connections = MockConnections()
mm_plex_account = MagicMock()
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch("plexapi.myplex.MyPlexAccount", return_value=mm_plex_account), patch( result = await hass.config_entries.flow.async_init(
"plexapi.server.PlexServer", side_effect=plexapi.exceptions.Unauthorized config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
with patch(
"plexapi.myplex.MyPlexAccount", side_effect=plexapi.exceptions.Unauthorized
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
"plexauth.PlexAuth.token", return_value="BAD TOKEN" "plexauth.PlexAuth.token", return_value="BAD TOKEN"
): ):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, context={"source": "user"}
)
assert result["type"] == "form"
assert result["step_id"] == "start_website_auth"
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
@ -74,31 +68,32 @@ async def test_import_file_from_discovery(hass):
"""Test importing a legacy file during discovery.""" """Test importing a legacy file during discovery."""
file_host_and_port, file_config = list(MOCK_FILE_CONTENTS.items())[0] file_host_and_port, file_config = list(MOCK_FILE_CONTENTS.items())[0]
used_url = f"http://{file_host_and_port}" file_use_ssl = file_config[CONF_SSL]
file_prefix = "https" if file_use_ssl else "http"
used_url = f"{file_prefix}://{file_host_and_port}"
with patch("plexapi.server.PlexServer") as mock_plex_server, patch( mock_plex_server = MockPlexServer(ssl=file_use_ssl)
with patch("plexapi.server.PlexServer", return_value=mock_plex_server), patch(
"homeassistant.components.plex.config_flow.load_json", "homeassistant.components.plex.config_flow.load_json",
return_value=MOCK_FILE_CONTENTS, return_value=MOCK_FILE_CONTENTS,
): ):
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_ID_1
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_NAME_1
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=used_url)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
context={"source": "discovery"}, context={"source": "discovery"},
data={CONF_HOST: MOCK_HOST_1, CONF_PORT: MOCK_PORT_1}, data={
CONF_HOST: MOCK_SERVERS[0][CONF_HOST],
CONF_PORT: MOCK_SERVERS[0][CONF_PORT],
},
) )
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == MOCK_NAME_1 assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == MOCK_NAME_1 assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER_IDENTIFIER] == MOCK_ID_1 assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== mock_plex_server.machineIdentifier
)
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] == used_url assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] == used_url
assert ( assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN]
@ -112,7 +107,10 @@ async def test_discovery(hass):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
context={"source": "discovery"}, context={"source": "discovery"},
data={CONF_HOST: MOCK_HOST_1, CONF_PORT: MOCK_PORT_1}, data={
CONF_HOST: MOCK_SERVERS[0][CONF_HOST],
CONF_PORT: MOCK_SERVERS[0][CONF_PORT],
},
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "discovery_no_file" assert result["reason"] == "discovery_no_file"
@ -128,7 +126,10 @@ async def test_discovery_while_in_progress(hass):
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
context={"source": "discovery"}, context={"source": "discovery"},
data={CONF_HOST: MOCK_HOST_1, CONF_PORT: MOCK_PORT_1}, data={
CONF_HOST: MOCK_SERVERS[0][CONF_HOST],
CONF_PORT: MOCK_SERVERS[0][CONF_PORT],
},
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "already_configured" assert result["reason"] == "already_configured"
@ -137,42 +138,28 @@ async def test_discovery_while_in_progress(hass):
async def test_import_success(hass): async def test_import_success(hass):
"""Test a successful configuration import.""" """Test a successful configuration import."""
mock_connections = MockConnections(ssl=True) mock_plex_server = MockPlexServer()
mm_plex_account = MagicMock()
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch("plexapi.server.PlexServer") as mock_plex_server:
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_SERVER_1.clientIdentifier
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_SERVER_1.name
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=mock_connections.connections[0].httpuri)
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, config_flow.DOMAIN,
context={"source": "import"}, context={"source": "import"},
data={ data={
CONF_TOKEN: MOCK_TOKEN, CONF_TOKEN: MOCK_TOKEN,
CONF_URL: f"https://{MOCK_HOST_1}:{MOCK_PORT_1}", CONF_URL: f"https://{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}",
}, },
) )
assert result["type"] == "create_entry" assert result["type"] == "create_entry"
assert result["title"] == MOCK_SERVER_1.name assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == MOCK_SERVER_1.name assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== MOCK_SERVER_1.clientIdentifier == mock_plex_server.machineIdentifier
) )
assert ( assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL]
== mock_connections.connections[0].httpuri == mock_plex_server.url_in_use
) )
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
@ -188,7 +175,7 @@ async def test_import_bad_hostname(hass):
context={"source": "import"}, context={"source": "import"},
data={ data={
CONF_TOKEN: MOCK_TOKEN, CONF_TOKEN: MOCK_TOKEN,
CONF_URL: f"http://{MOCK_HOST_1}:{MOCK_PORT_1}", CONF_URL: f"http://{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}",
}, },
) )
assert result["type"] == "form" assert result["type"] == "form"
@ -205,19 +192,12 @@ async def test_unknown_exception(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mock_connections = MockConnections() result = await hass.config_entries.flow.async_configure(result["flow_id"])
mm_plex_account = MagicMock() assert result["type"] == "external"
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch("plexapi.myplex.MyPlexAccount", return_value=mm_plex_account), patch(
"plexapi.server.PlexServer", side_effect=Exception
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
"plexauth.PlexAuth.token", return_value="MOCK_TOKEN"
):
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
with patch("plexapi.myplex.MyPlexAccount", side_effect=Exception), asynctest.patch(
"plexauth.PlexAuth.initiate_auth"
), asynctest.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_done" assert result["type"] == "external_done"
@ -237,18 +217,15 @@ async def test_no_servers_found(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mm_plex_account = MagicMock() result = await hass.config_entries.flow.async_configure(result["flow_id"])
mm_plex_account.resources = Mock(return_value=[]) assert result["type"] == "external"
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=mm_plex_account "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=0)
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.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"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
@ -261,6 +238,8 @@ async def test_no_servers_found(hass):
async def test_single_available_server(hass): async def test_single_available_server(hass):
"""Test creating an entry with one server available.""" """Test creating an entry with one server available."""
mock_plex_server = MockPlexServer()
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(
@ -269,46 +248,28 @@ async def test_single_available_server(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mock_connections = MockConnections() result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
mm_plex_account = MagicMock() with patch("plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount()), patch(
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1]) "plexapi.server.PlexServer", return_value=mock_plex_server
mm_plex_account.resource = Mock(return_value=mock_connections) ), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
with patch("plexapi.myplex.MyPlexAccount", return_value=mm_plex_account), patch(
"plexapi.server.PlexServer"
) as mock_plex_server, asynctest.patch(
"plexauth.PlexAuth.initiate_auth"
), asynctest.patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_SERVER_1.clientIdentifier
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_SERVER_1.name
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=mock_connections.connections[0].httpuri)
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
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_SERVER_1.name assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == MOCK_SERVER_1.name assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== MOCK_SERVER_1.clientIdentifier == mock_plex_server.machineIdentifier
) )
assert ( assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL]
== mock_connections.connections[0].httpuri == mock_plex_server.url_in_use
) )
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
@ -316,6 +277,8 @@ async def test_single_available_server(hass):
async def test_multiple_servers_with_selection(hass): async def test_multiple_servers_with_selection(hass):
"""Test creating an entry with multiple servers available.""" """Test creating an entry with multiple servers available."""
mock_plex_server = MockPlexServer()
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(
@ -324,31 +287,18 @@ async def test_multiple_servers_with_selection(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mock_connections = MockConnections() result = await hass.config_entries.flow.async_configure(result["flow_id"])
mm_plex_account = MagicMock() assert result["type"] == "external"
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1, MOCK_SERVER_2])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch("plexapi.myplex.MyPlexAccount", return_value=mm_plex_account), patch( with patch(
"plexapi.server.PlexServer" "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
) as mock_plex_server, asynctest.patch( ), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
"plexauth.PlexAuth.initiate_auth" "plexauth.PlexAuth.initiate_auth"
), asynctest.patch( ), asynctest.patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_SERVER_1.clientIdentifier
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_SERVER_1.name
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=mock_connections.connections[0].httpuri)
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
@ -357,18 +307,21 @@ 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"], user_input={config_flow.CONF_SERVER: MOCK_SERVER_1.name} result["flow_id"],
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_SERVER_1.name assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == MOCK_SERVER_1.name assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== MOCK_SERVER_1.clientIdentifier == mock_plex_server.machineIdentifier
) )
assert ( assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL]
== mock_connections.connections[0].httpuri == mock_plex_server.url_in_use
) )
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
@ -376,13 +329,17 @@ async def test_multiple_servers_with_selection(hass):
async def test_adding_last_unconfigured_server(hass): async def test_adding_last_unconfigured_server(hass):
"""Test automatically adding last unconfigured server when multiple servers on account.""" """Test automatically adding last unconfigured server when multiple servers on account."""
mock_plex_server = MockPlexServer()
await async_setup_component(hass, "http", {"http": {}}) await async_setup_component(hass, "http", {"http": {}})
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=config_flow.DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_ID_2, config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][
config_flow.CONF_SERVER: MOCK_NAME_2, config_flow.CONF_SERVER_IDENTIFIER
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
}, },
).add_to_hass(hass) ).add_to_hass(hass)
@ -392,45 +349,32 @@ async def test_adding_last_unconfigured_server(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mock_connections = MockConnections() result = await hass.config_entries.flow.async_configure(result["flow_id"])
mm_plex_account = MagicMock() assert result["type"] == "external"
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1, MOCK_SERVER_2])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch("plexapi.myplex.MyPlexAccount", return_value=mm_plex_account), patch( with patch(
"plexapi.server.PlexServer" "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
) as mock_plex_server, asynctest.patch( ), patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
), asynctest.patch(
"plexauth.PlexAuth.initiate_auth" "plexauth.PlexAuth.initiate_auth"
), asynctest.patch( ), asynctest.patch(
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
): ):
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_SERVER_1.clientIdentifier
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_SERVER_1.name
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=mock_connections.connections[0].httpuri)
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
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_SERVER_1.name assert result["title"] == mock_plex_server.friendlyName
assert result["data"][config_flow.CONF_SERVER] == MOCK_SERVER_1.name assert result["data"][config_flow.CONF_SERVER] == mock_plex_server.friendlyName
assert ( assert (
result["data"][config_flow.CONF_SERVER_IDENTIFIER] result["data"][config_flow.CONF_SERVER_IDENTIFIER]
== MOCK_SERVER_1.clientIdentifier == mock_plex_server.machineIdentifier
) )
assert ( assert (
result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL] result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_URL]
== mock_connections.connections[0].httpuri == mock_plex_server.url_in_use
) )
assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN assert result["data"][config_flow.PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
@ -438,32 +382,28 @@ async def test_adding_last_unconfigured_server(hass):
async def test_already_configured(hass): async def test_already_configured(hass):
"""Test a duplicated successful flow.""" """Test a duplicated successful flow."""
mock_plex_server = MockPlexServer()
flow = init_config_flow(hass) flow = init_config_flow(hass)
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, data={config_flow.CONF_SERVER_IDENTIFIER: MOCK_ID_1} domain=config_flow.DOMAIN,
data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][
config_flow.CONF_SERVER_IDENTIFIER
]
},
).add_to_hass(hass) ).add_to_hass(hass)
mock_connections = MockConnections() with patch(
"plexapi.server.PlexServer", return_value=mock_plex_server
mm_plex_account = MagicMock() ), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1]) "plexauth.PlexAuth.token", return_value=MOCK_TOKEN
mm_plex_account.resource = Mock(return_value=mock_connections) ):
with patch("plexapi.server.PlexServer") as mock_plex_server, asynctest.patch(
"plexauth.PlexAuth.initiate_auth"
), asynctest.patch("plexauth.PlexAuth.token", return_value=MOCK_TOKEN):
type(mock_plex_server.return_value).machineIdentifier = PropertyMock(
return_value=MOCK_SERVER_1.clientIdentifier
)
type(mock_plex_server.return_value).friendlyName = PropertyMock(
return_value=MOCK_SERVER_1.name
)
type( # pylint: disable=protected-access
mock_plex_server.return_value
)._baseurl = PropertyMock(return_value=mock_connections.connections[0].httpuri)
result = await flow.async_step_import( result = await flow.async_step_import(
{CONF_TOKEN: MOCK_TOKEN, CONF_URL: f"http://{MOCK_HOST_1}:{MOCK_PORT_1}"} {
CONF_TOKEN: MOCK_TOKEN,
CONF_URL: f"http://{MOCK_SERVERS[0][CONF_HOST]}:{MOCK_SERVERS[0][CONF_PORT]}",
}
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "already_configured" assert result["reason"] == "already_configured"
@ -477,16 +417,20 @@ async def test_all_available_servers_configured(hass):
MockConfigEntry( MockConfigEntry(
domain=config_flow.DOMAIN, domain=config_flow.DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_ID_1, config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][
config_flow.CONF_SERVER: MOCK_NAME_1, config_flow.CONF_SERVER_IDENTIFIER
],
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=config_flow.DOMAIN,
data={ data={
config_flow.CONF_SERVER_IDENTIFIER: MOCK_ID_2, config_flow.CONF_SERVER_IDENTIFIER: MOCK_SERVERS[1][
config_flow.CONF_SERVER: MOCK_NAME_2, config_flow.CONF_SERVER_IDENTIFIER
],
config_flow.CONF_SERVER: MOCK_SERVERS[1][config_flow.CONF_SERVER],
}, },
).add_to_hass(hass) ).add_to_hass(hass)
@ -496,20 +440,14 @@ async def test_all_available_servers_configured(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
mock_connections = MockConnections() result = await hass.config_entries.flow.async_configure(result["flow_id"])
mm_plex_account = MagicMock() assert result["type"] == "external"
mm_plex_account.resources = Mock(return_value=[MOCK_SERVER_1, MOCK_SERVER_2])
mm_plex_account.resource = Mock(return_value=mock_connections)
with patch( with patch(
"plexapi.myplex.MyPlexAccount", return_value=mm_plex_account "plexapi.myplex.MyPlexAccount", return_value=MockPlexAccount(servers=2)
), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( ), asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.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"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
@ -557,13 +495,12 @@ async def test_external_timed_out(hass):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch(
"plexauth.PlexAuth.token", return_value=None "plexauth.PlexAuth.token", return_value=None
): ):
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
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_done" assert result["type"] == "external_done"
@ -583,12 +520,12 @@ async def test_callback_view(hass, aiohttp_client):
assert result["type"] == "form" assert result["type"] == "form"
assert result["step_id"] == "start_website_auth" assert result["step_id"] == "start_website_auth"
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] == "external"
with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.patch( with asynctest.patch("plexauth.PlexAuth.initiate_auth"), asynctest.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"])
assert result["type"] == "external"
client = await aiohttp_client(hass.http.app) client = await aiohttp_client(hass.http.app)
forward_url = f'{config_flow.AUTH_CALLBACK_PATH}?flow_id={result["flow_id"]}' forward_url = f'{config_flow.AUTH_CALLBACK_PATH}?flow_id={result["flow_id"]}'