ha-core/tests/components/apns/test_notify.py

396 lines
11 KiB
Python

"""The tests for the APNS component."""
import io
from unittest.mock import Mock, mock_open, patch
from apns2.errors import Unregistered
import pytest
import yaml
import homeassistant.components.apns.notify as apns
import homeassistant.components.notify as notify
from homeassistant.core import State
from homeassistant.setup import async_setup_component
from tests.common import assert_setup_component
CONFIG = {
notify.DOMAIN: {
"platform": "apns",
"name": "test_app",
"topic": "testapp.appname",
"cert_file": "test_app.pem",
}
}
@pytest.fixture(scope="module", autouse=True)
def mock_apns_notify_open():
"""Mock builtins.open for apns.notify."""
with patch("homeassistant.components.apns.notify.open", mock_open(), create=True):
yield
@patch("os.path.isfile", Mock(return_value=True))
@patch("os.access", Mock(return_value=True))
async def _setup_notify(hass_):
assert isinstance(apns.load_yaml_config_file, Mock), "Found unmocked load_yaml"
with assert_setup_component(1) as handle_config:
assert await async_setup_component(hass_, notify.DOMAIN, CONFIG)
assert handle_config[notify.DOMAIN]
@patch("os.path.isfile", return_value=True)
@patch("os.access", return_value=True)
async def test_apns_setup_full(mock_access, mock_isfile, hass):
"""Test setup with all data."""
config = {
"notify": {
"platform": "apns",
"name": "test_app",
"sandbox": "True",
"topic": "testapp.appname",
"cert_file": "test_app.pem",
}
}
with assert_setup_component(1) as handle_config:
assert await async_setup_component(hass, notify.DOMAIN, config)
assert handle_config[notify.DOMAIN]
async def test_apns_setup_missing_name(hass):
"""Test setup with missing name."""
config = {
"notify": {
"platform": "apns",
"topic": "testapp.appname",
"cert_file": "test_app.pem",
}
}
with assert_setup_component(0) as handle_config:
assert await async_setup_component(hass, notify.DOMAIN, config)
assert not handle_config[notify.DOMAIN]
async def test_apns_setup_missing_certificate(hass):
"""Test setup with missing certificate."""
config = {
"notify": {
"platform": "apns",
"name": "test_app",
"topic": "testapp.appname",
}
}
with assert_setup_component(0) as handle_config:
assert await async_setup_component(hass, notify.DOMAIN, config)
assert not handle_config[notify.DOMAIN]
async def test_apns_setup_missing_topic(hass):
"""Test setup with missing topic."""
config = {
"notify": {
"platform": "apns",
"name": "test_app",
"cert_file": "test_app.pem",
}
}
with assert_setup_component(0) as handle_config:
assert await async_setup_component(hass, notify.DOMAIN, config)
assert not handle_config[notify.DOMAIN]
@patch("homeassistant.components.apns.notify._write_device")
async def test_register_new_device(mock_write, hass):
"""Test registering a new device with a name."""
yaml_file = {5678: {"name": "test device 2"}}
written_devices = []
def fake_write(_out, device):
"""Fake write_device."""
written_devices.append(device)
mock_write.side_effect = fake_write
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
apns.DOMAIN,
"apns_test_app",
{"push_id": "1234", "name": "test device"},
blocking=True,
)
assert len(written_devices) == 1
assert written_devices[0].name == "test device"
@patch("homeassistant.components.apns.notify._write_device")
async def test_register_device_without_name(mock_write, hass):
"""Test registering a without a name."""
yaml_file = {
1234: {"name": "test device 1", "tracking_device_id": "tracking123"},
5678: {"name": "test device 2", "tracking_device_id": "tracking456"},
}
written_devices = []
def fake_write(_out, device):
"""Fake write_device."""
written_devices.append(device)
mock_write.side_effect = fake_write
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
apns.DOMAIN, "apns_test_app", {"push_id": "1234"}, blocking=True
)
devices = {dev.push_id: dev for dev in written_devices}
test_device = devices.get("1234")
assert test_device is not None
assert test_device.name is None
@patch("homeassistant.components.apns.notify._write_device")
async def test_update_existing_device(mock_write, hass):
"""Test updating an existing device."""
yaml_file = {1234: {"name": "test device 1"}, 5678: {"name": "test device 2"}}
written_devices = []
def fake_write(_out, device):
"""Fake write_device."""
written_devices.append(device)
mock_write.side_effect = fake_write
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
apns.DOMAIN,
"apns_test_app",
{"push_id": "1234", "name": "updated device 1"},
blocking=True,
)
devices = {dev.push_id: dev for dev in written_devices}
test_device_1 = devices.get("1234")
test_device_2 = devices.get("5678")
assert test_device_1 is not None
assert test_device_2 is not None
assert test_device_1.name == "updated device 1"
@patch("homeassistant.components.apns.notify._write_device")
async def test_update_existing_device_with_tracking_id(mock_write, hass):
"""Test updating an existing device that has a tracking id."""
yaml_file = {
1234: {"name": "test device 1", "tracking_device_id": "tracking123"},
5678: {"name": "test device 2", "tracking_device_id": "tracking456"},
}
written_devices = []
def fake_write(_out, device):
"""Fake write_device."""
written_devices.append(device)
mock_write.side_effect = fake_write
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
apns.DOMAIN,
"apns_test_app",
{"push_id": "1234", "name": "updated device 1"},
blocking=True,
)
devices = {dev.push_id: dev for dev in written_devices}
test_device_1 = devices.get("1234")
test_device_2 = devices.get("5678")
assert test_device_1 is not None
assert test_device_2 is not None
assert test_device_1.tracking_device_id == "tracking123"
assert test_device_2.tracking_device_id == "tracking456"
@patch("homeassistant.components.apns.notify.APNsClient")
async def test_send(mock_client, hass):
"""Test updating an existing device."""
send = mock_client.return_value.send_notification
yaml_file = {1234: {"name": "test device 1"}}
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
"notify",
"test_app",
{
"message": "Hello",
"data": {"badge": 1, "sound": "test.mp3", "category": "testing"},
},
blocking=True,
)
assert send.called
assert len(send.mock_calls) == 1
target = send.mock_calls[0][1][0]
payload = send.mock_calls[0][1][1]
assert target == "1234"
assert payload.alert == "Hello"
assert payload.badge == 1
assert payload.sound == "test.mp3"
assert payload.category == "testing"
@patch("homeassistant.components.apns.notify.APNsClient")
async def test_send_when_disabled(mock_client, hass):
"""Test updating an existing device."""
send = mock_client.return_value.send_notification
yaml_file = {1234: {"name": "test device 1", "disabled": True}}
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
"notify",
"test_app",
{
"message": "Hello",
"data": {"badge": 1, "sound": "test.mp3", "category": "testing"},
},
blocking=True,
)
assert not send.called
@patch("homeassistant.components.apns.notify.APNsClient")
async def test_send_with_state(mock_client, hass):
"""Test updating an existing device."""
send = mock_client.return_value.send_notification
yaml_file = {
1234: {"name": "test device 1", "tracking_device_id": "tracking123"},
5678: {"name": "test device 2", "tracking_device_id": "tracking456"},
}
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
), patch("os.path.isfile", Mock(return_value=True)):
notify_service = await hass.async_add_executor_job(
apns.ApnsNotificationService,
hass,
"test_app",
"testapp.appname",
False,
"test_app.pem",
)
notify_service.device_state_changed_listener(
"device_tracker.tracking456",
State("device_tracker.tracking456", None),
State("device_tracker.tracking456", "home"),
)
notify_service.send_message(message="Hello", target="home")
assert send.called
assert len(send.mock_calls) == 1
target = send.mock_calls[0][1][0]
payload = send.mock_calls[0][1][1]
assert target == "5678"
assert payload.alert == "Hello"
@patch("homeassistant.components.apns.notify.APNsClient")
@patch("homeassistant.components.apns.notify._write_device")
async def test_disable_when_unregistered(mock_write, mock_client, hass):
"""Test disabling a device when it is unregistered."""
send = mock_client.return_value.send_notification
send.side_effect = Unregistered()
yaml_file = {
1234: {"name": "test device 1", "tracking_device_id": "tracking123"},
5678: {"name": "test device 2", "tracking_device_id": "tracking456"},
}
written_devices = []
def fake_write(_out, device):
"""Fake write_device."""
written_devices.append(device)
mock_write.side_effect = fake_write
with patch(
"homeassistant.components.apns.notify.load_yaml_config_file",
Mock(return_value=yaml_file),
):
await _setup_notify(hass)
assert await hass.services.async_call(
"notify", "test_app", {"message": "Hello"}, blocking=True
)
devices = {dev.push_id: dev for dev in written_devices}
test_device_1 = devices.get("1234")
assert test_device_1 is not None
assert test_device_1.disabled is True
async def test_write_device():
"""Test writing device."""
out = io.StringIO()
device = apns.ApnsDevice("123", "name", "track_id", True)
apns._write_device(out, device)
data = yaml.safe_load(out.getvalue())
assert data == {
123: {"name": "name", "tracking_device_id": "track_id", "disabled": True}
}