diff --git a/homeassistant/components/automation/logbook.py b/homeassistant/components/automation/logbook.py index 86fb797ea31..97a859d25b0 100644 --- a/homeassistant/components/automation/logbook.py +++ b/homeassistant/components/automation/logbook.py @@ -15,7 +15,7 @@ def async_describe_events(hass: HomeAssistant, async_describe_event): # type: i def async_describe_logbook_event(event: LazyEventPartialState): # type: ignore[no-untyped-def] """Describe a logbook event.""" data = event.data - message = "has been triggered" + message = "triggered" if ATTR_SOURCE in data: message = f"{message} by {data[ATTR_SOURCE]}" diff --git a/homeassistant/components/deconz/logbook.py b/homeassistant/components/deconz/logbook.py index 3dedeb4bfac..e67e07d2222 100644 --- a/homeassistant/components/deconz/logbook.py +++ b/homeassistant/components/deconz/logbook.py @@ -136,7 +136,7 @@ def async_describe_events( return { "name": f"{deconz_alarm_event.device.name}", - "message": f"fired event '{data}'.", + "message": f"fired event '{data}'", } @callback @@ -158,26 +158,26 @@ def async_describe_events( if not data: return { "name": f"{deconz_event.device.name}", - "message": "fired an unknown event.", + "message": "fired an unknown event", } # No device event match if not action: return { "name": f"{deconz_event.device.name}", - "message": f"fired event '{data}'.", + "message": f"fired event '{data}'", } # Gesture event if not interface: return { "name": f"{deconz_event.device.name}", - "message": f"fired event '{ACTIONS[action]}'.", + "message": f"fired event '{ACTIONS[action]}'", } return { "name": f"{deconz_event.device.name}", - "message": f"'{ACTIONS[action]}' event for '{INTERFACES[interface]}' was fired.", + "message": f"'{ACTIONS[action]}' event for '{INTERFACES[interface]}' was fired", } async_describe_event( diff --git a/homeassistant/components/doorbird/logbook.py b/homeassistant/components/doorbird/logbook.py index a4889360d81..fbd6c670a8d 100644 --- a/homeassistant/components/doorbird/logbook.py +++ b/homeassistant/components/doorbird/logbook.py @@ -17,7 +17,7 @@ def async_describe_events(hass, async_describe_event): return { "name": "Doorbird", - "message": f"Event {event.event_type} was fired.", + "message": f"Event {event.event_type} was fired", "entity_id": hass.data[DOMAIN][DOOR_STATION_EVENT_ENTITY_IDS].get( doorbird_event, event.data.get(ATTR_ENTITY_ID) ), diff --git a/homeassistant/components/homeassistant/logbook.py b/homeassistant/components/homeassistant/logbook.py new file mode 100644 index 00000000000..229fb24cb27 --- /dev/null +++ b/homeassistant/components/homeassistant/logbook.py @@ -0,0 +1,39 @@ +"""Describe homeassistant logbook events.""" +from __future__ import annotations + +from collections.abc import Callable + +from homeassistant.components.logbook import ( + LOGBOOK_ENTRY_ICON, + LOGBOOK_ENTRY_MESSAGE, + LOGBOOK_ENTRY_NAME, +) +from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP +from homeassistant.core import Event, HomeAssistant, callback + +from . import DOMAIN + +EVENT_TO_NAME = { + EVENT_HOMEASSISTANT_STOP: "stopped", + EVENT_HOMEASSISTANT_START: "started", +} + + +@callback +def async_describe_events( + hass: HomeAssistant, + async_describe_event: Callable[[str, str, Callable[[Event], dict[str, str]]], None], +) -> None: + """Describe logbook events.""" + + @callback + def async_describe_hass_event(event: Event) -> dict[str, str]: + """Describe homeassisant logbook event.""" + return { + LOGBOOK_ENTRY_NAME: "Home Assistant", + LOGBOOK_ENTRY_MESSAGE: EVENT_TO_NAME[event.event_type], + LOGBOOK_ENTRY_ICON: "mdi:home-assistant", + } + + async_describe_event(DOMAIN, EVENT_HOMEASSISTANT_STOP, async_describe_hass_event) + async_describe_event(DOMAIN, EVENT_HOMEASSISTANT_START, async_describe_hass_event) diff --git a/homeassistant/components/logbook/__init__.py b/homeassistant/components/logbook/__init__.py index df8143d39fb..80748768c55 100644 --- a/homeassistant/components/logbook/__init__.py +++ b/homeassistant/components/logbook/__init__.py @@ -37,13 +37,10 @@ from homeassistant.const import ( ATTR_NAME, ATTR_SERVICE, EVENT_CALL_SERVICE, - EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP, EVENT_LOGBOOK_ENTRY, EVENT_STATE_CHANGED, ) from homeassistant.core import ( - DOMAIN as HA_DOMAIN, Context, Event, HomeAssistant, @@ -70,7 +67,6 @@ from .queries import statement_for_request _LOGGER = logging.getLogger(__name__) - FRIENDLY_NAME_JSON_EXTRACT = re.compile('"friendly_name": ?"([^"]+)"') ENTITY_ID_JSON_EXTRACT = re.compile('"entity_id": ?"([^"]+)"') DOMAIN_JSON_EXTRACT = re.compile('"domain": ?"([^"]+)"') @@ -79,19 +75,28 @@ ATTR_MESSAGE = "message" DOMAIN = "logbook" -HA_DOMAIN_ENTITY_ID = f"{HA_DOMAIN}._" - CONFIG_SCHEMA = vol.Schema( {DOMAIN: INCLUDE_EXCLUDE_BASE_FILTER_SCHEMA}, extra=vol.ALLOW_EXTRA ) -HOMEASSISTANT_EVENTS = {EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP} +CONTEXT_USER_ID = "context_user_id" +CONTEXT_ENTITY_ID = "context_entity_id" +CONTEXT_ENTITY_ID_NAME = "context_entity_id_name" +CONTEXT_EVENT_TYPE = "context_event_type" +CONTEXT_DOMAIN = "context_domain" +CONTEXT_SERVICE = "context_service" +CONTEXT_NAME = "context_name" +CONTEXT_MESSAGE = "context_message" -ALL_EVENT_TYPES_EXCEPT_STATE_CHANGED = ( - EVENT_LOGBOOK_ENTRY, - EVENT_CALL_SERVICE, - *HOMEASSISTANT_EVENTS, -) +LOGBOOK_ENTRY_DOMAIN = "domain" +LOGBOOK_ENTRY_ENTITY_ID = "entity_id" +LOGBOOK_ENTRY_ICON = "icon" +LOGBOOK_ENTRY_MESSAGE = "message" +LOGBOOK_ENTRY_NAME = "name" +LOGBOOK_ENTRY_STATE = "state" +LOGBOOK_ENTRY_WHEN = "when" + +ALL_EVENT_TYPES_EXCEPT_STATE_CHANGED = {EVENT_LOGBOOK_ENTRY, EVENT_CALL_SERVICE} SCRIPT_AUTOMATION_EVENTS = {EVENT_AUTOMATION_TRIGGERED, EVENT_SCRIPT_STARTED} @@ -133,12 +138,12 @@ def async_log_entry( context: Context | None = None, ) -> None: """Add an entry to the logbook.""" - data = {ATTR_NAME: name, ATTR_MESSAGE: message} + data = {LOGBOOK_ENTRY_NAME: name, LOGBOOK_ENTRY_MESSAGE: message} if domain is not None: - data[ATTR_DOMAIN] = domain + data[LOGBOOK_ENTRY_DOMAIN] = domain if entity_id is not None: - data[ATTR_ENTITY_ID] = entity_id + data[LOGBOOK_ENTRY_ENTITY_ID] = entity_id hass.bus.async_fire(EVENT_LOGBOOK_ENTRY, data, context=context) @@ -162,7 +167,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: message.hass = hass message = message.async_render(parse_result=False) - async_log_entry(hass, name, message, domain, entity_id) + async_log_entry(hass, name, message, domain, entity_id, service.context) frontend.async_register_built_in_panel( hass, "logbook", "logbook", "hass:format-list-bulleted-type" @@ -375,13 +380,13 @@ def _humanify( continue data = { - "when": format_time(row), - "name": entity_name_cache.get(entity_id, row), - "state": row.state, - "entity_id": entity_id, + LOGBOOK_ENTRY_WHEN: format_time(row), + LOGBOOK_ENTRY_NAME: entity_name_cache.get(entity_id, row), + LOGBOOK_ENTRY_STATE: row.state, + LOGBOOK_ENTRY_ENTITY_ID: entity_id, } if icon := _row_attributes_extract(row, ICON_JSON_EXTRACT): - data["icon"] = icon + data[LOGBOOK_ENTRY_ICON] = icon context_augmenter.augment(data, entity_id, row) yield data @@ -389,26 +394,11 @@ def _humanify( elif event_type in external_events: domain, describe_event = external_events[event_type] data = describe_event(event_cache.get(row)) - data["when"] = format_time(row) - data["domain"] = domain + data[LOGBOOK_ENTRY_WHEN] = format_time(row) + data[LOGBOOK_ENTRY_DOMAIN] = domain context_augmenter.augment(data, data.get(ATTR_ENTITY_ID), row) yield data - elif event_type == EVENT_HOMEASSISTANT_START: - yield { - "when": format_time(row), - "name": "Home Assistant", - "message": "started", - "domain": HA_DOMAIN, - } - elif event_type == EVENT_HOMEASSISTANT_STOP: - yield { - "when": format_time(row), - "name": "Home Assistant", - "message": "stopped", - "domain": HA_DOMAIN, - } - elif event_type == EVENT_LOGBOOK_ENTRY: event = event_cache.get(row) event_data = event.data @@ -419,11 +409,11 @@ def _humanify( domain = split_entity_id(str(entity_id))[0] data = { - "when": format_time(row), - "name": event_data.get(ATTR_NAME), - "message": event_data.get(ATTR_MESSAGE), - "domain": domain, - "entity_id": entity_id, + LOGBOOK_ENTRY_WHEN: format_time(row), + LOGBOOK_ENTRY_NAME: event_data.get(ATTR_NAME), + LOGBOOK_ENTRY_MESSAGE: event_data.get(ATTR_MESSAGE), + LOGBOOK_ENTRY_DOMAIN: domain, + LOGBOOK_ENTRY_ENTITY_ID: entity_id, } context_augmenter.augment(data, entity_id, row) yield data @@ -505,9 +495,6 @@ def _keep_row( row: Row, entities_filter: EntityFilter | Callable[[str], bool] | None = None, ) -> bool: - if event_type in HOMEASSISTANT_EVENTS: - return entities_filter is None or entities_filter(HA_DOMAIN_ENTITY_ID) - if entity_id := _row_event_data_extract(row, ENTITY_ID_JSON_EXTRACT): return entities_filter is None or entities_filter(entity_id) @@ -544,7 +531,7 @@ class ContextAugmenter: def augment(self, data: dict[str, Any], entity_id: str | None, row: Row) -> None: """Augment data from the row and cache.""" if context_user_id := row.context_user_id: - data["context_user_id"] = context_user_id + data[CONTEXT_USER_ID] = context_user_id if not (context_row := self.context_lookup.get(row.context_id)): return @@ -567,43 +554,40 @@ class ContextAugmenter: # State change if context_entity_id := context_row.entity_id: - data["context_entity_id"] = context_entity_id - data["context_entity_id_name"] = self.entity_name_cache.get( + data[CONTEXT_ENTITY_ID] = context_entity_id + data[CONTEXT_ENTITY_ID_NAME] = self.entity_name_cache.get( context_entity_id, context_row ) - data["context_event_type"] = event_type + data[CONTEXT_EVENT_TYPE] = event_type return # Call service if event_type == EVENT_CALL_SERVICE: event = self.event_cache.get(context_row) event_data = event.data - data["context_domain"] = event_data.get(ATTR_DOMAIN) - data["context_service"] = event_data.get(ATTR_SERVICE) - data["context_event_type"] = event_type + data[CONTEXT_DOMAIN] = event_data.get(ATTR_DOMAIN) + data[CONTEXT_SERVICE] = event_data.get(ATTR_SERVICE) + data[CONTEXT_EVENT_TYPE] = event_type return - if not entity_id: + if event_type not in self.external_events: return - attr_entity_id = _row_event_data_extract(context_row, ENTITY_ID_JSON_EXTRACT) - if attr_entity_id is None or ( - event_type in SCRIPT_AUTOMATION_EVENTS and attr_entity_id == entity_id - ): + domain, describe_event = self.external_events[event_type] + data[CONTEXT_EVENT_TYPE] = event_type + data[CONTEXT_DOMAIN] = domain + event = self.event_cache.get(context_row) + described = describe_event(event) + if name := described.get(ATTR_NAME): + data[CONTEXT_NAME] = name + if message := described.get(ATTR_MESSAGE): + data[CONTEXT_MESSAGE] = message + if not (attr_entity_id := described.get(ATTR_ENTITY_ID)): return - - data["context_entity_id"] = attr_entity_id - data["context_entity_id_name"] = self.entity_name_cache.get( + data[CONTEXT_ENTITY_ID] = attr_entity_id + data[CONTEXT_ENTITY_ID_NAME] = self.entity_name_cache.get( attr_entity_id, context_row ) - data["context_event_type"] = event_type - - if event_type in self.external_events: - domain, describe_event = self.external_events[event_type] - data["context_domain"] = domain - event = self.event_cache.get(context_row) - if name := describe_event(event).get(ATTR_NAME): - data["context_name"] = name def _is_sensor_continuous( @@ -627,11 +611,14 @@ def _is_sensor_continuous( def _rows_match(row: Row, other_row: Row) -> bool: """Check of rows match by using the same method as Events __hash__.""" - return bool( - row.event_type == other_row.event_type - and row.context_id == other_row.context_id - and row.time_fired == other_row.time_fired - ) + if ( + (state_id := row.state_id) is not None + and state_id == other_row.state_id + or (event_id := row.event_id) is not None + and event_id == other_row.event_id + ): + return True + return False def _row_event_data_extract(row: Row, extractor: re.Pattern) -> str | None: diff --git a/homeassistant/components/logbook/queries.py b/homeassistant/components/logbook/queries.py index 08f6d759d25..2456c73fe22 100644 --- a/homeassistant/components/logbook/queries.py +++ b/homeassistant/components/logbook/queries.py @@ -33,6 +33,7 @@ UNIT_OF_MEASUREMENT_JSON_LIKE = f"%{UNIT_OF_MEASUREMENT_JSON}%" EVENT_COLUMNS = ( + Events.event_id.label("event_id"), Events.event_type.label("event_type"), Events.event_data.label("event_data"), Events.time_fired.label("time_fired"), @@ -42,6 +43,7 @@ EVENT_COLUMNS = ( ) STATE_COLUMNS = ( + States.state_id.label("state_id"), States.state.label("state"), States.entity_id.label("entity_id"), States.attributes.label("attributes"), @@ -49,6 +51,7 @@ STATE_COLUMNS = ( ) EMPTY_STATE_COLUMNS = ( + literal(value=None, type_=sqlalchemy.String).label("state_id"), literal(value=None, type_=sqlalchemy.String).label("state"), literal(value=None, type_=sqlalchemy.String).label("entity_id"), literal(value=None, type_=sqlalchemy.Text).label("attributes"), @@ -294,6 +297,7 @@ def _select_states(start_day: dt, end_day: dt) -> Select: old_state = aliased(States, name="old_state") return ( select( + literal(value=None, type_=sqlalchemy.Text).label("event_id"), literal(value=EVENT_STATE_CHANGED, type_=sqlalchemy.String).label( "event_type" ), diff --git a/homeassistant/components/shelly/logbook.py b/homeassistant/components/shelly/logbook.py index d4278e3e98e..504dfe90791 100644 --- a/homeassistant/components/shelly/logbook.py +++ b/homeassistant/components/shelly/logbook.py @@ -49,7 +49,7 @@ def async_describe_events( return { "name": "Shelly", - "message": f"'{click_type}' click event for {input_name} Input was fired.", + "message": f"'{click_type}' click event for {input_name} Input was fired", } async_describe_event(DOMAIN, EVENT_SHELLY_CLICK, async_describe_shelly_click_event) diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index af88adc00b7..bcbcf382892 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -1243,12 +1243,12 @@ async def test_logbook_humanify_automation_triggered_event(hass): assert event1["name"] == "Hello Automation" assert event1["domain"] == "automation" - assert event1["message"] == "has been triggered" + assert event1["message"] == "triggered" assert event1["entity_id"] == "automation.hello" assert event2["name"] == "Bye Automation" assert event2["domain"] == "automation" - assert event2["message"] == "has been triggered by source of trigger" + assert event2["message"] == "triggered by source of trigger" assert event2["entity_id"] == "automation.bye" diff --git a/tests/components/automation/test_logbook.py b/tests/components/automation/test_logbook.py index a3299d806ce..1f726f478bd 100644 --- a/tests/components/automation/test_logbook.py +++ b/tests/components/automation/test_logbook.py @@ -37,13 +37,13 @@ async def test_humanify_automation_trigger_event(hass): ) assert event1["name"] == "Bla" - assert event1["message"] == "has been triggered by state change of input_boolean.yo" + assert event1["message"] == "triggered by state change of input_boolean.yo" assert event1["source"] == "state change of input_boolean.yo" assert event1["context_id"] == context.id assert event1["entity_id"] == "automation.bla" assert event2["name"] == "Bla" - assert event2["message"] == "has been triggered" + assert event2["message"] == "triggered" assert event2["source"] is None assert event2["context_id"] == context.id assert event2["entity_id"] == "automation.bla" diff --git a/tests/components/deconz/test_logbook.py b/tests/components/deconz/test_logbook.py index 98245a0df20..a78e795573a 100644 --- a/tests/components/deconz/test_logbook.py +++ b/tests/components/deconz/test_logbook.py @@ -85,7 +85,7 @@ async def test_humanifying_deconz_alarm_event(hass, aioclient_mock): assert events[0]["name"] == "Keypad" assert events[0]["domain"] == "deconz" - assert events[0]["message"] == "fired event 'armed_away'." + assert events[0]["message"] == "fired event 'armed_away'" async def test_humanifying_deconz_event(hass, aioclient_mock): @@ -214,20 +214,20 @@ async def test_humanifying_deconz_event(hass, aioclient_mock): assert events[0]["name"] == "Switch 1" assert events[0]["domain"] == "deconz" - assert events[0]["message"] == "fired event '2000'." + assert events[0]["message"] == "fired event '2000'" assert events[1]["name"] == "Hue remote" assert events[1]["domain"] == "deconz" - assert events[1]["message"] == "'Long press' event for 'Dim up' was fired." + assert events[1]["message"] == "'Long press' event for 'Dim up' was fired" assert events[2]["name"] == "Xiaomi cube" assert events[2]["domain"] == "deconz" - assert events[2]["message"] == "fired event 'Shake'." + assert events[2]["message"] == "fired event 'Shake'" assert events[3]["name"] == "Xiaomi cube" assert events[3]["domain"] == "deconz" - assert events[3]["message"] == "fired event 'unsupported_gesture'." + assert events[3]["message"] == "fired event 'unsupported_gesture'" assert events[4]["name"] == "Faulty event" assert events[4]["domain"] == "deconz" - assert events[4]["message"] == "fired an unknown event." + assert events[4]["message"] == "fired an unknown event" diff --git a/tests/components/logbook/test_init.py b/tests/components/logbook/test_init.py index d382506a3db..82857e6735c 100644 --- a/tests/components/logbook/test_init.py +++ b/tests/components/logbook/test_init.py @@ -1,5 +1,6 @@ """The tests for the logbook component.""" # pylint: disable=protected-access,invalid-name +import asyncio import collections from datetime import datetime, timedelta from http import HTTPStatus @@ -208,8 +209,10 @@ async def test_filter_sensor(hass_: ha.HomeAssistant, hass_client): _assert_entry(entries[2], name="ble", entity_id=entity_id4, state="10") -def test_home_assistant_start_stop_not_grouped(hass_): +async def test_home_assistant_start_stop_not_grouped(hass_): """Test if HA start and stop events are no longer grouped.""" + await async_setup_component(hass_, "homeassistant", {}) + await hass_.async_block_till_done() entries = mock_humanify( hass_, ( @@ -223,8 +226,10 @@ def test_home_assistant_start_stop_not_grouped(hass_): assert_entry(entries[1], name="Home Assistant", message="started", domain=ha.DOMAIN) -def test_home_assistant_start(hass_): +async def test_home_assistant_start(hass_): """Test if HA start is not filtered or converted into a restart.""" + await async_setup_component(hass_, "homeassistant", {}) + await hass_.async_block_till_done() entity_id = "switch.bla" pointA = dt_util.utcnow() @@ -604,9 +609,12 @@ async def test_logbook_view_end_time_entity(hass, hass_client, recorder_mock): async def test_logbook_entity_filter_with_automations(hass, hass_client, recorder_mock): """Test the logbook view with end_time and entity with automations and scripts.""" - await async_setup_component(hass, "logbook", {}) - await async_setup_component(hass, "automation", {}) - await async_setup_component(hass, "script", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook", "automation", "script") + ] + ) await async_recorder_block_till_done(hass) @@ -749,7 +757,12 @@ async def test_filter_continuous_sensor_values( async def test_exclude_new_entities(hass, hass_client, recorder_mock, set_utc): """Test if events are excluded on first update.""" - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) await async_recorder_block_till_done(hass) entity_id = "climate.bla" @@ -781,7 +794,12 @@ async def test_exclude_new_entities(hass, hass_client, recorder_mock, set_utc): async def test_exclude_removed_entities(hass, hass_client, recorder_mock, set_utc): """Test if events are excluded on last update.""" - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) await async_recorder_block_till_done(hass) entity_id = "climate.bla" @@ -820,7 +838,12 @@ async def test_exclude_removed_entities(hass, hass_client, recorder_mock, set_ut async def test_exclude_attribute_changes(hass, hass_client, recorder_mock, set_utc): """Test if events of attribute changes are filtered.""" - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -855,9 +878,12 @@ async def test_exclude_attribute_changes(hass, hass_client, recorder_mock, set_u async def test_logbook_entity_context_id(hass, recorder_mock, hass_client): """Test the logbook view with end_time and entity with automations and scripts.""" - await async_setup_component(hass, "logbook", {}) - await async_setup_component(hass, "automation", {}) - await async_setup_component(hass, "script", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook", "automation", "script") + ] + ) await async_recorder_block_till_done(hass) @@ -1004,9 +1030,12 @@ async def test_logbook_context_id_automation_script_started_manually( hass, recorder_mock, hass_client ): """Test the logbook populates context_ids for scripts and automations started manually.""" - await async_setup_component(hass, "logbook", {}) - await async_setup_component(hass, "automation", {}) - await async_setup_component(hass, "script", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook", "automation", "script") + ] + ) await async_recorder_block_till_done(hass) @@ -1032,6 +1061,19 @@ async def test_logbook_context_id_automation_script_started_manually( ) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + + script_2_context = ha.Context( + id="1234", + user_id="b400facee45711eaa9308bfd3d19e474", + ) + hass.bus.async_fire( + EVENT_SCRIPT_STARTED, + {ATTR_NAME: "Mock script"}, + context=script_2_context, + ) + hass.states.async_set("switch.new", STATE_ON, context=script_2_context) + hass.states.async_set("switch.new", STATE_OFF, context=script_2_context) + await hass.async_block_till_done() await async_wait_recording_done(hass) @@ -1061,12 +1103,28 @@ async def test_logbook_context_id_automation_script_started_manually( assert json_dict[2]["domain"] == "homeassistant" + assert json_dict[3]["entity_id"] is None + assert json_dict[3]["name"] == "Mock script" + assert "context_entity_id" not in json_dict[1] + assert json_dict[3]["context_user_id"] == "b400facee45711eaa9308bfd3d19e474" + assert json_dict[3]["context_id"] == "1234" + + assert json_dict[4]["entity_id"] == "switch.new" + assert json_dict[4]["state"] == "off" + assert "context_entity_id" not in json_dict[1] + assert json_dict[4]["context_user_id"] == "b400facee45711eaa9308bfd3d19e474" + assert json_dict[4]["context_event_type"] == "script_started" + assert json_dict[4]["context_domain"] == "script" + async def test_logbook_entity_context_parent_id(hass, hass_client, recorder_mock): """Test the logbook view links events via context parent_id.""" - await async_setup_component(hass, "logbook", {}) - await async_setup_component(hass, "automation", {}) - await async_setup_component(hass, "script", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook", "automation", "script") + ] + ) await async_recorder_block_till_done(hass) @@ -1240,7 +1298,13 @@ async def test_logbook_entity_context_parent_id(hass, hass_client, recorder_mock async def test_logbook_context_from_template(hass, hass_client, recorder_mock): """Test the logbook view with end_time and entity with automations and scripts.""" - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) + assert await async_setup_component( hass, "switch", @@ -1637,7 +1701,13 @@ async def test_logbook_invalid_entity(hass, hass_client, recorder_mock): async def test_icon_and_state(hass, hass_client, recorder_mock): """Test to ensure state and custom icons are returned.""" - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) + await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1705,6 +1775,7 @@ async def test_exclude_events_domain(hass, hass_client, recorder_mock): entity_id = "switch.bla" entity_id2 = "sensor.blu" + await async_setup_component(hass, "homeassistant", {}) config = logbook.CONFIG_SCHEMA( { ha.DOMAIN: {}, @@ -1750,7 +1821,10 @@ async def test_exclude_events_domain_glob(hass, hass_client, recorder_mock): }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1789,7 +1863,10 @@ async def test_include_events_entity(hass, hass_client, recorder_mock): }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1821,7 +1898,10 @@ async def test_exclude_events_entity(hass, hass_client, recorder_mock): logbook.DOMAIN: {CONF_EXCLUDE: {CONF_ENTITIES: [entity_id]}}, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1854,7 +1934,10 @@ async def test_include_events_domain(hass, hass_client, recorder_mock): }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1897,7 +1980,10 @@ async def test_include_events_domain_glob(hass, hass_client, recorder_mock): }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -1948,7 +2034,10 @@ async def test_include_exclude_events(hass, hass_client, recorder_mock): }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -2004,7 +2093,10 @@ async def test_include_exclude_events_with_glob_filters( }, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -2047,7 +2139,10 @@ async def test_empty_config(hass, hass_client, recorder_mock): logbook.DOMAIN: {}, } ) - await async_setup_component(hass, "logbook", config) + await asyncio.gather( + async_setup_component(hass, "homeassistant", {}), + async_setup_component(hass, "logbook", config), + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) @@ -2141,7 +2236,12 @@ def _assert_entry( async def test_get_events(hass, hass_ws_client, recorder_mock): """Test logbook get_events.""" now = dt_util.utcnow() - await async_setup_component(hass, "logbook", {}) + await asyncio.gather( + *[ + async_setup_component(hass, comp, {}) + for comp in ("homeassistant", "logbook") + ] + ) await async_recorder_block_till_done(hass) hass.bus.async_fire(EVENT_HOMEASSISTANT_START) diff --git a/tests/components/shelly/test_logbook.py b/tests/components/shelly/test_logbook.py index 1ba7ea7ed16..5e267dcfd8f 100644 --- a/tests/components/shelly/test_logbook.py +++ b/tests/components/shelly/test_logbook.py @@ -46,14 +46,14 @@ async def test_humanify_shelly_click_event_block_device(hass, coap_wrapper): assert event1["domain"] == DOMAIN assert ( event1["message"] - == "'single' click event for Test name channel 1 Input was fired." + == "'single' click event for Test name channel 1 Input was fired" ) assert event2["name"] == "Shelly" assert event2["domain"] == DOMAIN assert ( event2["message"] - == "'long' click event for shellyswitch25-12345678 channel 2 Input was fired." + == "'long' click event for shellyswitch25-12345678 channel 2 Input was fired" ) @@ -91,12 +91,12 @@ async def test_humanify_shelly_click_event_rpc_device(hass, rpc_wrapper): assert event1["domain"] == DOMAIN assert ( event1["message"] - == "'single_push' click event for test switch_0 Input was fired." + == "'single_push' click event for test switch_0 Input was fired" ) assert event2["name"] == "Shelly" assert event2["domain"] == DOMAIN assert ( event2["message"] - == "'btn_down' click event for shellypro4pm-12345678 channel 2 Input was fired." + == "'btn_down' click event for shellypro4pm-12345678 channel 2 Input was fired" )