96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
import unittest
|
|
from pathlib import Path
|
|
from tempfile import TemporaryDirectory
|
|
from unittest.mock import patch
|
|
|
|
from lib._zyxel import ZyxelRouter, normalize_mac
|
|
from lib._arrival_detection import ArrivalDetector, _notify
|
|
|
|
|
|
class ArrivalDetectorTests(unittest.TestCase):
|
|
def test_starting_present_does_not_emit_arrival(self):
|
|
detector = ArrivalDetector(absent_after=2, present_after=2)
|
|
self.assertFalse(detector.sample(True))
|
|
self.assertFalse(detector.sample(True))
|
|
|
|
def test_emits_only_after_absence_and_debounced_presence(self):
|
|
detector = ArrivalDetector(absent_after=2, present_after=2)
|
|
for value in (False, False, True):
|
|
self.assertFalse(detector.sample(value))
|
|
self.assertTrue(detector.sample(True))
|
|
self.assertFalse(detector.sample(True))
|
|
|
|
def test_single_missed_poll_does_not_mark_absent(self):
|
|
detector = ArrivalDetector(absent_after=2, present_after=1)
|
|
detector.sample(True)
|
|
self.assertFalse(detector.sample(False))
|
|
self.assertFalse(detector.sample(True))
|
|
|
|
|
|
class MacTests(unittest.TestCase):
|
|
def test_normalizes_common_formats(self):
|
|
self.assertEqual(normalize_mac("AA-BB-CC-DD-EE-FF"), "aa:bb:cc:dd:ee:ff")
|
|
|
|
def test_rejects_invalid_mac(self):
|
|
with self.assertRaises(ValueError):
|
|
normalize_mac("not-a-mac")
|
|
|
|
def test_parses_ex5601_nested_lanhosts_response(self):
|
|
router = ZyxelRouter("192.0.2.1", "user", "password")
|
|
router.dal_get = lambda _oid: {
|
|
"result": "ZCFG_SUCCESS",
|
|
"Object": [
|
|
{
|
|
"lanhosts": [
|
|
{
|
|
"PhysAddress": "2C:DB:07:50:2B:5C",
|
|
"Active": True,
|
|
"HostName": "workstation",
|
|
"IPAddress": "192.168.178.10",
|
|
}
|
|
]
|
|
}
|
|
],
|
|
}
|
|
hosts = router.get_lan_hosts()
|
|
self.assertEqual(len(hosts), 1)
|
|
self.assertEqual(hosts[0].mac, "2c:db:07:50:2b:5c")
|
|
self.assertTrue(router.is_connected("2c-db-07-50-2b-5c"))
|
|
|
|
|
|
class NotificationTests(unittest.TestCase):
|
|
@patch("lib._arrival_detection.send_notification")
|
|
def test_uses_notify_module(self, send_notification):
|
|
config = {
|
|
"notification": {
|
|
"enabled": True,
|
|
"message": "Welcome home, {name} ({mac})",
|
|
"topic_url": "https://ntfy.example/home",
|
|
"timeout": 4,
|
|
}
|
|
}
|
|
_notify(config, {"name": "Ignace", "mac": "aa:bb:cc:dd:ee:ff"})
|
|
send_notification.assert_called_once_with(
|
|
"Welcome home, Ignace (aa:bb:cc:dd:ee:ff)",
|
|
topic_url="https://ntfy.example/home",
|
|
timeout=4.0,
|
|
)
|
|
|
|
@patch("lib._arrival_detection.send_notification")
|
|
def test_appends_notification_to_event_log(self, send_notification):
|
|
with TemporaryDirectory() as directory:
|
|
event_log = Path(directory) / "arrivals.txt"
|
|
config = {
|
|
"notification": {
|
|
"enabled": True,
|
|
"message": "{name} arrived home",
|
|
"event_log": str(event_log),
|
|
}
|
|
}
|
|
_notify(config, {"name": "Ignace", "mac": "aa:bb:cc:dd:ee:ff"})
|
|
self.assertTrue(event_log.read_text().endswith(" Ignace arrived home\n"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|