diff --git a/homeassistant/components/media_player/device_trigger.py b/homeassistant/components/media_player/device_trigger.py index 58fc0aca84f..e626059841c 100644 --- a/homeassistant/components/media_player/device_trigger.py +++ b/homeassistant/components/media_player/device_trigger.py @@ -33,7 +33,7 @@ TRIGGER_TYPES = {"turned_on", "turned_off", "buffering", "idle", "paused", "play MEDIA_PLAYER_TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend( { - vol.Required(CONF_ENTITY_ID): cv.entity_id, + vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid, vol.Required(CONF_TYPE): vol.In(TRIGGER_TYPES), vol.Optional(CONF_FOR): cv.positive_time_period_dict, } @@ -66,7 +66,7 @@ async def async_get_triggers( CONF_PLATFORM: "device", CONF_DEVICE_ID: device_id, CONF_DOMAIN: DOMAIN, - CONF_ENTITY_ID: entry.entity_id, + CONF_ENTITY_ID: entry.id, CONF_TYPE: trigger, } for trigger in TRIGGER_TYPES diff --git a/tests/components/media_player/test_device_trigger.py b/tests/components/media_player/test_device_trigger.py index c899bf2ce75..8bf71f85647 100644 --- a/tests/components/media_player/test_device_trigger.py +++ b/tests/components/media_player/test_device_trigger.py @@ -54,13 +54,15 @@ async def test_get_triggers( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) - entity_registry.async_get_or_create( + entity_entry = entity_registry.async_get_or_create( DOMAIN, "test", "5678", device_id=device_entry.id ) + entity_trigger_types = { + "changed_states", + } trigger_types = { "buffering", - "changed_states", "idle", "paused", "playing", @@ -73,11 +75,22 @@ async def test_get_triggers( "domain": DOMAIN, "type": trigger, "device_id": device_entry.id, - "entity_id": f"{DOMAIN}.test_5678", + "entity_id": entity_entry.id, "metadata": {"secondary": False}, } for trigger in trigger_types ] + expected_triggers += [ + { + "platform": "device", + "domain": DOMAIN, + "type": trigger, + "device_id": device_entry.id, + "entity_id": entity_entry.entity_id, + "metadata": {"secondary": False}, + } + for trigger in entity_trigger_types + ] triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id ) @@ -107,7 +120,7 @@ async def test_get_triggers_hidden_auxiliary( config_entry_id=config_entry.entry_id, connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) - entity_registry.async_get_or_create( + entity_entry = entity_registry.async_get_or_create( DOMAIN, "test", "5678", @@ -115,24 +128,38 @@ async def test_get_triggers_hidden_auxiliary( entity_category=entity_category, hidden_by=hidden_by, ) + entity_trigger_types = { + "changed_states", + } + trigger_types = { + "buffering", + "idle", + "paused", + "playing", + "turned_off", + "turned_on", + } expected_triggers = [ { "platform": "device", "domain": DOMAIN, "type": trigger, "device_id": device_entry.id, - "entity_id": f"{DOMAIN}.test_5678", + "entity_id": entity_entry.id, "metadata": {"secondary": True}, } - for trigger in [ - "buffering", - "changed_states", - "idle", - "paused", - "playing", - "turned_off", - "turned_on", - ] + for trigger in trigger_types + ] + expected_triggers += [ + { + "platform": "device", + "domain": DOMAIN, + "type": trigger, + "device_id": device_entry.id, + "entity_id": entity_entry.entity_id, + "metadata": {"secondary": True}, + } + for trigger in entity_trigger_types ] triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id @@ -171,9 +198,45 @@ async def test_get_trigger_capabilities( } -async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None: +async def test_get_trigger_capabilities_legacy( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + entity_registry: er.EntityRegistry, +) -> None: + """Test we get the expected capabilities from a media player.""" + config_entry = MockConfigEntry(domain="test", data={}) + config_entry.add_to_hass(hass) + device_entry = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, + ) + entity_registry.async_get_or_create( + DOMAIN, "test", "5678", device_id=device_entry.id + ) + + triggers = await async_get_device_automations( + hass, DeviceAutomationType.TRIGGER, device_entry.id + ) + assert len(triggers) == 7 + for trigger in triggers: + trigger["entity_id"] = entity_registry.async_get(trigger["entity_id"]).entity_id + capabilities = await async_get_device_automation_capabilities( + hass, DeviceAutomationType.TRIGGER, trigger + ) + assert capabilities == { + "extra_fields": [ + {"name": "for", "optional": True, "type": "positive_time_period_dict"} + ] + } + + +async def test_if_fires_on_state_change( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: """Test triggers firing.""" - hass.states.async_set("media_player.entity", STATE_OFF) + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_OFF) data_template = ( "{label} - {{{{ trigger.platform}}}} - " @@ -200,7 +263,9 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None: "platform": "device", "domain": DOMAIN, "device_id": "", - "entity_id": "media_player.entity", + "entity_id": entry.entity_id + if trigger == "changed_states" + else entry.id, "type": trigger, }, "action": { @@ -214,64 +279,73 @@ async def test_if_fires_on_state_change(hass: HomeAssistant, calls) -> None: ) # Fake that the entity is turning on. - hass.states.async_set("media_player.entity", STATE_ON) + hass.states.async_set(entry.entity_id, STATE_ON) await hass.async_block_till_done() assert len(calls) == 2 assert {calls[0].data["some"], calls[1].data["some"]} == { - "turned_on - device - media_player.entity - off - on - None", - "changed_states - device - media_player.entity - off - on - None", + "turned_on - device - media_player.test_5678 - off - on - None", + "changed_states - device - media_player.test_5678 - off - on - None", } # Fake that the entity is turning off. - hass.states.async_set("media_player.entity", STATE_OFF) + hass.states.async_set(entry.entity_id, STATE_OFF) await hass.async_block_till_done() assert len(calls) == 4 assert {calls[2].data["some"], calls[3].data["some"]} == { - "turned_off - device - media_player.entity - on - off - None", - "changed_states - device - media_player.entity - on - off - None", + "turned_off - device - media_player.test_5678 - on - off - None", + "changed_states - device - media_player.test_5678 - on - off - None", } # Fake that the entity becomes idle. - hass.states.async_set("media_player.entity", STATE_IDLE) + hass.states.async_set(entry.entity_id, STATE_IDLE) await hass.async_block_till_done() assert len(calls) == 6 assert {calls[4].data["some"], calls[5].data["some"]} == { - "idle - device - media_player.entity - off - idle - None", - "changed_states - device - media_player.entity - off - idle - None", + "idle - device - media_player.test_5678 - off - idle - None", + "changed_states - device - media_player.test_5678 - off - idle - None", } # Fake that the entity starts playing. - hass.states.async_set("media_player.entity", STATE_PLAYING) + hass.states.async_set(entry.entity_id, STATE_PLAYING) await hass.async_block_till_done() assert len(calls) == 8 assert {calls[6].data["some"], calls[7].data["some"]} == { - "playing - device - media_player.entity - idle - playing - None", - "changed_states - device - media_player.entity - idle - playing - None", + "playing - device - media_player.test_5678 - idle - playing - None", + "changed_states - device - media_player.test_5678 - idle - playing - None", } # Fake that the entity is paused. - hass.states.async_set("media_player.entity", STATE_PAUSED) + hass.states.async_set(entry.entity_id, STATE_PAUSED) await hass.async_block_till_done() assert len(calls) == 10 assert {calls[8].data["some"], calls[9].data["some"]} == { - "paused - device - media_player.entity - playing - paused - None", - "changed_states - device - media_player.entity - playing - paused - None", + "paused - device - media_player.test_5678 - playing - paused - None", + "changed_states - device - media_player.test_5678 - playing - paused - None", } # Fake that the entity is buffering. - hass.states.async_set("media_player.entity", STATE_BUFFERING) + hass.states.async_set(entry.entity_id, STATE_BUFFERING) await hass.async_block_till_done() assert len(calls) == 12 assert {calls[10].data["some"], calls[11].data["some"]} == { - "buffering - device - media_player.entity - paused - buffering - None", - "changed_states - device - media_player.entity - paused - buffering - None", + "buffering - device - media_player.test_5678 - paused - buffering - None", + "changed_states - device - media_player.test_5678 - paused - buffering - None", } -async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) -> None: - """Test for triggers firing with delay.""" - entity_id = f"{DOMAIN}.entity" - hass.states.async_set(entity_id, STATE_OFF) +async def test_if_fires_on_state_change_legacy( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: + """Test triggers firing.""" + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_OFF) + + data_template = ( + "{label} - {{{{ trigger.platform}}}} - " + "{{{{ trigger.entity_id}}}} - {{{{ trigger.from_state.state}}}} - " + "{{{{ trigger.to_state.state}}}} - {{{{ trigger.for }}}}" + ) assert await async_setup_component( hass, @@ -283,7 +357,49 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) -> "platform": "device", "domain": DOMAIN, "device_id": "", - "entity_id": entity_id, + "entity_id": entry.entity_id, + "type": "turned_on", + }, + "action": { + "service": "test.automation", + "data_template": { + "some": data_template.format(label="turned_on") + }, + }, + } + ] + }, + ) + + # Fake that the entity is turning on. + hass.states.async_set(entry.entity_id, STATE_ON) + await hass.async_block_till_done() + assert len(calls) == 1 + assert ( + calls[0].data["some"] + == "turned_on - device - media_player.test_5678 - off - on - None" + ) + + +async def test_if_fires_on_state_change_with_for( + hass: HomeAssistant, entity_registry: er.EntityRegistry, calls +) -> None: + """Test for triggers firing with delay.""" + entry = entity_registry.async_get_or_create(DOMAIN, "test", "5678") + + hass.states.async_set(entry.entity_id, STATE_OFF) + + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": { + "platform": "device", + "domain": DOMAIN, + "device_id": "", + "entity_id": entry.id, "type": "turned_on", "for": {"seconds": 5}, }, @@ -307,10 +423,9 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) -> }, ) await hass.async_block_till_done() - assert hass.states.get(entity_id).state == STATE_OFF assert len(calls) == 0 - hass.states.async_set(entity_id, STATE_ON) + hass.states.async_set(entry.entity_id, STATE_ON) await hass.async_block_till_done() assert len(calls) == 0 async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10)) @@ -318,5 +433,6 @@ async def test_if_fires_on_state_change_with_for(hass: HomeAssistant, calls) -> assert len(calls) == 1 await hass.async_block_till_done() assert ( - calls[0].data["some"] == f"turn_off device - {entity_id} - off - on - 0:00:05" + calls[0].data["some"] + == f"turn_off device - {entry.entity_id} - off - on - 0:00:05" )