diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..72521e0 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,12 @@ +"""Shared pytest configuration. + +Ensures the repository root is on sys.path so tests can import the ``src`` +package regardless of the working directory pytest is invoked from. +""" + +import os +import sys + +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if REPO_ROOT not in sys.path: + sys.path.insert(0, REPO_ROOT) diff --git a/tests/test_matrix_formatting.py b/tests/test_matrix_formatting.py new file mode 100644 index 0000000..ed1c082 --- /dev/null +++ b/tests/test_matrix_formatting.py @@ -0,0 +1,98 @@ +"""Assert-based tests for Matrix message formatting. + +Matrix clients only render formatting from an HTML ``formatted_body``; Markdown +in the plain ``body`` shows as literal characters. These tests lock in that the +notifier emits real HTML plus a clean plain-text fallback, and that untrusted +station data is HTML-escaped. +""" + +import datetime + +from src.alerting import AlertLevel, MatrixNotifier, WaterAlert, markdown_to_matrix_html, strip_markdown + + +class _FakeResponse: + def raise_for_status(self): + pass + + def json(self): + return {"event_id": "$test"} + + +def _notifier_capturing(captured): + """A MatrixNotifier whose HTTP PUT records the JSON payload into ``captured``.""" + notifier = MatrixNotifier("https://hs.example", "token", "!room:hs.example") + + def fake_put(url, headers=None, json=None, timeout=None): + captured.update(json) + return _FakeResponse() + + notifier.session.put = fake_put + return notifier + + +def test_bold_becomes_strong(): + assert markdown_to_matrix_html("**hi**") == "hi" + + +def test_url_is_linkified(): + out = markdown_to_matrix_html("see https://x.example/z") + assert 'https://x.example/z' in out + + +def test_newlines_become_br(): + assert markdown_to_matrix_html("a\nb") == "a
b" + + +def test_html_is_escaped(): + out = markdown_to_matrix_html("