Migrate demo notify platform (#115448)
* Migrate demo notify platform * Update homeassistant/components/demo/notify.py Co-authored-by: Paulus Schoutsen <balloob@gmail.com> * Remove no needed tests * Cleanup redundant attribute assignment --------- Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
5e8b46c670
commit
36bdda5669
3 changed files with 67 additions and 184 deletions
|
@ -38,6 +38,7 @@ COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM = [
|
||||||
Platform.LIGHT,
|
Platform.LIGHT,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
Platform.MEDIA_PLAYER,
|
Platform.MEDIA_PLAYER,
|
||||||
|
Platform.NOTIFY,
|
||||||
Platform.NUMBER,
|
Platform.NUMBER,
|
||||||
Platform.SELECT,
|
Platform.SELECT,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
|
@ -55,7 +56,6 @@ COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM = [
|
||||||
COMPONENTS_WITH_DEMO_PLATFORM = [
|
COMPONENTS_WITH_DEMO_PLATFORM = [
|
||||||
Platform.TTS,
|
Platform.TTS,
|
||||||
Platform.MAILBOX,
|
Platform.MAILBOX,
|
||||||
Platform.NOTIFY,
|
|
||||||
Platform.IMAGE_PROCESSING,
|
Platform.IMAGE_PROCESSING,
|
||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,38 +1,44 @@
|
||||||
"""Demo notification service."""
|
"""Demo notification entity."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from homeassistant.components.notify import DOMAIN, NotifyEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.components.notify import BaseNotificationService
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
EVENT_NOTIFY = "notify"
|
EVENT_NOTIFY = "notify"
|
||||||
|
|
||||||
|
|
||||||
def get_service(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: ConfigType,
|
config_entry: ConfigEntry,
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> BaseNotificationService:
|
) -> None:
|
||||||
"""Get the demo notification service."""
|
"""Set up the demo entity platform."""
|
||||||
return DemoNotificationService(hass)
|
async_add_entities([DemoNotifyEntity(unique_id="notify", device_name="Notifier")])
|
||||||
|
|
||||||
|
|
||||||
class DemoNotificationService(BaseNotificationService):
|
class DemoNotifyEntity(NotifyEntity):
|
||||||
"""Implement demo notification service."""
|
"""Implement demo notification platform."""
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
_attr_has_entity_name = True
|
||||||
"""Initialize the service."""
|
_attr_name = None
|
||||||
self.hass = hass
|
|
||||||
|
|
||||||
@property
|
def __init__(
|
||||||
def targets(self) -> dict[str, str]:
|
self,
|
||||||
"""Return a dictionary of registered targets."""
|
unique_id: str,
|
||||||
return {"test target name": "test target id"}
|
device_name: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the Demo button entity."""
|
||||||
|
self._attr_unique_id = unique_id
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, unique_id)},
|
||||||
|
name=device_name,
|
||||||
|
)
|
||||||
|
|
||||||
def send_message(self, message: str = "", **kwargs: Any) -> None:
|
async def async_send_message(self, message: str) -> None:
|
||||||
"""Send a message to a user."""
|
"""Send a message to a user."""
|
||||||
kwargs["message"] = message
|
event_notitifcation = {"message": message}
|
||||||
self.hass.bus.fire(EVENT_NOTIFY, kwargs)
|
self.hass.bus.async_fire(EVENT_NOTIFY, event_notitifcation)
|
||||||
|
|
|
@ -1,29 +1,43 @@
|
||||||
"""The tests for the notify demo platform."""
|
"""The tests for the notify demo platform."""
|
||||||
|
|
||||||
import logging
|
from collections.abc import Generator
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components import notify
|
from homeassistant.components import notify
|
||||||
|
from homeassistant.components.demo import DOMAIN
|
||||||
import homeassistant.components.demo.notify as demo
|
import homeassistant.components.demo.notify as demo
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.const import Platform
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from tests.common import assert_setup_component, async_capture_events
|
from tests.common import MockConfigEntry, async_capture_events
|
||||||
|
|
||||||
CONFIG = {notify.DOMAIN: {"platform": "demo"}}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
|
||||||
def autouse_disable_platforms(disable_platforms):
|
|
||||||
"""Auto use the disable_platforms fixture."""
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def events(hass):
|
def notify_only() -> Generator[None, None]:
|
||||||
|
"""Enable only the notify platform."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.demo.COMPONENTS_WITH_CONFIG_ENTRY_DEMO_PLATFORM",
|
||||||
|
[Platform.NOTIFY],
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
async def setup_notify(hass: HomeAssistant, notify_only: None) -> None:
|
||||||
|
"""Initialize setup demo Notify entity."""
|
||||||
|
entry = MockConfigEntry(domain=DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("notify.notifier")
|
||||||
|
assert state is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def events(hass: HomeAssistant) -> list[Event]:
|
||||||
"""Fixture that catches notify events."""
|
"""Fixture that catches notify events."""
|
||||||
return async_capture_events(hass, demo.EVENT_NOTIFY)
|
return async_capture_events(hass, demo.EVENT_NOTIFY)
|
||||||
|
|
||||||
|
@ -46,104 +60,26 @@ def record_calls(calls):
|
||||||
return record_calls
|
return record_calls
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="mock_demo_notify")
|
async def test_sending_message(hass: HomeAssistant, events: list[Event]) -> None:
|
||||||
def mock_demo_notify_fixture():
|
"""Test sending a message."""
|
||||||
"""Mock demo notify service."""
|
|
||||||
with patch("homeassistant.components.demo.notify.get_service", autospec=True) as ns:
|
|
||||||
yield ns
|
|
||||||
|
|
||||||
|
|
||||||
async def setup_notify(hass):
|
|
||||||
"""Test setup."""
|
|
||||||
with assert_setup_component(1, notify.DOMAIN) as config:
|
|
||||||
assert await async_setup_component(hass, notify.DOMAIN, CONFIG)
|
|
||||||
assert config[notify.DOMAIN]
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
|
|
||||||
async def test_no_notify_service(
|
|
||||||
hass: HomeAssistant, mock_demo_notify, caplog: pytest.LogCaptureFixture
|
|
||||||
) -> None:
|
|
||||||
"""Test missing platform notify service instance."""
|
|
||||||
caplog.set_level(logging.ERROR)
|
|
||||||
mock_demo_notify.return_value = None
|
|
||||||
await setup_notify(hass)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert mock_demo_notify.called
|
|
||||||
assert "Failed to initialize notification service demo" in caplog.text
|
|
||||||
|
|
||||||
|
|
||||||
async def test_discover_notify(hass: HomeAssistant, mock_demo_notify) -> None:
|
|
||||||
"""Test discovery of notify demo platform."""
|
|
||||||
assert notify.DOMAIN not in hass.config.components
|
|
||||||
mock_demo_notify.return_value = None
|
|
||||||
await discovery.async_load_platform(
|
|
||||||
hass, "notify", "demo", {"test_key": "test_val"}, {"notify": {}}
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert notify.DOMAIN in hass.config.components
|
|
||||||
assert mock_demo_notify.called
|
|
||||||
assert mock_demo_notify.mock_calls[0][1] == (
|
|
||||||
hass,
|
|
||||||
{},
|
|
||||||
{"test_key": "test_val"},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_sending_none_message(hass: HomeAssistant, events) -> None:
|
|
||||||
"""Test send with None as message."""
|
|
||||||
await setup_notify(hass)
|
|
||||||
with pytest.raises(vol.Invalid):
|
|
||||||
await hass.services.async_call(
|
|
||||||
notify.DOMAIN, notify.SERVICE_NOTIFY, {notify.ATTR_MESSAGE: None}
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert len(events) == 0
|
|
||||||
|
|
||||||
|
|
||||||
async def test_sending_templated_message(hass: HomeAssistant, events) -> None:
|
|
||||||
"""Send a templated message."""
|
|
||||||
await setup_notify(hass)
|
|
||||||
hass.states.async_set("sensor.temperature", 10)
|
|
||||||
data = {
|
data = {
|
||||||
notify.ATTR_MESSAGE: "{{states.sensor.temperature.state}}",
|
"entity_id": "notify.notifier",
|
||||||
notify.ATTR_TITLE: "{{ states.sensor.temperature.name }}",
|
notify.ATTR_MESSAGE: "Test message",
|
||||||
}
|
}
|
||||||
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_NOTIFY, data)
|
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_SEND_MESSAGE, data)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
last_event = events[-1]
|
last_event = events[-1]
|
||||||
assert last_event.data[notify.ATTR_TITLE] == "temperature"
|
assert last_event.data[notify.ATTR_MESSAGE] == "Test message"
|
||||||
assert last_event.data[notify.ATTR_MESSAGE] == "10"
|
|
||||||
|
|
||||||
|
|
||||||
async def test_method_forwards_correct_data(hass: HomeAssistant, events) -> None:
|
async def test_calling_notify_from_script_loaded_from_yaml(
|
||||||
"""Test that all data from the service gets forwarded to service."""
|
hass: HomeAssistant, events: list[Event]
|
||||||
await setup_notify(hass)
|
|
||||||
data = {
|
|
||||||
notify.ATTR_MESSAGE: "my message",
|
|
||||||
notify.ATTR_TITLE: "my title",
|
|
||||||
notify.ATTR_DATA: {"hello": "world"},
|
|
||||||
}
|
|
||||||
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_NOTIFY, data)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert len(events) == 1
|
|
||||||
data = events[0].data
|
|
||||||
assert {
|
|
||||||
"message": "my message",
|
|
||||||
"title": "my title",
|
|
||||||
"data": {"hello": "world"},
|
|
||||||
} == data
|
|
||||||
|
|
||||||
|
|
||||||
async def test_calling_notify_from_script_loaded_from_yaml_without_title(
|
|
||||||
hass: HomeAssistant, events
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if we can call a notify from a script."""
|
"""Test if we can call a notify from a script."""
|
||||||
await setup_notify(hass)
|
|
||||||
step = {
|
step = {
|
||||||
"service": "notify.notify",
|
"service": "notify.send_message",
|
||||||
"data": {
|
"data": {
|
||||||
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}}
|
"entity_id": "notify.notifier",
|
||||||
},
|
},
|
||||||
"data_template": {"message": "Test 123 {{ 2 + 2 }}\n"},
|
"data_template": {"message": "Test 123 {{ 2 + 2 }}\n"},
|
||||||
}
|
}
|
||||||
|
@ -155,63 +91,4 @@ async def test_calling_notify_from_script_loaded_from_yaml_without_title(
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
assert {
|
assert {
|
||||||
"message": "Test 123 4",
|
"message": "Test 123 4",
|
||||||
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}},
|
|
||||||
} == events[0].data
|
} == events[0].data
|
||||||
|
|
||||||
|
|
||||||
async def test_calling_notify_from_script_loaded_from_yaml_with_title(
|
|
||||||
hass: HomeAssistant, events
|
|
||||||
) -> None:
|
|
||||||
"""Test if we can call a notify from a script."""
|
|
||||||
await setup_notify(hass)
|
|
||||||
step = {
|
|
||||||
"service": "notify.notify",
|
|
||||||
"data": {
|
|
||||||
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}}
|
|
||||||
},
|
|
||||||
"data_template": {"message": "Test 123 {{ 2 + 2 }}\n", "title": "Test"},
|
|
||||||
}
|
|
||||||
await async_setup_component(
|
|
||||||
hass, "script", {"script": {"test": {"sequence": step}}}
|
|
||||||
)
|
|
||||||
await hass.services.async_call("script", "test")
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
assert len(events) == 1
|
|
||||||
assert {
|
|
||||||
"message": "Test 123 4",
|
|
||||||
"title": "Test",
|
|
||||||
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}},
|
|
||||||
} == events[0].data
|
|
||||||
|
|
||||||
|
|
||||||
async def test_targets_are_services(hass: HomeAssistant) -> None:
|
|
||||||
"""Test that all targets are exposed as individual services."""
|
|
||||||
await setup_notify(hass)
|
|
||||||
assert hass.services.has_service("notify", "demo") is not None
|
|
||||||
service = "demo_test_target_name"
|
|
||||||
assert hass.services.has_service("notify", service) is not None
|
|
||||||
|
|
||||||
|
|
||||||
async def test_messages_to_targets_route(
|
|
||||||
hass: HomeAssistant, calls, record_calls
|
|
||||||
) -> None:
|
|
||||||
"""Test message routing to specific target services."""
|
|
||||||
await setup_notify(hass)
|
|
||||||
hass.bus.async_listen_once("notify", record_calls)
|
|
||||||
|
|
||||||
await hass.services.async_call(
|
|
||||||
"notify",
|
|
||||||
"demo_test_target_name",
|
|
||||||
{"message": "my message", "title": "my title", "data": {"hello": "world"}},
|
|
||||||
)
|
|
||||||
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
data = calls[0][0].data
|
|
||||||
|
|
||||||
assert {
|
|
||||||
"message": "my message",
|
|
||||||
"target": ["test target id"],
|
|
||||||
"title": "my title",
|
|
||||||
"data": {"hello": "world"},
|
|
||||||
} == data
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue