Exclude hidden entities from alexa (#68555)

This commit is contained in:
Erik Montnemery 2022-03-23 12:40:28 +01:00 committed by GitHub
parent 04843a975e
commit dc8e87a6f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 59 deletions

View file

@ -68,7 +68,10 @@ class AlexaConfig(AbstractConfig):
entity_registry = er.async_get(self.hass)
if registry_entry := entity_registry.async_get(entity_id):
auxiliary_entity = registry_entry.entity_category is not None
auxiliary_entity = (
registry_entry.entity_category is not None
or registry_entry.hidden_by is not None
)
else:
auxiliary_entity = False
return not auxiliary_entity

View file

@ -3,8 +3,10 @@ import re
from unittest.mock import Mock
from uuid import uuid4
from homeassistant.components.alexa import config, smart_home
from homeassistant.components.alexa import config, smart_home, smart_home_http
from homeassistant.components.alexa.const import CONF_ENDPOINT, CONF_FILTER, CONF_LOCALE
from homeassistant.core import Context, callback
from homeassistant.helpers import entityfilter
from tests.common import async_mock_service
@ -13,7 +15,7 @@ TEST_TOKEN_URL = "https://api.amazon.com/auth/o2/token"
TEST_LOCALE = "en-US"
class MockConfig(config.AbstractConfig):
class MockConfig(smart_home_http.AlexaConfig):
"""Mock Alexa config."""
entity_config = {
@ -26,7 +28,14 @@ class MockConfig(config.AbstractConfig):
def __init__(self, hass):
"""Mock Alexa config."""
super().__init__(hass)
super().__init__(
hass,
{
CONF_ENDPOINT: TEST_URL,
CONF_FILTER: entityfilter.FILTER_SCHEMA({}),
CONF_LOCALE: TEST_LOCALE,
},
)
self._store = Mock(spec_set=config.AlexaConfigStore)
@property
@ -34,25 +43,11 @@ class MockConfig(config.AbstractConfig):
"""Return if config supports auth."""
return True
@property
def endpoint(self):
"""Endpoint for report state."""
return TEST_URL
@property
def locale(self):
"""Return config locale."""
return TEST_LOCALE
@callback
def user_identifier(self):
"""Return an identifier for the user that represents this config."""
return "mock-user-id"
def should_expose(self, entity_id):
"""If an entity should be exposed."""
return True
@callback
def async_invalidate_access_token(self):
"""Invalidate access token."""
@ -65,9 +60,9 @@ class MockConfig(config.AbstractConfig):
"""Accept a grant."""
def get_default_config():
def get_default_config(hass):
"""Return a MockConfig instance."""
return MockConfig(None)
return MockConfig(hass)
def get_new_request(namespace, name, endpoint=None):
@ -117,7 +112,7 @@ async def assert_request_calls_service(
calls = async_mock_service(hass, domain, service_name)
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
await hass.async_block_till_done()
@ -142,7 +137,7 @@ async def assert_request_fails(
domain, service_name = service_not_called.split(".")
call = async_mock_service(hass, domain, service_name)
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert not call
@ -201,7 +196,7 @@ async def reported_properties(hass, endpoint, return_full_response=False):
assertions about the properties.
"""
request = get_new_request("Alexa", "ReportState", endpoint)
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
if return_full_response:
return msg

View file

@ -55,7 +55,7 @@ async def test_api_adjust_brightness(hass, adjust):
call_light = async_mock_service(hass, "light", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -85,7 +85,7 @@ async def test_api_set_color_rgb(hass):
call_light = async_mock_service(hass, "light", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -111,7 +111,7 @@ async def test_api_set_color_temperature(hass):
call_light = async_mock_service(hass, "light", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -139,7 +139,7 @@ async def test_api_decrease_color_temp(hass, result, initial):
call_light = async_mock_service(hass, "light", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -167,7 +167,7 @@ async def test_api_increase_color_temp(hass, result, initial):
call_light = async_mock_service(hass, "light", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg

View file

@ -3,6 +3,8 @@ from unittest.mock import patch
from homeassistant.components.alexa import smart_home
from homeassistant.const import __version__
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity import EntityCategory
from . import get_default_config, get_new_request
@ -13,7 +15,63 @@ async def test_unsupported_domain(hass):
hass.states.async_set("woz.boop", "on", {"friendly_name": "Boop Woz"})
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
assert "event" in msg
msg = msg["event"]
assert not msg["payload"]["endpoints"]
async def test_categorized_hidden_entities(hass):
"""Discovery ignores hidden and categorized entities."""
entity_registry = er.async_get(hass)
request = get_new_request("Alexa.Discovery", "Discover")
entity_entry1 = entity_registry.async_get_or_create(
"switch",
"test",
"switch_config_id",
suggested_object_id="config_switch",
entity_category=EntityCategory.CONFIG,
)
entity_entry2 = entity_registry.async_get_or_create(
"switch",
"test",
"switch_diagnostic_id",
suggested_object_id="diagnostic_switch",
entity_category=EntityCategory.DIAGNOSTIC,
)
entity_entry3 = entity_registry.async_get_or_create(
"switch",
"test",
"switch_system_id",
suggested_object_id="system_switch",
entity_category=EntityCategory.SYSTEM,
)
entity_entry4 = entity_registry.async_get_or_create(
"switch",
"test",
"switch_hidden_integration_id",
suggested_object_id="hidden_integration_switch",
hidden_by=er.RegistryEntryHider.INTEGRATION,
)
entity_entry5 = entity_registry.async_get_or_create(
"switch",
"test",
"switch_hidden_user_id",
suggested_object_id="hidden_user_switch",
hidden_by=er.RegistryEntryHider.USER,
)
# These should not show up in the sync request
hass.states.async_set(entity_entry1.entity_id, "on")
hass.states.async_set(entity_entry2.entity_id, "something_else")
hass.states.async_set(entity_entry3.entity_id, "blah")
hass.states.async_set(entity_entry4.entity_id, "foo")
hass.states.async_set(entity_entry5.entity_id, "bar")
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
assert "event" in msg
msg = msg["event"]
@ -27,7 +85,7 @@ async def test_serialize_discovery(hass):
hass.states.async_set("switch.bla", "on", {"friendly_name": "Boop Woz"})
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
assert "event" in msg
msg = msg["event"]
@ -51,7 +109,9 @@ async def test_serialize_discovery_recovers(hass, caplog):
"homeassistant.components.alexa.capabilities.AlexaPowerController.serialize_discovery",
side_effect=TypeError,
):
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(
hass, get_default_config(hass), request
)
assert "event" in msg
msg = msg["event"]

View file

@ -121,7 +121,7 @@ async def test_wrong_version(hass):
msg["directive"]["header"]["payloadVersion"] = "2"
with pytest.raises(AssertionError):
await smart_home.async_handle_message(hass, get_default_config(), msg)
await smart_home.async_handle_message(hass, get_default_config(hass), msg)
async def discovery_test(device, hass, expected_endpoints=1):
@ -131,7 +131,7 @@ async def discovery_test(device, hass, expected_endpoints=1):
# setup test devices
hass.states.async_set(*device)
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
assert "event" in msg
msg = msg["event"]
@ -2308,7 +2308,7 @@ async def test_api_entity_not_exists(hass):
call_switch = async_mock_service(hass, "switch", "turn_on")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -2323,7 +2323,7 @@ async def test_api_entity_not_exists(hass):
async def test_api_function_not_implemented(hass):
"""Test api call that is not implemented to us."""
request = get_new_request("Alexa.HAHAAH", "Sweet")
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
assert "event" in msg
msg = msg["event"]
@ -2347,7 +2347,7 @@ async def test_api_accept_grant(hass):
}
# setup test devices
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(hass, get_default_config(hass), request)
await hass.async_block_till_done()
assert "event" in msg
@ -2400,7 +2400,9 @@ async def test_logging_request(hass, events):
"""Test that we log requests."""
context = Context()
request = get_new_request("Alexa.Discovery", "Discover")
await smart_home.async_handle_message(hass, get_default_config(), request, context)
await smart_home.async_handle_message(
hass, get_default_config(hass), request, context
)
# To trigger event listener
await hass.async_block_till_done()
@ -2420,7 +2422,9 @@ async def test_logging_request_with_entity(hass, events):
"""Test that we log requests."""
context = Context()
request = get_new_request("Alexa.PowerController", "TurnOn", "switch#xy")
await smart_home.async_handle_message(hass, get_default_config(), request, context)
await smart_home.async_handle_message(
hass, get_default_config(hass), request, context
)
# To trigger event listener
await hass.async_block_till_done()
@ -2446,7 +2450,7 @@ async def test_disabled(hass):
call_switch = async_mock_service(hass, "switch", "turn_on")
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, enabled=False
hass, get_default_config(hass), request, enabled=False
)
await hass.async_block_till_done()
@ -2630,7 +2634,7 @@ async def test_range_unsupported_domain(hass):
request["directive"]["header"]["instance"] = "switch.speed"
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
assert "event" in msg
@ -2651,7 +2655,7 @@ async def test_mode_unsupported_domain(hass):
request["directive"]["header"]["instance"] = "switch.direction"
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
assert "event" in msg
@ -3393,7 +3397,7 @@ async def test_media_player_eq_bands_not_supported(hass):
)
request["directive"]["payload"] = {"bands": [{"name": "BASS", "value": -2}]}
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
assert "event" in msg
@ -3410,7 +3414,7 @@ async def test_media_player_eq_bands_not_supported(hass):
"bands": [{"name": "BASS", "levelDelta": 3, "levelDirection": "UP"}]
}
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
assert "event" in msg
@ -3427,7 +3431,7 @@ async def test_media_player_eq_bands_not_supported(hass):
"bands": [{"name": "BASS", "levelDelta": 3, "levelDirection": "UP"}]
}
msg = await smart_home.async_handle_message(
hass, get_default_config(), request, context
hass, get_default_config(hass), request, context
)
assert "event" in msg
@ -3928,7 +3932,9 @@ async def test_initialize_camera_stream(hass, mock_camera, mock_stream):
"homeassistant.components.demo.camera.DemoCamera.stream_source",
return_value="rtsp://example.local",
):
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
msg = await smart_home.async_handle_message(
hass, get_default_config(hass), request
)
await hass.async_block_till_done()
assert "event" in msg
@ -3982,7 +3988,7 @@ async def test_api_message_sets_authorized(hass):
msg = get_new_request("Alexa.PowerController", "TurnOn", "switch#xy")
async_mock_service(hass, "switch", "turn_on")
config = get_default_config()
config = get_default_config(hass)
config._store.set_authorized.assert_not_called()
await smart_home.async_handle_message(hass, config, msg)
config._store.set_authorized.assert_called_once_with(True)

View file

@ -21,7 +21,7 @@ async def test_report_state(hass, aioclient_mock):
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_contact",
@ -66,7 +66,7 @@ async def test_report_state_fail(hass, aioclient_mock, caplog):
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_contact",
@ -100,7 +100,7 @@ async def test_report_state_timeout(hass, aioclient_mock, caplog):
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_contact",
@ -134,7 +134,7 @@ async def test_report_state_retry(hass, aioclient_mock):
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_contact",
@ -162,7 +162,7 @@ async def test_report_state_unsets_authorized_on_error(hass, aioclient_mock):
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
config = get_default_config()
config = get_default_config(hass)
await state_report.async_enable_proactive_mode(hass, config)
hass.states.async_set(
@ -191,7 +191,7 @@ async def test_report_state_unsets_authorized_on_access_token_error(
{"friendly_name": "Test Contact Sensor", "device_class": "door"},
)
config = get_default_config()
config = get_default_config(hass)
await state_report.async_enable_proactive_mode(hass, config)
@ -226,7 +226,7 @@ async def test_report_state_instance(hass, aioclient_mock):
},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"fan.test_fan",
@ -296,7 +296,7 @@ async def test_send_add_or_update_message(hass, aioclient_mock):
"zwave.bla", # Unsupported
]
await state_report.async_send_add_or_update_message(
hass, get_default_config(), entities
hass, get_default_config(hass), entities
)
assert len(aioclient_mock.mock_calls) == 1
@ -323,7 +323,7 @@ async def test_send_delete_message(hass, aioclient_mock):
)
await state_report.async_send_delete_message(
hass, get_default_config(), ["binary_sensor.test_contact", "zwave.bla"]
hass, get_default_config(hass), ["binary_sensor.test_contact", "zwave.bla"]
)
assert len(aioclient_mock.mock_calls) == 1
@ -349,7 +349,7 @@ async def test_doorbell_event(hass, aioclient_mock):
{"friendly_name": "Test Doorbell Sensor", "device_class": "occupancy"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_doorbell",
@ -407,7 +407,7 @@ async def test_doorbell_event_fail(hass, aioclient_mock, caplog):
{"friendly_name": "Test Doorbell Sensor", "device_class": "occupancy"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_doorbell",
@ -441,7 +441,7 @@ async def test_doorbell_event_timeout(hass, aioclient_mock, caplog):
{"friendly_name": "Test Doorbell Sensor", "device_class": "occupancy"},
)
await state_report.async_enable_proactive_mode(hass, get_default_config())
await state_report.async_enable_proactive_mode(hass, get_default_config(hass))
hass.states.async_set(
"binary_sensor.test_doorbell",
@ -464,7 +464,7 @@ async def test_doorbell_event_timeout(hass, aioclient_mock, caplog):
async def test_proactive_mode_filter_states(hass, aioclient_mock):
"""Test all the cases that filter states."""
aioclient_mock.post(TEST_URL, text="", status=202)
config = get_default_config()
config = get_default_config(hass)
await state_report.async_enable_proactive_mode(hass, config)
# First state should report