1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
"""The tests for the Ring platform."""
import datetime
import json
import pytest
from freezegun.api import FrozenDateTimeFactory
from ring_doorbell import Ring
from ring_doorbell.exceptions import RingError
from ring_doorbell.listen import RingEventListener
from tests.conftest import load_alert_v1, load_alert_v2, load_fixture
async def test_listen(auth, mocker):
import firebase_messaging
ring = Ring(auth)
listener = RingEventListener(ring)
await listener.start()
assert firebase_messaging.FcmPushClient.checkin_or_register.call_count == 1
assert firebase_messaging.FcmPushClient.start.call_count == 1
assert listener.subscribed is True
assert listener.started is True
with pytest.raises(RingError, match="ID 10 is not a valid callback id"):
listener.remove_notification_callback(10)
with pytest.raises(
RingError,
match="Cannot remove the default callback for ring-doorbell with value 1",
):
listener.remove_notification_callback(1)
cbid = listener.add_notification_callback(lambda: 2)
del listener._callbacks[1]
listener.remove_notification_callback(cbid)
async def test_active_dings(auth, mocker):
import firebase_messaging
ring = Ring(auth)
listener = RingEventListener(ring)
await listener.start()
assert firebase_messaging.FcmPushClient.checkin_or_register.call_count == 1
assert firebase_messaging.FcmPushClient.start.call_count == 1
assert listener.subscribed is True
assert listener.started is True
num_active = len(ring.active_alerts())
assert num_active == 0
alertstoadd = 2
for i in range(alertstoadd):
msg = load_alert_v1("doorbot_ding", 123456781, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
msg = load_alert_v2("camera_motion", 123456782, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
msg = load_alert_v1("intercom_unlock", 185036587, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
dings = ring.active_alerts()
assert len(dings) == num_active + alertstoadd * 3
# Test with the same id which should overwrite
# previous and keep the overall count the same
for i in range(alertstoadd):
msg = load_alert_v1("doorbot_ding", 123456781, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
msg = load_alert_v2("camera_motion", 123456782, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
dings = ring.active_alerts()
assert len(dings) == num_active + alertstoadd * 3
await listener.stop()
async def test_ding_expirey(auth, mocker, freezer: FrozenDateTimeFactory):
ring = Ring(auth)
listener = RingEventListener(ring)
await listener.start()
assert listener.subscribed is True
assert listener.started is True
assert len(ring.push_dings_data) == 0
assert len(ring.active_alerts()) == 0
alertstoadd = 2
for i in range(alertstoadd):
msg = load_alert_v1("doorbot_ding", 123456781, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
msg = load_alert_v2("camera_motion", 123456782, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
msg = load_alert_v1("intercom_unlock", 185036587, ding_id_inc=i)
listener._on_notification(msg, "1234567" + str(i))
assert len(ring.push_dings_data) == 6
assert len(ring.active_alerts()) == 6
freezer.tick(datetime.timedelta(minutes=5))
msg = load_alert_v1("doorbot_ding", 123456781, ding_id_inc=alertstoadd + 1)
listener._on_notification(msg, "123456781" + str(alertstoadd + 1))
assert len(ring.push_dings_data) == 1
assert len(ring.active_alerts()) == 1
@pytest.mark.nolistenmock
async def test_listen_subscribe_fail(auth, mocker, caplog, putpatch_status_fixture):
checkinmock = mocker.patch(
"firebase_messaging.FcmPushClient.checkin_or_register", return_value="foobar"
)
connectmock = mocker.patch("firebase_messaging.FcmPushClient.start")
mocker.patch("firebase_messaging.FcmPushClient.is_started", return_value=True)
putpatch_status_fixture.overrides["https://api.ring.com/clients_api/device"] = 401
ring = Ring(auth)
listener = RingEventListener(ring)
await listener.start()
# Check in gets and error so register is called
assert checkinmock.call_count == 1
assert listener.subscribed is False
assert listener.started is False
assert connectmock.call_count == 0
exp = (
"Unable to checkin to listen service, "
"response was 401 , event listener not started"
)
assert (
len(
[
record
for record in caplog.records
if record.levelname == "ERROR" and record.message == exp
]
)
== 1
)
@pytest.mark.nolistenmock
async def test_listen_gcm_fail(auth, mocker):
# Check in gets and error so register is called, the subscribe gets an error
credentials = json.loads(load_fixture("ring_listen_credentials.json"))
checkinmock = mocker.patch(
"firebase_messaging.fcmregister.FcmRegister.gcm_check_in", return_value=None
)
registermock = mocker.patch(
"firebase_messaging.fcmregister.FcmRegister.register", return_value=credentials
)
connectmock = mocker.patch("firebase_messaging.FcmPushClient.start")
mocker.patch("firebase_messaging.FcmPushClient.is_started", return_value=True)
ring = Ring(auth)
listener = RingEventListener(ring, credentials)
await listener.start()
# Check in gets and error so register is called
assert checkinmock.call_count == 1
assert registermock.call_count == 1
assert listener.subscribed is True
assert listener.started is True
assert connectmock.call_count == 1
@pytest.mark.nolistenmock
async def test_listen_fcm_fail(auth, mocker, caplog):
checkinmock = mocker.patch(
"firebase_messaging.FcmPushClient.checkin_or_register", return_value=None
)
connectmock = mocker.patch("firebase_messaging.FcmPushClient.start")
mocker.patch("firebase_messaging.FcmPushClient.is_started", return_value=True)
ring = Ring(auth)
listener = RingEventListener(ring)
await listener.start()
# Check in gets and error so register is called
assert checkinmock.call_count == 1
assert listener.subscribed is False
assert listener.started is False
assert connectmock.call_count == 0
exp = "Ring listener unable to check in to fcm, event listener not started"
assert (
len(
[
record
for record in caplog.records
if record.levelname == "ERROR" and record.message == exp
]
)
== 1
)
|