mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
2022.12.4 (#83870)
This commit is contained in:
commit
05c429bcd7
@ -7,9 +7,9 @@
|
||||
"quality_scale": "internal",
|
||||
"requirements": [
|
||||
"bleak==0.19.2",
|
||||
"bleak-retry-connector==2.10.1",
|
||||
"bleak-retry-connector==2.10.2",
|
||||
"bluetooth-adapters==0.12.0",
|
||||
"bluetooth-auto-recovery==0.5.5",
|
||||
"bluetooth-auto-recovery==1.0.0",
|
||||
"bluetooth-data-tools==0.3.0",
|
||||
"dbus-fast==1.75.0"
|
||||
],
|
||||
|
@ -130,6 +130,7 @@ class HaScanner(BaseHaScanner):
|
||||
new_info_callback: Callable[[BluetoothServiceInfoBleak], None],
|
||||
) -> None:
|
||||
"""Init bluetooth discovery."""
|
||||
self.mac_address = address
|
||||
source = address if address != DEFAULT_ADDRESS else adapter or SOURCE_LOCAL
|
||||
super().__init__(hass, source, adapter)
|
||||
self.mode = mode
|
||||
@ -375,7 +376,7 @@ class HaScanner(BaseHaScanner):
|
||||
# so we log at debug level. If we later come up with a repair
|
||||
# strategy, we will change this to raise a repair issue as well.
|
||||
_LOGGER.debug("%s: adapter stopped responding; executing reset", self.name)
|
||||
result = await async_reset_adapter(self.adapter)
|
||||
result = await async_reset_adapter(self.adapter, self.mac_address)
|
||||
_LOGGER.debug("%s: adapter reset result: %s", self.name, result)
|
||||
|
||||
async def async_stop(self) -> None:
|
||||
|
@ -36,9 +36,9 @@ def async_load_history_from_system(
|
||||
}
|
||||
|
||||
|
||||
async def async_reset_adapter(adapter: str | None) -> bool | None:
|
||||
async def async_reset_adapter(adapter: str | None, mac_address: str) -> bool | None:
|
||||
"""Reset the adapter."""
|
||||
if adapter and adapter.startswith("hci"):
|
||||
adapter_id = int(adapter[3:])
|
||||
return await recover_adapter(adapter_id)
|
||||
return await recover_adapter(adapter_id, mac_address)
|
||||
return False
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Google Cast",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/cast",
|
||||
"requirements": ["pychromecast==13.0.2"],
|
||||
"requirements": ["pychromecast==13.0.3"],
|
||||
"after_dependencies": [
|
||||
"cloud",
|
||||
"http",
|
||||
|
@ -13,7 +13,7 @@ from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
|
||||
from .const import DOMAIN
|
||||
from .subscription import async_subscription_info
|
||||
from .subscription import async_migrate_paypal_agreement, async_subscription_info
|
||||
|
||||
BACKOFF_TIME = 5
|
||||
MAX_RETRIES = 60 # This allows for 10 minutes of retries
|
||||
@ -68,13 +68,13 @@ class LegacySubscriptionRepairFlow(RepairsFlow):
|
||||
async def async_step_change_plan(self, _: None = None) -> FlowResult:
|
||||
"""Wait for the user to authorize the app installation."""
|
||||
|
||||
cloud: Cloud = self.hass.data[DOMAIN]
|
||||
|
||||
async def _async_wait_for_plan_change() -> None:
|
||||
flow_manager = repairs_flow_manager(self.hass)
|
||||
# We can not get here without a flow manager
|
||||
assert flow_manager is not None
|
||||
|
||||
cloud: Cloud = self.hass.data[DOMAIN]
|
||||
|
||||
retries = 0
|
||||
while retries < MAX_RETRIES:
|
||||
self._data = await async_subscription_info(cloud)
|
||||
@ -90,9 +90,10 @@ class LegacySubscriptionRepairFlow(RepairsFlow):
|
||||
|
||||
if not self.wait_task:
|
||||
self.wait_task = self.hass.async_create_task(_async_wait_for_plan_change())
|
||||
migration = await async_migrate_paypal_agreement(cloud)
|
||||
return self.async_external_step(
|
||||
step_id="change_plan",
|
||||
url="https://account.nabucasa.com/",
|
||||
url=migration["url"] if migration else "https://account.nabucasa.com/",
|
||||
)
|
||||
|
||||
await self.wait_task
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Subscription information."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
@ -18,7 +19,28 @@ async def async_subscription_info(cloud: Cloud) -> dict[str, Any] | None:
|
||||
try:
|
||||
async with async_timeout.timeout(REQUEST_TIMEOUT):
|
||||
return await cloud_api.async_subscription_info(cloud)
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error(
|
||||
"A timeout of %s was reached while trying to fetch subscription information",
|
||||
REQUEST_TIMEOUT,
|
||||
)
|
||||
except ClientError:
|
||||
_LOGGER.error("Failed to fetch subscription information")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
async def async_migrate_paypal_agreement(cloud: Cloud) -> dict[str, Any] | None:
|
||||
"""Migrate a paypal agreement from legacy."""
|
||||
try:
|
||||
async with async_timeout.timeout(REQUEST_TIMEOUT):
|
||||
return await cloud_api.async_migrate_paypal_agreement(cloud)
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error(
|
||||
"A timeout of %s was reached while trying to start agreement migration",
|
||||
REQUEST_TIMEOUT,
|
||||
)
|
||||
except ClientError as exception:
|
||||
_LOGGER.error("Failed to start agreement migration - %s", exception)
|
||||
|
||||
return None
|
||||
|
@ -2,6 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from xml.etree.ElementTree import ParseError
|
||||
|
||||
from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError
|
||||
from pyfritzhome.devicetypes.fritzhomeentitybase import FritzhomeEntityBase
|
||||
@ -43,7 +44,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
CONF_CONNECTIONS: fritz,
|
||||
}
|
||||
|
||||
coordinator = FritzboxDataUpdateCoordinator(hass, entry)
|
||||
try:
|
||||
await hass.async_add_executor_job(fritz.update_templates)
|
||||
except ParseError:
|
||||
LOGGER.debug("Disable smarthome templates")
|
||||
has_templates = False
|
||||
else:
|
||||
LOGGER.debug("Enable smarthome templates")
|
||||
has_templates = True
|
||||
|
||||
coordinator = FritzboxDataUpdateCoordinator(hass, entry, has_templates)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -3,7 +3,6 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from xml.etree.ElementTree import ParseError
|
||||
|
||||
from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError
|
||||
from pyfritzhome.devicetypes import FritzhomeTemplate
|
||||
@ -30,17 +29,14 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
||||
|
||||
configuration_url: str
|
||||
|
||||
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, entry: ConfigEntry, has_templates: bool
|
||||
) -> None:
|
||||
"""Initialize the Fritzbox Smarthome device coordinator."""
|
||||
self.entry = entry
|
||||
self.fritz: Fritzhome = hass.data[DOMAIN][self.entry.entry_id][CONF_CONNECTIONS]
|
||||
self.configuration_url = self.fritz.get_prefixed_host()
|
||||
self.has_templates = True
|
||||
try:
|
||||
hass.async_add_executor_job(self.fritz.update_templates)
|
||||
except ParseError:
|
||||
LOGGER.info("Disable smarthome templates")
|
||||
self.has_templates = False
|
||||
self.has_templates = has_templates
|
||||
|
||||
super().__init__(
|
||||
hass,
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "frontend",
|
||||
"name": "Home Assistant Frontend",
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"requirements": ["home-assistant-frontend==20221208.0"],
|
||||
"requirements": ["home-assistant-frontend==20221212.0"],
|
||||
"dependencies": [
|
||||
"api",
|
||||
"auth",
|
||||
|
@ -18,7 +18,7 @@ from homeassistant.const import (
|
||||
SERVICE_TURN_ON,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import State, callback
|
||||
|
||||
from .accessories import TYPES, HomeAccessory
|
||||
from .const import (
|
||||
@ -96,7 +96,7 @@ class RemoteInputSelectAccessory(HomeAccessory):
|
||||
self.sources = []
|
||||
self.support_select_source = False
|
||||
if features & required_feature:
|
||||
sources = state.attributes.get(source_list_key, [])
|
||||
sources = self._get_ordered_source_list_from_state(state)
|
||||
if len(sources) > MAXIMUM_SOURCES:
|
||||
_LOGGER.warning(
|
||||
"%s: Reached maximum number of sources (%s)",
|
||||
@ -143,6 +143,21 @@ class RemoteInputSelectAccessory(HomeAccessory):
|
||||
serv_input.configure_char(CHAR_CURRENT_VISIBILITY_STATE, value=False)
|
||||
_LOGGER.debug("%s: Added source %s", self.entity_id, source)
|
||||
|
||||
def _get_ordered_source_list_from_state(self, state: State) -> list[str]:
|
||||
"""Return ordered source list while preserving order with duplicates removed.
|
||||
|
||||
Some integrations have duplicate sources in the source list
|
||||
which will make the source list conflict as HomeKit requires
|
||||
unique source names.
|
||||
"""
|
||||
seen = set()
|
||||
sources: list[str] = []
|
||||
for source in state.attributes.get(self.source_list_key, []):
|
||||
if source not in seen:
|
||||
sources.append(source)
|
||||
seen.add(source)
|
||||
return sources
|
||||
|
||||
@abstractmethod
|
||||
def set_on_off(self, value):
|
||||
"""Move switch state to value if call came from HomeKit."""
|
||||
@ -169,7 +184,7 @@ class RemoteInputSelectAccessory(HomeAccessory):
|
||||
self.char_input_source.set_value(index)
|
||||
return
|
||||
|
||||
possible_sources = new_state.attributes.get(self.source_list_key, [])
|
||||
possible_sources = self._get_ordered_source_list_from_state(new_state)
|
||||
if source in possible_sources:
|
||||
index = possible_sources.index(source)
|
||||
if index >= MAXIMUM_SOURCES:
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"integration_type": "hub",
|
||||
"documentation": "https://www.home-assistant.io/integrations/overkiz",
|
||||
"requirements": ["pyoverkiz==1.7.1"],
|
||||
"requirements": ["pyoverkiz==1.7.2"],
|
||||
"zeroconf": [
|
||||
{
|
||||
"type": "_kizbox._tcp.local.",
|
||||
|
@ -305,14 +305,6 @@ class DomesticHotWaterProduction(OverkizEntity, WaterHeaterEntity):
|
||||
OverkizCommand.SET_BOOST_MODE, OverkizCommand.OFF
|
||||
)
|
||||
|
||||
if self.executor.has_command(OverkizCommand.SET_BOOST_MODE_DURATION):
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.SET_BOOST_MODE_DURATION, 0
|
||||
)
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_BOOST_MODE_DURATION
|
||||
)
|
||||
|
||||
if self.executor.has_command(OverkizCommand.SET_CURRENT_OPERATING_MODE):
|
||||
current_operating_mode = self.executor.select_state(
|
||||
OverkizState.CORE_OPERATING_MODE
|
||||
@ -331,5 +323,10 @@ class DomesticHotWaterProduction(OverkizEntity, WaterHeaterEntity):
|
||||
OverkizCommand.SET_DHW_MODE, self.overkiz_to_operation_mode[operation_mode]
|
||||
)
|
||||
|
||||
if self.executor.has_command(OverkizCommand.REFRESH_BOOST_MODE_DURATION):
|
||||
await self.executor.async_execute_command(
|
||||
OverkizCommand.REFRESH_BOOST_MODE_DURATION
|
||||
)
|
||||
|
||||
if self.executor.has_command(OverkizCommand.REFRESH_DHW_MODE):
|
||||
await self.executor.async_execute_command(OverkizCommand.REFRESH_DHW_MODE)
|
||||
|
@ -85,7 +85,7 @@ class SleepIQFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self._reauth_entry = self.hass.config_entries.async_get_entry(
|
||||
self.context["entry_id"]
|
||||
)
|
||||
return await self.async_step_reauth_confirm(dict(entry_data))
|
||||
return await self.async_step_reauth_confirm()
|
||||
|
||||
async def async_step_reauth_confirm(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
|
@ -7,7 +7,7 @@
|
||||
"bellows==0.34.5",
|
||||
"pyserial==3.5",
|
||||
"pyserial-asyncio==0.6",
|
||||
"zha-quirks==0.0.88",
|
||||
"zha-quirks==0.0.89",
|
||||
"zigpy-deconz==0.19.2",
|
||||
"zigpy==0.52.3",
|
||||
"zigpy-xbee==0.16.2",
|
||||
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 12
|
||||
PATCH_VERSION: Final = "3"
|
||||
PATCH_VERSION: Final = "4"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||
|
@ -10,10 +10,10 @@ atomicwrites-homeassistant==1.4.1
|
||||
attrs==21.2.0
|
||||
awesomeversion==22.9.0
|
||||
bcrypt==3.1.7
|
||||
bleak-retry-connector==2.10.1
|
||||
bleak-retry-connector==2.10.2
|
||||
bleak==0.19.2
|
||||
bluetooth-adapters==0.12.0
|
||||
bluetooth-auto-recovery==0.5.5
|
||||
bluetooth-auto-recovery==1.0.0
|
||||
bluetooth-data-tools==0.3.0
|
||||
certifi>=2021.5.30
|
||||
ciso8601==2.2.0
|
||||
@ -22,7 +22,7 @@ dbus-fast==1.75.0
|
||||
fnvhash==0.1.0
|
||||
hass-nabucasa==0.61.0
|
||||
home-assistant-bluetooth==1.8.1
|
||||
home-assistant-frontend==20221208.0
|
||||
home-assistant-frontend==20221212.0
|
||||
httpx==0.23.1
|
||||
ifaddr==0.1.7
|
||||
janus==1.0.0
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2022.12.3"
|
||||
version = "2022.12.4"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
readme = "README.rst"
|
||||
|
@ -422,7 +422,7 @@ bimmer_connected==0.10.4
|
||||
bizkaibus==0.1.1
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak-retry-connector==2.10.1
|
||||
bleak-retry-connector==2.10.2
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.19.2
|
||||
@ -450,7 +450,7 @@ bluemaestro-ble==0.2.0
|
||||
bluetooth-adapters==0.12.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.5.5
|
||||
bluetooth-auto-recovery==1.0.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
# homeassistant.components.led_ble
|
||||
@ -884,7 +884,7 @@ hole==0.7.0
|
||||
holidays==0.17.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20221208.0
|
||||
home-assistant-frontend==20221212.0
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@ -1504,7 +1504,7 @@ pycfdns==2.0.1
|
||||
pychannels==1.2.3
|
||||
|
||||
# homeassistant.components.cast
|
||||
pychromecast==13.0.2
|
||||
pychromecast==13.0.3
|
||||
|
||||
# homeassistant.components.pocketcasts
|
||||
pycketcasts==1.0.1
|
||||
@ -1812,7 +1812,7 @@ pyotgw==2.1.3
|
||||
pyotp==2.7.0
|
||||
|
||||
# homeassistant.components.overkiz
|
||||
pyoverkiz==1.7.1
|
||||
pyoverkiz==1.7.2
|
||||
|
||||
# homeassistant.components.openweathermap
|
||||
pyowm==3.2.0
|
||||
@ -2639,7 +2639,7 @@ zengge==0.2
|
||||
zeroconf==0.39.4
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.88
|
||||
zha-quirks==0.0.89
|
||||
|
||||
# homeassistant.components.zhong_hong
|
||||
zhong_hong_hvac==1.0.9
|
||||
|
@ -346,7 +346,7 @@ bellows==0.34.5
|
||||
bimmer_connected==0.10.4
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak-retry-connector==2.10.1
|
||||
bleak-retry-connector==2.10.2
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bleak==0.19.2
|
||||
@ -364,7 +364,7 @@ bluemaestro-ble==0.2.0
|
||||
bluetooth-adapters==0.12.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.5.5
|
||||
bluetooth-auto-recovery==1.0.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
# homeassistant.components.led_ble
|
||||
@ -664,7 +664,7 @@ hole==0.7.0
|
||||
holidays==0.17.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20221208.0
|
||||
home-assistant-frontend==20221212.0
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@ -1077,7 +1077,7 @@ pybravia==0.2.3
|
||||
pycfdns==2.0.1
|
||||
|
||||
# homeassistant.components.cast
|
||||
pychromecast==13.0.2
|
||||
pychromecast==13.0.3
|
||||
|
||||
# homeassistant.components.comfoconnect
|
||||
pycomfoconnect==0.4
|
||||
@ -1289,7 +1289,7 @@ pyotgw==2.1.3
|
||||
pyotp==2.7.0
|
||||
|
||||
# homeassistant.components.overkiz
|
||||
pyoverkiz==1.7.1
|
||||
pyoverkiz==1.7.2
|
||||
|
||||
# homeassistant.components.openweathermap
|
||||
pyowm==3.2.0
|
||||
@ -1840,7 +1840,7 @@ zamg==0.1.1
|
||||
zeroconf==0.39.4
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.88
|
||||
zha-quirks==0.0.89
|
||||
|
||||
# homeassistant.components.zha
|
||||
zigpy-deconz==0.19.2
|
||||
|
@ -88,6 +88,10 @@ async def test_legacy_subscription_repair_flow(
|
||||
"https://accounts.nabucasa.com/payments/subscription_info",
|
||||
json={"provider": None},
|
||||
)
|
||||
aioclient_mock.post(
|
||||
"https://accounts.nabucasa.com/payments/migrate_paypal_agreement",
|
||||
json={"url": "https://paypal.com"},
|
||||
)
|
||||
|
||||
cloud_repairs.async_manage_legacy_subscription_issue(hass, {"provider": "legacy"})
|
||||
repair_issue = issue_registry.async_get_issue(
|
||||
@ -133,7 +137,7 @@ async def test_legacy_subscription_repair_flow(
|
||||
"flow_id": flow_id,
|
||||
"handler": DOMAIN,
|
||||
"step_id": "change_plan",
|
||||
"url": "https://account.nabucasa.com/",
|
||||
"url": "https://paypal.com",
|
||||
"description_placeholders": None,
|
||||
}
|
||||
|
||||
@ -161,8 +165,15 @@ async def test_legacy_subscription_repair_flow(
|
||||
async def test_legacy_subscription_repair_flow_timeout(
|
||||
hass: HomeAssistant,
|
||||
hass_client: Callable[..., Awaitable[ClientSession]],
|
||||
mock_auth: Generator[None, AsyncMock, None],
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
):
|
||||
"""Test timeout flow of the fix flow for legacy subscription."""
|
||||
aioclient_mock.post(
|
||||
"https://accounts.nabucasa.com/payments/migrate_paypal_agreement",
|
||||
status=403,
|
||||
)
|
||||
|
||||
issue_registry: ir.IssueRegistry = ir.async_get(hass)
|
||||
|
||||
cloud_repairs.async_manage_legacy_subscription_issue(hass, {"provider": "legacy"})
|
||||
|
61
tests/components/cloud/test_subscription.py
Normal file
61
tests/components/cloud/test_subscription.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""Test cloud subscription functions."""
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
|
||||
from hass_nabucasa import Cloud
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.cloud.subscription import (
|
||||
async_migrate_paypal_agreement,
|
||||
async_subscription_info,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
|
||||
@pytest.fixture(name="mocked_cloud")
|
||||
def mocked_cloud_object(hass: HomeAssistant) -> Cloud:
|
||||
"""Mock cloud object."""
|
||||
return Mock(
|
||||
accounts_server="accounts.nabucasa.com",
|
||||
auth=Mock(async_check_token=AsyncMock()),
|
||||
websession=async_get_clientsession(hass),
|
||||
)
|
||||
|
||||
|
||||
async def test_fetching_subscription_with_timeout_error(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
mocked_cloud: Cloud,
|
||||
):
|
||||
"""Test that we handle timeout error."""
|
||||
aioclient_mock.get(
|
||||
"https://accounts.nabucasa.com/payments/subscription_info",
|
||||
exc=asyncio.TimeoutError(),
|
||||
)
|
||||
|
||||
assert await async_subscription_info(mocked_cloud) is None
|
||||
assert (
|
||||
"A timeout of 10 was reached while trying to fetch subscription information"
|
||||
in caplog.text
|
||||
)
|
||||
|
||||
|
||||
async def test_migrate_paypal_agreement_with_timeout_error(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
mocked_cloud: Cloud,
|
||||
):
|
||||
"""Test that we handle timeout error."""
|
||||
aioclient_mock.post(
|
||||
"https://accounts.nabucasa.com/payments/migrate_paypal_agreement",
|
||||
exc=asyncio.TimeoutError(),
|
||||
)
|
||||
|
||||
assert await async_migrate_paypal_agreement(mocked_cloud) is None
|
||||
assert (
|
||||
"A timeout of 10 was reached while trying to start agreement migration"
|
||||
in caplog.text
|
||||
)
|
@ -512,3 +512,48 @@ async def test_media_player_television_max_sources(hass, hk_driver, events, capl
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 0
|
||||
|
||||
|
||||
async def test_media_player_television_duplicate_sources(
|
||||
hass, hk_driver, events, caplog
|
||||
):
|
||||
"""Test if television accessory with duplicate sources."""
|
||||
entity_id = "media_player.television"
|
||||
sources = ["MUSIC", "HDMI", "SCREEN MIRRORING", "HDMI", "MUSIC"]
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{
|
||||
ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
|
||||
ATTR_SUPPORTED_FEATURES: 3469,
|
||||
ATTR_MEDIA_VOLUME_MUTED: False,
|
||||
ATTR_INPUT_SOURCE: "HDMI",
|
||||
ATTR_INPUT_SOURCE_LIST: sources,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = TelevisionMediaPlayer(hass, hk_driver, "MediaPlayer", entity_id, 2, None)
|
||||
await acc.run()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert acc.aid == 2
|
||||
assert acc.category == 31 # Television
|
||||
|
||||
assert acc.char_active.value == 0
|
||||
assert acc.char_remote_key.value == 0
|
||||
assert acc.char_input_source.value == 1
|
||||
assert acc.char_mute.value is False
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{
|
||||
ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
|
||||
ATTR_SUPPORTED_FEATURES: 3469,
|
||||
ATTR_MEDIA_VOLUME_MUTED: False,
|
||||
ATTR_INPUT_SOURCE: "MUSIC",
|
||||
ATTR_INPUT_SOURCE_LIST: sources,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user