commit
77f14b63f5
|
@ -15,14 +15,14 @@ from .const import DOMAIN
|
|||
PLATFORMS = ["sensor"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
|
||||
"""Set up the Coronavirus component."""
|
||||
# Make sure coordinator is initialized.
|
||||
await get_coordinator(hass)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Coronavirus from a config entry."""
|
||||
if isinstance(entry.data["country"], int):
|
||||
hass.config_entries.async_update_entry(
|
||||
|
@ -44,6 +44,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
if not entry.unique_id:
|
||||
hass.config_entries.async_update_entry(entry, unique_id=entry.data["country"])
|
||||
|
||||
coordinator = await get_coordinator(hass)
|
||||
if not coordinator.last_update_success:
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
for platform in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, platform)
|
||||
|
@ -52,9 +56,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
unload_ok = all(
|
||||
return all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(entry, platform)
|
||||
|
@ -63,10 +67,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
)
|
||||
)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
async def get_coordinator(hass):
|
||||
async def get_coordinator(
|
||||
hass: HomeAssistant,
|
||||
) -> update_coordinator.DataUpdateCoordinator:
|
||||
"""Get the data update coordinator."""
|
||||
if DOMAIN in hass.data:
|
||||
return hass.data[DOMAIN]
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
"""Config flow for Coronavirus integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -15,13 +19,18 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
_options = None
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> dict[str, Any]:
|
||||
"""Handle the initial step."""
|
||||
errors = {}
|
||||
|
||||
if self._options is None:
|
||||
self._options = {OPTION_WORLDWIDE: "Worldwide"}
|
||||
coordinator = await get_coordinator(self.hass)
|
||||
if not coordinator.last_update_success:
|
||||
return self.async_abort(reason="cannot_connect")
|
||||
|
||||
self._options = {OPTION_WORLDWIDE: "Worldwide"}
|
||||
for case in sorted(
|
||||
coordinator.data.values(), key=lambda case: case.country
|
||||
):
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
}
|
||||
},
|
||||
"abort": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Service is already configured"
|
||||
"already_configured": "Service is already configured",
|
||||
"cannot_connect": "Failed to connect"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "DHCP Discovery",
|
||||
"documentation": "https://www.home-assistant.io/integrations/dhcp",
|
||||
"requirements": [
|
||||
"scapy==2.4.4", "aiodiscover==1.3.3"
|
||||
"scapy==2.4.4", "aiodiscover==1.3.4"
|
||||
],
|
||||
"codeowners": [
|
||||
"@bdraco"
|
||||
|
|
|
@ -507,5 +507,5 @@ def state_needs_accessory_mode(state):
|
|||
or state.domain == MEDIA_PLAYER_DOMAIN
|
||||
and state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TV
|
||||
or state.domain == REMOTE_DOMAIN
|
||||
and state.attributes.get(ATTR_SUPPORTED_FEATURES) & SUPPORT_ACTIVITY
|
||||
and state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) & SUPPORT_ACTIVITY
|
||||
)
|
||||
|
|
|
@ -751,3 +751,20 @@ class Light(LightEntity):
|
|||
"Light is deprecated, modify %s to extend LightEntity",
|
||||
cls.__name__,
|
||||
)
|
||||
|
||||
|
||||
def legacy_supported_features(
|
||||
supported_features: int, supported_color_modes: list[str] | None
|
||||
) -> int:
|
||||
"""Calculate supported features with backwards compatibility."""
|
||||
# Backwards compatibility for supported_color_modes added in 2021.4
|
||||
if supported_color_modes is None:
|
||||
return supported_features
|
||||
if any(mode in supported_color_modes for mode in COLOR_MODES_COLOR):
|
||||
supported_features |= SUPPORT_COLOR
|
||||
if any(mode in supported_color_modes for mode in COLOR_MODES_BRIGHTNESS):
|
||||
supported_features |= SUPPORT_BRIGHTNESS
|
||||
if COLOR_MODE_COLOR_TEMP in supported_color_modes:
|
||||
supported_features |= SUPPORT_COLOR_TEMP
|
||||
|
||||
return supported_features
|
||||
|
|
|
@ -35,6 +35,7 @@ from homeassistant.components.light import (
|
|||
SUPPORT_WHITE_VALUE,
|
||||
VALID_COLOR_MODES,
|
||||
LightEntity,
|
||||
legacy_supported_features,
|
||||
valid_supported_color_modes,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
|
@ -458,7 +459,9 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity):
|
|||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return self._supported_features
|
||||
return legacy_supported_features(
|
||||
self._supported_features, self._config.get(CONF_SUPPORTED_COLOR_MODES)
|
||||
)
|
||||
|
||||
def _set_flash_and_transition(self, message, **kwargs):
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
|
|
|
@ -7,6 +7,11 @@ from homeassistant.components.mqtt import valid_publish_topic, valid_subscribe_t
|
|||
from homeassistant.const import (
|
||||
ATTR_SERVICE_DATA,
|
||||
EVENT_CALL_SERVICE,
|
||||
EVENT_HOMEASSISTANT_CLOSE,
|
||||
EVENT_HOMEASSISTANT_FINAL_WRITE,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
EVENT_STATE_CHANGED,
|
||||
EVENT_TIME_CHANGED,
|
||||
MATCH_ALL,
|
||||
|
@ -37,6 +42,14 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
BLOCKED_EVENTS = [
|
||||
EVENT_HOMEASSISTANT_CLOSE,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
EVENT_HOMEASSISTANT_FINAL_WRITE,
|
||||
]
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Set up the MQTT eventstream component."""
|
||||
|
@ -45,16 +58,15 @@ async def async_setup(hass, config):
|
|||
pub_topic = conf.get(CONF_PUBLISH_TOPIC)
|
||||
sub_topic = conf.get(CONF_SUBSCRIBE_TOPIC)
|
||||
ignore_event = conf.get(CONF_IGNORE_EVENT)
|
||||
ignore_event.append(EVENT_TIME_CHANGED)
|
||||
|
||||
@callback
|
||||
def _event_publisher(event):
|
||||
"""Handle events by publishing them on the MQTT queue."""
|
||||
if event.origin != EventOrigin.local:
|
||||
return
|
||||
if event.event_type == EVENT_TIME_CHANGED:
|
||||
return
|
||||
|
||||
# User-defined events to ignore
|
||||
# Events to ignore
|
||||
if event.event_type in ignore_event:
|
||||
return
|
||||
|
||||
|
@ -84,6 +96,10 @@ async def async_setup(hass, config):
|
|||
event_type = event.get("event_type")
|
||||
event_data = event.get("event_data")
|
||||
|
||||
# Don't fire HOMEASSISTANT_* events on this instance
|
||||
if event_type in BLOCKED_EVENTS:
|
||||
return
|
||||
|
||||
# Special case handling for event STATE_CHANGED
|
||||
# We will try to convert state dicts back to State objects
|
||||
# Copied over from the _handle_api_post_events_event method
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""Support for MySensors sensors."""
|
||||
from typing import Callable
|
||||
|
||||
from awesomeversion import AwesomeVersion
|
||||
|
||||
from homeassistant.components import mysensors
|
||||
from homeassistant.components.mysensors import on_unload
|
||||
from homeassistant.components.mysensors.const import MYSENSORS_DISCOVERY
|
||||
|
@ -115,7 +117,7 @@ class MySensorsSensor(mysensors.device.MySensorsEntity, SensorEntity):
|
|||
"""Return the unit of measurement of this entity."""
|
||||
set_req = self.gateway.const.SetReq
|
||||
if (
|
||||
float(self.gateway.protocol_version) >= 1.5
|
||||
AwesomeVersion(self.gateway.protocol_version) >= AwesomeVersion("1.5")
|
||||
and set_req.V_UNIT_PREFIX in self._values
|
||||
):
|
||||
return self._values[set_req.V_UNIT_PREFIX]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "spotify",
|
||||
"name": "Spotify",
|
||||
"documentation": "https://www.home-assistant.io/integrations/spotify",
|
||||
"requirements": ["spotipy==2.17.1"],
|
||||
"requirements": ["spotipy==2.18.0"],
|
||||
"zeroconf": ["_spotify-connect._tcp.local."],
|
||||
"dependencies": ["http"],
|
||||
"codeowners": ["@frenck"],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 2021
|
||||
MINOR_VERSION = 4
|
||||
PATCH_VERSION = "4"
|
||||
PATCH_VERSION = "5"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 8, 0)
|
||||
|
|
|
@ -1144,10 +1144,7 @@ class Script:
|
|||
self._log("Already running", level=LOGSEVERITY[self._max_exceeded])
|
||||
script_execution_set("failed_single")
|
||||
return
|
||||
if self.script_mode == SCRIPT_MODE_RESTART:
|
||||
self._log("Restarting")
|
||||
await self.async_stop(update_state=False)
|
||||
elif len(self._runs) == self.max_runs:
|
||||
if self.script_mode != SCRIPT_MODE_RESTART and self.runs == self.max_runs:
|
||||
if self._max_exceeded != "SILENT":
|
||||
self._log(
|
||||
"Maximum number of runs exceeded",
|
||||
|
@ -1186,6 +1183,14 @@ class Script:
|
|||
self._hass, self, cast(dict, variables), context, self._log_exceptions
|
||||
)
|
||||
self._runs.append(run)
|
||||
if self.script_mode == SCRIPT_MODE_RESTART:
|
||||
# When script mode is SCRIPT_MODE_RESTART, first add the new run and then
|
||||
# stop any other runs. If we stop other runs first, self.is_running will
|
||||
# return false after the other script runs were stopped until our task
|
||||
# resumes running.
|
||||
self._log("Restarting")
|
||||
await self.async_stop(update_state=False, spare=run)
|
||||
|
||||
if started_action:
|
||||
self._hass.async_run_job(started_action)
|
||||
self.last_triggered = utcnow()
|
||||
|
@ -1198,17 +1203,21 @@ class Script:
|
|||
self._changed()
|
||||
raise
|
||||
|
||||
async def _async_stop(self, update_state):
|
||||
aws = [asyncio.create_task(run.async_stop()) for run in self._runs]
|
||||
async def _async_stop(self, update_state, spare=None):
|
||||
aws = [
|
||||
asyncio.create_task(run.async_stop()) for run in self._runs if run != spare
|
||||
]
|
||||
if not aws:
|
||||
return
|
||||
await asyncio.wait(aws)
|
||||
if update_state:
|
||||
self._changed()
|
||||
|
||||
async def async_stop(self, update_state: bool = True) -> None:
|
||||
async def async_stop(
|
||||
self, update_state: bool = True, spare: _ScriptRun | None = None
|
||||
) -> None:
|
||||
"""Stop running script."""
|
||||
await asyncio.shield(self._async_stop(update_state))
|
||||
await asyncio.shield(self._async_stop(update_state, spare))
|
||||
|
||||
async def _async_get_condition(self, config):
|
||||
if isinstance(config, template.Template):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
PyJWT==1.7.1
|
||||
PyNaCl==1.3.0
|
||||
aiodiscover==1.3.3
|
||||
aiodiscover==1.3.4
|
||||
aiohttp==3.7.4.post0
|
||||
aiohttp_cors==0.7.0
|
||||
astral==1.10.1
|
||||
|
|
|
@ -22,6 +22,7 @@ BASE_PLATFORMS = {
|
|||
"air_quality",
|
||||
"alarm_control_panel",
|
||||
"binary_sensor",
|
||||
"camera",
|
||||
"climate",
|
||||
"cover",
|
||||
"device_tracker",
|
||||
|
|
|
@ -147,7 +147,7 @@ aioazuredevops==1.3.5
|
|||
aiobotocore==0.11.1
|
||||
|
||||
# homeassistant.components.dhcp
|
||||
aiodiscover==1.3.3
|
||||
aiodiscover==1.3.4
|
||||
|
||||
# homeassistant.components.dnsip
|
||||
# homeassistant.components.minecraft_server
|
||||
|
@ -2117,7 +2117,7 @@ spiderpy==1.4.2
|
|||
spotcrime==1.0.4
|
||||
|
||||
# homeassistant.components.spotify
|
||||
spotipy==2.17.1
|
||||
spotipy==2.18.0
|
||||
|
||||
# homeassistant.components.recorder
|
||||
# homeassistant.components.sql
|
||||
|
|
|
@ -84,7 +84,7 @@ aioazuredevops==1.3.5
|
|||
aiobotocore==0.11.1
|
||||
|
||||
# homeassistant.components.dhcp
|
||||
aiodiscover==1.3.3
|
||||
aiodiscover==1.3.4
|
||||
|
||||
# homeassistant.components.dnsip
|
||||
# homeassistant.components.minecraft_server
|
||||
|
@ -1104,7 +1104,7 @@ speedtest-cli==2.1.3
|
|||
spiderpy==1.4.2
|
||||
|
||||
# homeassistant.components.spotify
|
||||
spotipy==2.17.1
|
||||
spotipy==2.18.0
|
||||
|
||||
# homeassistant.components.recorder
|
||||
# homeassistant.components.sql
|
||||
|
|
|
@ -156,8 +156,8 @@ async def test_motion_light(hass):
|
|||
# Turn on motion
|
||||
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||
# Can't block till done because delay is active
|
||||
# So wait 5 event loop iterations to process script
|
||||
for _ in range(5):
|
||||
# So wait 10 event loop iterations to process script
|
||||
for _ in range(10):
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert len(turn_on_calls) == 1
|
||||
|
@ -165,7 +165,7 @@ async def test_motion_light(hass):
|
|||
# Test light doesn't turn off if motion stays
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=200))
|
||||
|
||||
for _ in range(5):
|
||||
for _ in range(10):
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert len(turn_off_calls) == 0
|
||||
|
@ -173,7 +173,7 @@ async def test_motion_light(hass):
|
|||
# Test light turns off off 120s after last motion
|
||||
hass.states.async_set("binary_sensor.kitchen", "off")
|
||||
|
||||
for _ in range(5):
|
||||
for _ in range(10):
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=120))
|
||||
|
@ -184,7 +184,7 @@ async def test_motion_light(hass):
|
|||
# Test restarting the script
|
||||
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||
|
||||
for _ in range(5):
|
||||
for _ in range(10):
|
||||
await asyncio.sleep(0)
|
||||
|
||||
assert len(turn_on_calls) == 2
|
||||
|
@ -192,7 +192,7 @@ async def test_motion_light(hass):
|
|||
|
||||
hass.states.async_set("binary_sensor.kitchen", "off")
|
||||
|
||||
for _ in range(5):
|
||||
for _ in range(10):
|
||||
await asyncio.sleep(0)
|
||||
|
||||
hass.states.async_set("binary_sensor.kitchen", "on")
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
"""Test the Coronavirus config flow."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from aiohttp import ClientError
|
||||
|
||||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.coronavirus.const import DOMAIN, OPTION_WORLDWIDE
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
async def test_form(hass):
|
||||
async def test_form(hass: HomeAssistant) -> None:
|
||||
"""Test we get the form."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -24,3 +29,22 @@ async def test_form(hass):
|
|||
}
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 4
|
||||
|
||||
|
||||
@patch(
|
||||
"coronavirus.get_cases",
|
||||
side_effect=ClientError,
|
||||
)
|
||||
async def test_abort_on_connection_error(
|
||||
mock_get_cases: MagicMock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test we abort on connection error."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
assert "type" in result
|
||||
assert result["type"] == "abort"
|
||||
assert "reason" in result
|
||||
assert result["reason"] == "cannot_connect"
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
"""Test init of Coronavirus integration."""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from aiohttp import ClientError
|
||||
|
||||
from homeassistant.components.coronavirus.const import DOMAIN, OPTION_WORLDWIDE
|
||||
from homeassistant.config_entries import ENTRY_STATE_SETUP_RETRY
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry, mock_registry
|
||||
|
||||
|
||||
async def test_migration(hass):
|
||||
async def test_migration(hass: HomeAssistant) -> None:
|
||||
"""Test that we can migrate coronavirus to stable unique ID."""
|
||||
nl_entry = MockConfigEntry(domain=DOMAIN, title="Netherlands", data={"country": 34})
|
||||
nl_entry.add_to_hass(hass)
|
||||
|
@ -47,3 +53,20 @@ async def test_migration(hass):
|
|||
|
||||
assert nl_entry.unique_id == "Netherlands"
|
||||
assert worldwide_entry.unique_id == OPTION_WORLDWIDE
|
||||
|
||||
|
||||
@patch(
|
||||
"coronavirus.get_cases",
|
||||
side_effect=ClientError,
|
||||
)
|
||||
async def test_config_entry_not_ready(
|
||||
mock_get_cases: MagicMock, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test the configuration entry not ready."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, title="Netherlands", data={"country": 34})
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state == ENTRY_STATE_SETUP_RETRY
|
||||
|
|
|
@ -145,6 +145,8 @@ async def test_setup_creates_entries_for_accessory_mode_devices(hass):
|
|||
hass.states.async_set("camera.one", "on")
|
||||
hass.states.async_set("camera.existing", "on")
|
||||
hass.states.async_set("media_player.two", "on", {"device_class": "tv"})
|
||||
hass.states.async_set("remote.standard", "on")
|
||||
hass.states.async_set("remote.activity", "on", {"supported_features": 4})
|
||||
|
||||
bridge_mode_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
|
@ -178,7 +180,7 @@ async def test_setup_creates_entries_for_accessory_mode_devices(hass):
|
|||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"include_domains": ["camera", "media_player", "light"]},
|
||||
{"include_domains": ["camera", "media_player", "light", "remote"]},
|
||||
)
|
||||
assert result2["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result2["step_id"] == "pairing"
|
||||
|
@ -205,7 +207,7 @@ async def test_setup_creates_entries_for_accessory_mode_devices(hass):
|
|||
"filter": {
|
||||
"exclude_domains": [],
|
||||
"exclude_entities": [],
|
||||
"include_domains": ["media_player", "light"],
|
||||
"include_domains": ["media_player", "light", "remote"],
|
||||
"include_entities": [],
|
||||
},
|
||||
"exclude_accessory_mode": True,
|
||||
|
@ -222,7 +224,8 @@ async def test_setup_creates_entries_for_accessory_mode_devices(hass):
|
|||
# 3 - new bridge
|
||||
# 4 - camera.one in accessory mode
|
||||
# 5 - media_player.two in accessory mode
|
||||
assert len(mock_setup_entry.mock_calls) == 5
|
||||
# 6 - remote.activity in accessory mode
|
||||
assert len(mock_setup_entry.mock_calls) == 6
|
||||
|
||||
|
||||
async def test_import(hass):
|
||||
|
|
|
@ -234,10 +234,10 @@ async def test_rgb_light(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
expected_features = (
|
||||
light.SUPPORT_TRANSITION
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_TRANSITION
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
|
||||
|
@ -261,7 +261,8 @@ async def test_no_color_brightness_color_temp_white_val_if_no_topics(hass, mqtt_
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 40
|
||||
expected_features = light.SUPPORT_FLASH | light.SUPPORT_TRANSITION
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get("rgb_color") is None
|
||||
assert state.attributes.get("brightness") is None
|
||||
assert state.attributes.get("color_temp") is None
|
||||
|
@ -310,7 +311,16 @@ async def test_controlling_state_via_topic(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 191
|
||||
expected_features = (
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_COLOR_TEMP
|
||||
| light.SUPPORT_EFFECT
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_TRANSITION
|
||||
| light.SUPPORT_WHITE_VALUE
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get("rgb_color") is None
|
||||
assert state.attributes.get("brightness") is None
|
||||
assert state.attributes.get("color_temp") is None
|
||||
|
@ -429,7 +439,15 @@ async def test_controlling_state_via_topic2(hass, mqtt_mock, caplog):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 44
|
||||
expected_features = (
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_COLOR_TEMP
|
||||
| light.SUPPORT_EFFECT
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_TRANSITION
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get("brightness") is None
|
||||
assert state.attributes.get("color_mode") is None
|
||||
assert state.attributes.get("color_temp") is None
|
||||
|
@ -610,7 +628,16 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
|
|||
assert state.attributes.get("effect") == "random"
|
||||
assert state.attributes.get("color_temp") == 100
|
||||
assert state.attributes.get("white_value") == 50
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 191
|
||||
expected_features = (
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_COLOR_TEMP
|
||||
| light.SUPPORT_EFFECT
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_TRANSITION
|
||||
| light.SUPPORT_WHITE_VALUE
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||
|
||||
await common.async_turn_on(hass, "light.test")
|
||||
|
@ -738,7 +765,15 @@ async def test_sending_mqtt_commands_and_optimistic2(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 44
|
||||
expected_features = (
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_COLOR_TEMP
|
||||
| light.SUPPORT_EFFECT
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_TRANSITION
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get("brightness") == 95
|
||||
assert state.attributes.get("color_mode") == "rgb"
|
||||
assert state.attributes.get("color_temp") is None
|
||||
|
@ -1313,7 +1348,10 @@ async def test_effect(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 44
|
||||
expected_features = (
|
||||
light.SUPPORT_EFFECT | light.SUPPORT_FLASH | light.SUPPORT_TRANSITION
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
|
||||
await common.async_turn_on(hass, "light.test")
|
||||
|
||||
|
@ -1373,7 +1411,8 @@ async def test_flash_short_and_long(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 40
|
||||
expected_features = light.SUPPORT_FLASH | light.SUPPORT_TRANSITION
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
|
||||
await common.async_turn_on(hass, "light.test", flash="short")
|
||||
|
||||
|
@ -1431,8 +1470,8 @@ async def test_transition(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 40
|
||||
|
||||
expected_features = light.SUPPORT_FLASH | light.SUPPORT_TRANSITION
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
await common.async_turn_on(hass, "light.test", transition=15)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
|
@ -1523,7 +1562,15 @@ async def test_invalid_values(hass, mqtt_mock):
|
|||
|
||||
state = hass.states.get("light.test")
|
||||
assert state.state == STATE_OFF
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 187
|
||||
expected_features = (
|
||||
light.SUPPORT_BRIGHTNESS
|
||||
| light.SUPPORT_COLOR
|
||||
| light.SUPPORT_COLOR_TEMP
|
||||
| light.SUPPORT_FLASH
|
||||
| light.SUPPORT_TRANSITION
|
||||
| light.SUPPORT_WHITE_VALUE
|
||||
)
|
||||
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
|
||||
assert state.attributes.get("rgb_color") is None
|
||||
assert state.attributes.get("brightness") is None
|
||||
assert state.attributes.get("white_value") is None
|
||||
|
|
|
@ -3,7 +3,7 @@ import json
|
|||
from unittest.mock import ANY, patch
|
||||
|
||||
import homeassistant.components.mqtt_eventstream as eventstream
|
||||
from homeassistant.const import EVENT_STATE_CHANGED
|
||||
from homeassistant.const import EVENT_STATE_CHANGED, MATCH_ALL
|
||||
from homeassistant.core import State, callback
|
||||
from homeassistant.helpers.json import JSONEncoder
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
@ -114,6 +114,7 @@ async def test_time_event_does_not_send_message(hass, mqtt_mock):
|
|||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow())
|
||||
await hass.async_block_till_done()
|
||||
assert not mqtt_mock.async_publish.called
|
||||
|
||||
|
||||
|
@ -140,6 +141,33 @@ async def test_receiving_remote_event_fires_hass_event(hass, mqtt_mock):
|
|||
|
||||
assert len(calls) == 1
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_receiving_blocked_event_fires_hass_event(hass, mqtt_mock):
|
||||
"""Test the receiving of blocked event does not fire."""
|
||||
sub_topic = "foo"
|
||||
assert await add_eventstream(hass, sub_topic=sub_topic)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
calls = []
|
||||
|
||||
@callback
|
||||
def listener(_):
|
||||
calls.append(1)
|
||||
|
||||
hass.bus.async_listen(MATCH_ALL, listener)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
for event in eventstream.BLOCKED_EVENTS:
|
||||
payload = json.dumps({"event_type": event, "event_data": {}}, cls=JSONEncoder)
|
||||
async_fire_mqtt_message(hass, sub_topic, payload)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(calls) == 0
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_ignored_event_doesnt_send_over_stream(hass, mqtt_mock):
|
||||
"""Test the ignoring of sending events if defined."""
|
||||
|
@ -159,6 +187,7 @@ async def test_ignored_event_doesnt_send_over_stream(hass, mqtt_mock):
|
|||
# Set a state of an entity
|
||||
mock_state_change_event(hass, State(e_id, "on"))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not mqtt_mock.async_publish.called
|
||||
|
||||
|
|
Loading…
Reference in New Issue