mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 03:37:07 +00:00
Hass.io Add-on panel support for Ingress (#23185)
* Hass.io Add-on panel support for Ingress * Revert part of discovery startup handling * Add type * Fix tests * Add tests * Fix lint * Fix lint on test
This commit is contained in:
parent
6a7bd19a5a
commit
3e443d253c
@ -16,11 +16,12 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
from .auth import async_setup_auth
|
from .auth import async_setup_auth_view
|
||||||
from .discovery import async_setup_discovery
|
from .addon_panel import async_setup_addon_panel
|
||||||
|
from .discovery import async_setup_discovery_view
|
||||||
from .handler import HassIO, HassioAPIError
|
from .handler import HassIO, HassioAPIError
|
||||||
from .http import HassIOView
|
from .http import HassIOView
|
||||||
from .ingress import async_setup_ingress
|
from .ingress import async_setup_ingress_view
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -265,12 +266,15 @@ async def async_setup(hass, config):
|
|||||||
HASS_DOMAIN, service, async_handle_core_service)
|
HASS_DOMAIN, service, async_handle_core_service)
|
||||||
|
|
||||||
# Init discovery Hass.io feature
|
# Init discovery Hass.io feature
|
||||||
async_setup_discovery(hass, hassio, config)
|
async_setup_discovery_view(hass, hassio)
|
||||||
|
|
||||||
# Init auth Hass.io feature
|
# Init auth Hass.io feature
|
||||||
async_setup_auth(hass)
|
async_setup_auth_view(hass)
|
||||||
|
|
||||||
# Init ingress Hass.io feature
|
# Init ingress Hass.io feature
|
||||||
async_setup_ingress(hass, host)
|
async_setup_ingress_view(hass, host)
|
||||||
|
|
||||||
|
# Init add-on ingress panels
|
||||||
|
await async_setup_addon_panel(hass, hassio)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
93
homeassistant/components/hassio/addon_panel.py
Normal file
93
homeassistant/components/hassio/addon_panel.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
"""Implement the Ingress Panel feature for Hass.io Add-ons."""
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
from homeassistant.components.http import HomeAssistantView
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
from .const import ATTR_PANELS, ATTR_TITLE, ATTR_ICON, ATTR_ADMIN, ATTR_ENABLE
|
||||||
|
from .handler import HassioAPIError
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_addon_panel(hass: HomeAssistantType, hassio):
|
||||||
|
"""Add-on Ingress Panel setup."""
|
||||||
|
hassio_addon_panel = HassIOAddonPanel(hass, hassio)
|
||||||
|
hass.http.register_view(hassio_addon_panel)
|
||||||
|
|
||||||
|
# If panels are exists
|
||||||
|
panels = await hassio_addon_panel.get_panels()
|
||||||
|
if not panels:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Register available panels
|
||||||
|
jobs = []
|
||||||
|
for addon, data in panels.items():
|
||||||
|
if not data[ATTR_ENABLE]:
|
||||||
|
continue
|
||||||
|
jobs.append(_register_panel(hass, addon, data))
|
||||||
|
|
||||||
|
if jobs:
|
||||||
|
await asyncio.wait(jobs)
|
||||||
|
|
||||||
|
|
||||||
|
class HassIOAddonPanel(HomeAssistantView):
|
||||||
|
"""Hass.io view to handle base part."""
|
||||||
|
|
||||||
|
name = "api:hassio_push:panel"
|
||||||
|
url = "/api/hassio_push/panel/{addon}"
|
||||||
|
|
||||||
|
def __init__(self, hass, hassio):
|
||||||
|
"""Initialize WebView."""
|
||||||
|
self.hass = hass
|
||||||
|
self.hassio = hassio
|
||||||
|
|
||||||
|
async def post(self, request, addon):
|
||||||
|
"""Handle new add-on panel requests."""
|
||||||
|
panels = await self.get_panels()
|
||||||
|
|
||||||
|
# Panel exists for add-on slug
|
||||||
|
if addon not in panels or not panels[addon][ATTR_ENABLE]:
|
||||||
|
_LOGGER.error("Panel is not enable for %s", addon)
|
||||||
|
return web.Response(status=400)
|
||||||
|
data = panels[addon]
|
||||||
|
|
||||||
|
# Register panel
|
||||||
|
await _register_panel(self.hass, addon, data)
|
||||||
|
return web.Response()
|
||||||
|
|
||||||
|
async def delete(self, request, addon):
|
||||||
|
"""Handle remove add-on panel requests."""
|
||||||
|
# Currently not supported by backend / frontend
|
||||||
|
return web.Response()
|
||||||
|
|
||||||
|
async def get_panels(self):
|
||||||
|
"""Return panels add-on info data."""
|
||||||
|
try:
|
||||||
|
data = await self.hassio.get_ingress_panels()
|
||||||
|
return data[ATTR_PANELS]
|
||||||
|
except HassioAPIError as err:
|
||||||
|
_LOGGER.error("Can't read panel info: %s", err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _register_panel(hass, addon, data):
|
||||||
|
"""Init coroutine to register the panel.
|
||||||
|
|
||||||
|
Return coroutine.
|
||||||
|
"""
|
||||||
|
return hass.components.frontend.async_register_built_in_panel(
|
||||||
|
frontend_url_path=addon,
|
||||||
|
webcomponent_name='hassio-main',
|
||||||
|
sidebar_title=data[ATTR_TITLE],
|
||||||
|
sidebar_icon=data[ATTR_ICON],
|
||||||
|
js_url='/api/hassio/app/entrypoint.js',
|
||||||
|
embed_iframe=True,
|
||||||
|
require_admin=data[ATTR_ADMIN],
|
||||||
|
config={
|
||||||
|
"ingress": addon
|
||||||
|
}
|
||||||
|
)
|
@ -1,18 +1,19 @@
|
|||||||
"""Implement the auth feature from Hass.io for Add-ons."""
|
"""Implement the auth feature from Hass.io for Add-ons."""
|
||||||
from ipaddress import ip_address
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from ipaddress import ip_address
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp.web_exceptions import HTTPForbidden, HTTPNotFound
|
from aiohttp.web_exceptions import HTTPForbidden, HTTPNotFound
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.components.http import HomeAssistantView
|
from homeassistant.components.http import HomeAssistantView
|
||||||
from homeassistant.components.http.const import KEY_REAL_IP
|
from homeassistant.components.http.const import KEY_REAL_IP
|
||||||
from homeassistant.components.http.data_validator import RequestDataValidator
|
from homeassistant.components.http.data_validator import RequestDataValidator
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
from .const import ATTR_ADDON, ATTR_PASSWORD, ATTR_USERNAME
|
from .const import ATTR_ADDON, ATTR_PASSWORD, ATTR_USERNAME
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ SCHEMA_API_AUTH = vol.Schema({
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_setup_auth(hass):
|
def async_setup_auth_view(hass: HomeAssistantType):
|
||||||
"""Auth setup."""
|
"""Auth setup."""
|
||||||
hassio_auth = HassIOAuth(hass)
|
hassio_auth = HassIOAuth(hass)
|
||||||
hass.http.register_view(hassio_auth)
|
hass.http.register_view(hassio_auth)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Hass.io const variables."""
|
"""Hass.io const variables."""
|
||||||
|
|
||||||
|
ATTR_ADDONS = 'addons'
|
||||||
ATTR_DISCOVERY = 'discovery'
|
ATTR_DISCOVERY = 'discovery'
|
||||||
ATTR_ADDON = 'addon'
|
ATTR_ADDON = 'addon'
|
||||||
ATTR_NAME = 'name'
|
ATTR_NAME = 'name'
|
||||||
@ -8,6 +9,11 @@ ATTR_CONFIG = 'config'
|
|||||||
ATTR_UUID = 'uuid'
|
ATTR_UUID = 'uuid'
|
||||||
ATTR_USERNAME = 'username'
|
ATTR_USERNAME = 'username'
|
||||||
ATTR_PASSWORD = 'password'
|
ATTR_PASSWORD = 'password'
|
||||||
|
ATTR_PANELS = 'panels'
|
||||||
|
ATTR_ENABLE = 'enable'
|
||||||
|
ATTR_TITLE = 'title'
|
||||||
|
ATTR_ICON = 'icon'
|
||||||
|
ATTR_ADMIN = 'admin'
|
||||||
|
|
||||||
X_HASSIO = 'X-Hassio-Key'
|
X_HASSIO = 'X-Hassio-Key'
|
||||||
X_INGRESS_PATH = "X-Ingress-Path"
|
X_INGRESS_PATH = "X-Ingress-Path"
|
||||||
|
@ -5,9 +5,9 @@ import logging
|
|||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp.web_exceptions import HTTPServiceUnavailable
|
from aiohttp.web_exceptions import HTTPServiceUnavailable
|
||||||
|
|
||||||
from homeassistant.components.http import HomeAssistantView
|
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||||
from homeassistant.core import CoreState, callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.components.http import HomeAssistantView
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_ADDON, ATTR_CONFIG, ATTR_DISCOVERY, ATTR_NAME, ATTR_SERVICE,
|
ATTR_ADDON, ATTR_CONFIG, ATTR_DISCOVERY, ATTR_NAME, ATTR_SERVICE,
|
||||||
@ -18,12 +18,13 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_setup_discovery(hass, hassio, config):
|
def async_setup_discovery_view(hass: HomeAssistantView, hassio):
|
||||||
"""Discovery setup."""
|
"""Discovery setup."""
|
||||||
hassio_discovery = HassIODiscovery(hass, hassio, config)
|
hassio_discovery = HassIODiscovery(hass, hassio)
|
||||||
|
hass.http.register_view(hassio_discovery)
|
||||||
|
|
||||||
# Handle exists discovery messages
|
# Handle exists discovery messages
|
||||||
async def async_discovery_start_handler(event):
|
async def _async_discovery_start_handler(event):
|
||||||
"""Process all exists discovery on startup."""
|
"""Process all exists discovery on startup."""
|
||||||
try:
|
try:
|
||||||
data = await hassio.retrieve_discovery_messages()
|
data = await hassio.retrieve_discovery_messages()
|
||||||
@ -36,13 +37,8 @@ def async_setup_discovery(hass, hassio, config):
|
|||||||
if jobs:
|
if jobs:
|
||||||
await asyncio.wait(jobs)
|
await asyncio.wait(jobs)
|
||||||
|
|
||||||
if hass.state == CoreState.running:
|
hass.bus.async_listen_once(
|
||||||
hass.async_create_task(async_discovery_start_handler(None))
|
EVENT_HOMEASSISTANT_START, _async_discovery_start_handler)
|
||||||
else:
|
|
||||||
hass.bus.async_listen_once(
|
|
||||||
EVENT_HOMEASSISTANT_START, async_discovery_start_handler)
|
|
||||||
|
|
||||||
hass.http.register_view(hassio_discovery)
|
|
||||||
|
|
||||||
|
|
||||||
class HassIODiscovery(HomeAssistantView):
|
class HassIODiscovery(HomeAssistantView):
|
||||||
@ -51,11 +47,10 @@ class HassIODiscovery(HomeAssistantView):
|
|||||||
name = "api:hassio_push:discovery"
|
name = "api:hassio_push:discovery"
|
||||||
url = "/api/hassio_push/discovery/{uuid}"
|
url = "/api/hassio_push/discovery/{uuid}"
|
||||||
|
|
||||||
def __init__(self, hass, hassio, config):
|
def __init__(self, hass: HomeAssistantView, hassio):
|
||||||
"""Initialize WebView."""
|
"""Initialize WebView."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.hassio = hassio
|
self.hassio = hassio
|
||||||
self.config = config
|
|
||||||
|
|
||||||
async def post(self, request, uuid):
|
async def post(self, request, uuid):
|
||||||
"""Handle new discovery requests."""
|
"""Handle new discovery requests."""
|
||||||
|
@ -81,6 +81,14 @@ class HassIO:
|
|||||||
return self.send_command(
|
return self.send_command(
|
||||||
"/addons/{}/info".format(addon), method="get")
|
"/addons/{}/info".format(addon), method="get")
|
||||||
|
|
||||||
|
@_api_data
|
||||||
|
def get_ingress_panels(self):
|
||||||
|
"""Return data for Add-on ingress panels.
|
||||||
|
|
||||||
|
This method return a coroutine.
|
||||||
|
"""
|
||||||
|
return self.send_command("/ingress/panels", method="get")
|
||||||
|
|
||||||
@_api_bool
|
@_api_bool
|
||||||
def restart_homeassistant(self):
|
def restart_homeassistant(self):
|
||||||
"""Restart Home-Assistant container.
|
"""Restart Home-Assistant container.
|
||||||
|
@ -20,7 +20,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_setup_ingress(hass: HomeAssistantType, host: str):
|
def async_setup_ingress_view(hass: HomeAssistantType, host: str):
|
||||||
"""Auth setup."""
|
"""Auth setup."""
|
||||||
websession = hass.helpers.aiohttp_client.async_get_clientsession()
|
websession = hass.helpers.aiohttp_client.async_get_clientsession()
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"requirements": [],
|
"requirements": [],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"http",
|
"http",
|
||||||
|
"frontend",
|
||||||
"panel_custom"
|
"panel_custom"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
128
tests/components/hassio/test_addon_panel.py
Normal file
128
tests/components/hassio/test_addon_panel.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
"""Test add-on panel."""
|
||||||
|
from unittest.mock import patch, Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
from homeassistant.const import HTTP_HEADER_HA_AUTH
|
||||||
|
|
||||||
|
from tests.common import mock_coro
|
||||||
|
from . import API_PASSWORD
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def mock_all(aioclient_mock):
|
||||||
|
"""Mock all setup requests."""
|
||||||
|
aioclient_mock.post(
|
||||||
|
"http://127.0.0.1/homeassistant/options", json={'result': 'ok'})
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/supervisor/ping", json={'result': 'ok'})
|
||||||
|
aioclient_mock.post(
|
||||||
|
"http://127.0.0.1/supervisor/options", json={'result': 'ok'})
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/homeassistant/info", json={
|
||||||
|
'result': 'ok', 'data': {'last_version': '10.0'}})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_hassio_addon_panel_startup(hass, aioclient_mock, hassio_env):
|
||||||
|
"""Test startup and panel setup after event."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/ingress/panels", json={
|
||||||
|
'result': 'ok', 'data': {'panels': {
|
||||||
|
"test1": {
|
||||||
|
"enable": True,
|
||||||
|
"title": "Test",
|
||||||
|
"icon": "mdi:test",
|
||||||
|
"admin": False
|
||||||
|
},
|
||||||
|
"test2": {
|
||||||
|
"enable": False,
|
||||||
|
"title": "Test 2",
|
||||||
|
"icon": "mdi:test2",
|
||||||
|
"admin": True
|
||||||
|
},
|
||||||
|
}}})
|
||||||
|
|
||||||
|
assert aioclient_mock.call_count == 0
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
'homeassistant.components.hassio.addon_panel._register_panel',
|
||||||
|
Mock(return_value=mock_coro())
|
||||||
|
) as mock_panel:
|
||||||
|
await async_setup_component(hass, 'hassio', {
|
||||||
|
'http': {
|
||||||
|
'api_password': API_PASSWORD
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert aioclient_mock.call_count == 2
|
||||||
|
assert mock_panel.called
|
||||||
|
mock_panel.assert_called_with(
|
||||||
|
hass, 'test1', {
|
||||||
|
'enable': True, 'title': 'Test',
|
||||||
|
'icon': 'mdi:test', 'admin': False
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_hassio_addon_panel_api(hass, aioclient_mock, hassio_env,
|
||||||
|
hass_client):
|
||||||
|
"""Test panel api after event."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/ingress/panels", json={
|
||||||
|
'result': 'ok', 'data': {'panels': {
|
||||||
|
"test1": {
|
||||||
|
"enable": True,
|
||||||
|
"title": "Test",
|
||||||
|
"icon": "mdi:test",
|
||||||
|
"admin": False
|
||||||
|
},
|
||||||
|
"test2": {
|
||||||
|
"enable": False,
|
||||||
|
"title": "Test 2",
|
||||||
|
"icon": "mdi:test2",
|
||||||
|
"admin": True
|
||||||
|
},
|
||||||
|
}}})
|
||||||
|
|
||||||
|
assert aioclient_mock.call_count == 0
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
'homeassistant.components.hassio.addon_panel._register_panel',
|
||||||
|
Mock(return_value=mock_coro())
|
||||||
|
) as mock_panel:
|
||||||
|
await async_setup_component(hass, 'hassio', {
|
||||||
|
'http': {
|
||||||
|
'api_password': API_PASSWORD
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert aioclient_mock.call_count == 2
|
||||||
|
assert mock_panel.called
|
||||||
|
mock_panel.assert_called_with(
|
||||||
|
hass, 'test1', {
|
||||||
|
'enable': True, 'title': 'Test',
|
||||||
|
'icon': 'mdi:test', 'admin': False
|
||||||
|
})
|
||||||
|
|
||||||
|
hass_client = await hass_client()
|
||||||
|
|
||||||
|
resp = await hass_client.post(
|
||||||
|
'/api/hassio_push/panel/test2', headers={
|
||||||
|
HTTP_HEADER_HA_AUTH: API_PASSWORD
|
||||||
|
})
|
||||||
|
assert resp.status == 400
|
||||||
|
|
||||||
|
resp = await hass_client.post(
|
||||||
|
'/api/hassio_push/panel/test1', headers={
|
||||||
|
HTTP_HEADER_HA_AUTH: API_PASSWORD
|
||||||
|
})
|
||||||
|
assert resp.status == 200
|
||||||
|
assert mock_panel.call_count == 2
|
||||||
|
|
||||||
|
mock_panel.assert_called_with(
|
||||||
|
hass, 'test1', {
|
||||||
|
'enable': True, 'title': 'Test',
|
||||||
|
'icon': 'mdi:test', 'admin': False
|
||||||
|
})
|
@ -105,3 +105,23 @@ async def test_api_retrieve_discovery(hassio_handler, aioclient_mock):
|
|||||||
data = await hassio_handler.retrieve_discovery_messages()
|
data = await hassio_handler.retrieve_discovery_messages()
|
||||||
assert data['discovery'][-1]['service'] == "mqtt"
|
assert data['discovery'][-1]['service'] == "mqtt"
|
||||||
assert aioclient_mock.call_count == 1
|
assert aioclient_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_api_ingress_panels(hassio_handler, aioclient_mock):
|
||||||
|
"""Test setup with API Ingress panels."""
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/ingress/panels", json={'result': 'ok', 'data': {
|
||||||
|
"panels": {
|
||||||
|
"slug": {
|
||||||
|
"enable": True,
|
||||||
|
"title": "Test",
|
||||||
|
"icon": "mdi:test",
|
||||||
|
"admin": False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
|
||||||
|
data = await hassio_handler.get_ingress_panels()
|
||||||
|
assert aioclient_mock.call_count == 1
|
||||||
|
assert data['panels']
|
||||||
|
assert "slug" in data['panels']
|
||||||
|
@ -31,6 +31,9 @@ def mock_all(aioclient_mock):
|
|||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
"http://127.0.0.1/homeassistant/info", json={
|
"http://127.0.0.1/homeassistant/info", json={
|
||||||
'result': 'ok', 'data': {'last_version': '10.0'}})
|
'result': 'ok', 'data': {'last_version': '10.0'}})
|
||||||
|
aioclient_mock.get(
|
||||||
|
"http://127.0.0.1/ingress/panels", json={
|
||||||
|
'result': 'ok', 'data': {'panels': {}}})
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -40,7 +43,7 @@ def test_setup_api_ping(hass, aioclient_mock):
|
|||||||
result = yield from async_setup_component(hass, 'hassio', {})
|
result = yield from async_setup_component(hass, 'hassio', {})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert hass.components.hassio.get_homeassistant_version() == "10.0"
|
assert hass.components.hassio.get_homeassistant_version() == "10.0"
|
||||||
assert hass.components.hassio.is_hassio()
|
assert hass.components.hassio.is_hassio()
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ def test_setup_api_push_api_data(hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
||||||
assert aioclient_mock.mock_calls[1][2]['port'] == 9999
|
assert aioclient_mock.mock_calls[1][2]['port'] == 9999
|
||||||
assert aioclient_mock.mock_calls[1][2]['watchdog']
|
assert aioclient_mock.mock_calls[1][2]['watchdog']
|
||||||
@ -98,7 +101,7 @@ def test_setup_api_push_api_data_server_host(hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
||||||
assert aioclient_mock.mock_calls[1][2]['port'] == 9999
|
assert aioclient_mock.mock_calls[1][2]['port'] == 9999
|
||||||
assert not aioclient_mock.mock_calls[1][2]['watchdog']
|
assert not aioclient_mock.mock_calls[1][2]['watchdog']
|
||||||
@ -114,7 +117,7 @@ async def test_setup_api_push_api_data_default(hass, aioclient_mock,
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
||||||
assert aioclient_mock.mock_calls[1][2]['port'] == 8123
|
assert aioclient_mock.mock_calls[1][2]['port'] == 8123
|
||||||
refresh_token = aioclient_mock.mock_calls[1][2]['refresh_token']
|
refresh_token = aioclient_mock.mock_calls[1][2]['refresh_token']
|
||||||
@ -174,7 +177,7 @@ async def test_setup_api_existing_hassio_user(hass, aioclient_mock,
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
assert not aioclient_mock.mock_calls[1][2]['ssl']
|
||||||
assert aioclient_mock.mock_calls[1][2]['port'] == 8123
|
assert aioclient_mock.mock_calls[1][2]['port'] == 8123
|
||||||
assert aioclient_mock.mock_calls[1][2]['refresh_token'] == token.token
|
assert aioclient_mock.mock_calls[1][2]['refresh_token'] == token.token
|
||||||
@ -192,7 +195,7 @@ def test_setup_core_push_timezone(hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 4
|
assert aioclient_mock.call_count == 5
|
||||||
assert aioclient_mock.mock_calls[2][2]['timezone'] == "testzone"
|
assert aioclient_mock.mock_calls[2][2]['timezone'] == "testzone"
|
||||||
|
|
||||||
|
|
||||||
@ -206,7 +209,7 @@ def test_setup_hassio_no_additional_data(hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
assert aioclient_mock.mock_calls[-1][3]['X-Hassio-Key'] == "123456"
|
assert aioclient_mock.mock_calls[-1][3]['X-Hassio-Key'] == "123456"
|
||||||
|
|
||||||
|
|
||||||
@ -285,14 +288,14 @@ def test_service_calls(hassio_env, hass, aioclient_mock):
|
|||||||
'hassio', 'addon_stdin', {'addon': 'test', 'input': 'test'})
|
'hassio', 'addon_stdin', {'addon': 'test', 'input': 'test'})
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 5
|
assert aioclient_mock.call_count == 6
|
||||||
assert aioclient_mock.mock_calls[-1][2] == 'test'
|
assert aioclient_mock.mock_calls[-1][2] == 'test'
|
||||||
|
|
||||||
yield from hass.services.async_call('hassio', 'host_shutdown', {})
|
yield from hass.services.async_call('hassio', 'host_shutdown', {})
|
||||||
yield from hass.services.async_call('hassio', 'host_reboot', {})
|
yield from hass.services.async_call('hassio', 'host_reboot', {})
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 7
|
assert aioclient_mock.call_count == 8
|
||||||
|
|
||||||
yield from hass.services.async_call('hassio', 'snapshot_full', {})
|
yield from hass.services.async_call('hassio', 'snapshot_full', {})
|
||||||
yield from hass.services.async_call('hassio', 'snapshot_partial', {
|
yield from hass.services.async_call('hassio', 'snapshot_partial', {
|
||||||
@ -302,7 +305,7 @@ def test_service_calls(hassio_env, hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 9
|
assert aioclient_mock.call_count == 10
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
'addons': ['test'], 'folders': ['ssl'], 'password': "123456"}
|
'addons': ['test'], 'folders': ['ssl'], 'password': "123456"}
|
||||||
|
|
||||||
@ -318,7 +321,7 @@ def test_service_calls(hassio_env, hass, aioclient_mock):
|
|||||||
})
|
})
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 11
|
assert aioclient_mock.call_count == 12
|
||||||
assert aioclient_mock.mock_calls[-1][2] == {
|
assert aioclient_mock.mock_calls[-1][2] == {
|
||||||
'addons': ['test'], 'folders': ['ssl'], 'homeassistant': False,
|
'addons': ['test'], 'folders': ['ssl'], 'homeassistant': False,
|
||||||
'password': "123456"
|
'password': "123456"
|
||||||
@ -338,12 +341,12 @@ def test_service_calls_core(hassio_env, hass, aioclient_mock):
|
|||||||
yield from hass.services.async_call('homeassistant', 'stop')
|
yield from hass.services.async_call('homeassistant', 'stop')
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 2
|
assert aioclient_mock.call_count == 3
|
||||||
|
|
||||||
yield from hass.services.async_call('homeassistant', 'check_config')
|
yield from hass.services.async_call('homeassistant', 'check_config')
|
||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 2
|
assert aioclient_mock.call_count == 3
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
'homeassistant.config.async_check_ha_config_file',
|
'homeassistant.config.async_check_ha_config_file',
|
||||||
@ -353,4 +356,4 @@ def test_service_calls_core(hassio_env, hass, aioclient_mock):
|
|||||||
yield from hass.async_block_till_done()
|
yield from hass.async_block_till_done()
|
||||||
assert mock_check_config.called
|
assert mock_check_config.called
|
||||||
|
|
||||||
assert aioclient_mock.call_count == 3
|
assert aioclient_mock.call_count == 4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user