added ntfy support for scheduled runs
This commit is contained in:
@@ -535,3 +535,92 @@ class TestNonInteractiveTosGate:
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
assert "no terminal to" in result.output
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ntfy notifications
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestNotifyFormatting:
|
||||
"""The payload must stay counts-only: a public ntfy topic is world-readable."""
|
||||
|
||||
def test_success_summary(self):
|
||||
from src.notify import format_summary
|
||||
|
||||
title, body, tags, priority = format_summary(
|
||||
{"codex": {"exported": 2, "skipped": 5, "failed": 0}}, None, []
|
||||
)
|
||||
assert title.startswith("AI archive OK")
|
||||
assert "codex: 2 exported, 5 up to date" in body
|
||||
assert tags == "white_check_mark"
|
||||
assert priority == "default"
|
||||
|
||||
def test_quiet_run_is_low_priority(self):
|
||||
from src.notify import format_summary
|
||||
|
||||
_, _, tags, priority = format_summary(
|
||||
{"codex": {"exported": 0, "skipped": 7, "failed": 0}}, None, []
|
||||
)
|
||||
assert tags == "zzz"
|
||||
assert priority == "low"
|
||||
|
||||
def test_failure_summary_is_high_priority(self):
|
||||
from src.notify import format_summary
|
||||
|
||||
title, body, tags, priority = format_summary(
|
||||
{"chatgpt": {"exported": 0, "skipped": 0, "failed": 12}},
|
||||
None,
|
||||
["chatgpt: 12 conversation(s) failed to export"],
|
||||
)
|
||||
assert "FAILED" in title
|
||||
assert "12 FAILED" in body
|
||||
assert tags == "rotating_light"
|
||||
assert priority == "high"
|
||||
|
||||
def test_hostname_present(self):
|
||||
"""Two machines share one topic — counts are meaningless without it."""
|
||||
from src.notify import format_summary, machine_name
|
||||
|
||||
title, _, _, _ = format_summary({}, None, [])
|
||||
assert machine_name() in title
|
||||
|
||||
|
||||
class TestNotifyHeaderEncoding:
|
||||
"""HTTP headers are latin-1; an em dash in a title loses the notification."""
|
||||
|
||||
def test_smart_punctuation_flattened(self):
|
||||
from src.notify import _ascii_header
|
||||
|
||||
out = _ascii_header("AI archive — don’t “fail”…")
|
||||
assert out == 'AI archive - don\'t "fail"...'
|
||||
out.encode("ascii") # must not raise
|
||||
|
||||
def test_arbitrary_unicode_survives_as_ascii(self):
|
||||
from src.notify import _ascii_header
|
||||
|
||||
_ascii_header("héllo — 世界").encode("ascii")
|
||||
|
||||
|
||||
class TestNotifySend:
|
||||
def test_no_topic_is_a_no_op(self, monkeypatch):
|
||||
from src import notify as notify_mod
|
||||
|
||||
monkeypatch.delenv("NTFY_TOPIC", raising=False)
|
||||
assert notify_mod.send("t", "m") is False
|
||||
assert notify_mod.is_configured() is False
|
||||
|
||||
def test_network_failure_never_raises(self, monkeypatch):
|
||||
"""A down ntfy server must not fail a run that captured data."""
|
||||
from src import notify as notify_mod
|
||||
|
||||
monkeypatch.setenv("NTFY_TOPIC", "unit-test-topic")
|
||||
monkeypatch.setenv("NTFY_SERVER", "http://127.0.0.1:9")
|
||||
assert notify_mod.send("t", "m") is False
|
||||
|
||||
def test_off_policy_disables(self, monkeypatch):
|
||||
from src import notify as notify_mod
|
||||
|
||||
monkeypatch.setenv("NTFY_TOPIC", "unit-test-topic")
|
||||
monkeypatch.setenv("NTFY_NOTIFY", "off")
|
||||
assert notify_mod.is_configured() is False
|
||||
|
||||
Reference in New Issue
Block a user