Skip to content

Commit 76fefaa

Browse files
authored
Move out demo notify tests to the notify platform (#115504)
* Move test file * Make independent of demo platform * Restore tests for demo platform for coverage
1 parent 0d0b77c commit 76fefaa

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
"""The tests for legacy notify services."""
2+
3+
from collections.abc import Mapping
4+
from pathlib import Path
5+
from typing import Any
6+
from unittest.mock import MagicMock
7+
8+
import pytest
9+
import voluptuous as vol
10+
11+
from homeassistant.components import notify
12+
from homeassistant.core import HomeAssistant
13+
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
14+
from homeassistant.setup import async_setup_component
15+
16+
from tests.common import MockPlatform, mock_platform
17+
18+
19+
class MockNotifyPlatform(MockPlatform):
20+
"""Help to set up a legacy test notify service."""
21+
22+
def __init__(self, async_get_service: Any = None, get_service: Any = None) -> None:
23+
"""Return a legacy notify service."""
24+
super().__init__()
25+
if get_service:
26+
self.get_service = get_service
27+
if async_get_service:
28+
self.async_get_service = async_get_service
29+
30+
31+
def mock_notify_platform(
32+
hass: HomeAssistant,
33+
tmp_path: Path,
34+
integration: str = "notify",
35+
async_get_service: Any = None,
36+
get_service: Any = None,
37+
):
38+
"""Specialize the mock platform for legacy notify service."""
39+
loaded_platform = MockNotifyPlatform(async_get_service, get_service)
40+
mock_platform(hass, f"{integration}.notify", loaded_platform)
41+
42+
return loaded_platform
43+
44+
45+
async def help_setup_notify(
46+
hass: HomeAssistant, tmp_path: Path, targets: dict[str, None] | None = None
47+
) -> MagicMock:
48+
"""Help set up a platform notify service."""
49+
send_message_mock = MagicMock()
50+
51+
class _TestNotifyService(notify.BaseNotificationService):
52+
def __init__(self, targets: dict[str, None] | None) -> None:
53+
"""Initialize service."""
54+
self._targets = targets
55+
super().__init__()
56+
57+
@property
58+
def targets(self) -> Mapping[str, Any] | None:
59+
"""Return a dictionary of registered targets."""
60+
return self._targets
61+
62+
def send_message(self, message: str, **kwargs: Any) -> None:
63+
"""Send a message."""
64+
send_message_mock(message, kwargs)
65+
66+
async def async_get_service(
67+
hass: HomeAssistant,
68+
config: ConfigType,
69+
discovery_info: DiscoveryInfoType | None = None,
70+
) -> notify.BaseNotificationService:
71+
"""Get notify service for mocked platform."""
72+
return _TestNotifyService(targets)
73+
74+
# Mock platform with service
75+
mock_notify_platform(hass, tmp_path, "test", async_get_service=async_get_service)
76+
# Setup the platform
77+
await async_setup_component(hass, "notify", {"notify": [{"platform": "test"}]})
78+
await hass.async_block_till_done()
79+
80+
# Return mock for assertion service calls
81+
return send_message_mock
82+
83+
84+
async def test_sending_none_message(hass: HomeAssistant, tmp_path: Path) -> None:
85+
"""Test send with None as message."""
86+
send_message_mock = await help_setup_notify(hass, tmp_path)
87+
with pytest.raises(vol.Invalid) as exc:
88+
await hass.services.async_call(
89+
notify.DOMAIN, notify.SERVICE_NOTIFY, {notify.ATTR_MESSAGE: None}
90+
)
91+
await hass.async_block_till_done()
92+
assert (
93+
str(exc.value)
94+
== "template value is None for dictionary value @ data['message']"
95+
)
96+
send_message_mock.assert_not_called()
97+
98+
99+
async def test_sending_templated_message(hass: HomeAssistant, tmp_path: Path) -> None:
100+
"""Send a templated message."""
101+
send_message_mock = await help_setup_notify(hass, tmp_path)
102+
hass.states.async_set("sensor.temperature", 10)
103+
data = {
104+
notify.ATTR_MESSAGE: "{{states.sensor.temperature.state}}",
105+
notify.ATTR_TITLE: "{{ states.sensor.temperature.name }}",
106+
}
107+
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_NOTIFY, data)
108+
await hass.async_block_till_done()
109+
send_message_mock.assert_called_once_with(
110+
"10", {"title": "temperature", "data": None}
111+
)
112+
113+
114+
async def test_method_forwards_correct_data(
115+
hass: HomeAssistant, tmp_path: Path
116+
) -> None:
117+
"""Test that all data from the service gets forwarded to service."""
118+
send_message_mock = await help_setup_notify(hass, tmp_path)
119+
data = {
120+
notify.ATTR_MESSAGE: "my message",
121+
notify.ATTR_TITLE: "my title",
122+
notify.ATTR_DATA: {"hello": "world"},
123+
}
124+
await hass.services.async_call(notify.DOMAIN, notify.SERVICE_NOTIFY, data)
125+
await hass.async_block_till_done()
126+
send_message_mock.assert_called_once_with(
127+
"my message", {"title": "my title", "data": {"hello": "world"}}
128+
)
129+
130+
131+
async def test_calling_notify_from_script_loaded_from_yaml_without_title(
132+
hass: HomeAssistant, tmp_path: Path
133+
) -> None:
134+
"""Test if we can call a notify from a script."""
135+
send_message_mock = await help_setup_notify(hass, tmp_path)
136+
step = {
137+
"service": "notify.notify",
138+
"data": {
139+
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}}
140+
},
141+
"data_template": {"message": "Test 123 {{ 2 + 2 }}\n"},
142+
}
143+
await async_setup_component(
144+
hass, "script", {"script": {"test": {"sequence": step}}}
145+
)
146+
await hass.services.async_call("script", "test")
147+
await hass.async_block_till_done()
148+
send_message_mock.assert_called_once_with(
149+
"Test 123 4",
150+
{"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}}},
151+
)
152+
153+
154+
async def test_calling_notify_from_script_loaded_from_yaml_with_title(
155+
hass: HomeAssistant, tmp_path: Path
156+
) -> None:
157+
"""Test if we can call a notify from a script."""
158+
send_message_mock = await help_setup_notify(hass, tmp_path)
159+
step = {
160+
"service": "notify.notify",
161+
"data": {
162+
"data": {"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}}
163+
},
164+
"data_template": {"message": "Test 123 {{ 2 + 2 }}\n", "title": "Test"},
165+
}
166+
await async_setup_component(
167+
hass, "script", {"script": {"test": {"sequence": step}}}
168+
)
169+
await hass.services.async_call("script", "test")
170+
await hass.async_block_till_done()
171+
send_message_mock.assert_called_once_with(
172+
"Test 123 4",
173+
{
174+
"title": "Test",
175+
"data": {
176+
"push": {"sound": "US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"}
177+
},
178+
},
179+
)
180+
181+
182+
async def test_targets_are_services(hass: HomeAssistant, tmp_path: Path) -> None:
183+
"""Test that all targets are exposed as individual services."""
184+
await help_setup_notify(hass, tmp_path, targets={"a": 1, "b": 2})
185+
assert hass.services.has_service("notify", "notify") is not None
186+
assert hass.services.has_service("notify", "test_a") is not None
187+
assert hass.services.has_service("notify", "test_b") is not None
188+
189+
190+
async def test_messages_to_targets_route(hass: HomeAssistant, tmp_path: Path) -> None:
191+
"""Test message routing to specific target services."""
192+
send_message_mock = await help_setup_notify(
193+
hass, tmp_path, targets={"target_name": "test target id"}
194+
)
195+
196+
await hass.services.async_call(
197+
"notify",
198+
"test_target_name",
199+
{"message": "my message", "title": "my title", "data": {"hello": "world"}},
200+
)
201+
await hass.async_block_till_done()
202+
203+
send_message_mock.assert_called_once_with(
204+
"my message",
205+
{"target": ["test target id"], "title": "my title", "data": {"hello": "world"}},
206+
)

0 commit comments

Comments
 (0)