"""Tests for the operator-notification mechanism (harness/notify.py).""" from harness.notify import announce_experiment_once def _summary(tmp_path, text="experiment X: faster cuts"): p = tmp_path / "CURRENT_EXPERIMENT.md" p.write_text(text, encoding="utf-8") return p def test_sends_once_then_dedups(tmp_path): sent = [] summary = _summary(tmp_path) state = tmp_path / "state" def send(chat_id, text): sent.append((chat_id, text)) first = announce_experiment_once(summary_path=summary, admin_chat_id="123", send_text=send, state_dir=state) second = announce_experiment_once(summary_path=summary, admin_chat_id="123", send_text=send, state_dir=state) assert first is True and second is False assert len(sent) == 1 assert sent[0][0] == "123" assert "experiment X" in sent[0][1] def test_new_summary_sends_again(tmp_path): sent = [] state = tmp_path / "state" s1 = _summary(tmp_path, "first") announce_experiment_once(summary_path=s1, admin_chat_id="1", send_text=lambda c, t: sent.append(t), state_dir=state) s1.write_text("second — different experiment", encoding="utf-8") announce_experiment_once(summary_path=s1, admin_chat_id="1", send_text=lambda c, t: sent.append(t), state_dir=state) assert len(sent) == 2 # content changed → new announcement def test_no_chat_id_is_noop(tmp_path): sent = [] announce_experiment_once(summary_path=_summary(tmp_path), admin_chat_id="", send_text=lambda c, t: sent.append(t), state_dir=tmp_path / "s") assert sent == [] def test_missing_summary_is_noop(tmp_path): sent = [] announce_experiment_once(summary_path=tmp_path / "nope.md", admin_chat_id="1", send_text=lambda c, t: sent.append(t), state_dir=tmp_path / "s") assert sent == [] def test_send_failure_is_swallowed(tmp_path): def boom(chat_id, text): raise RuntimeError("telegram down") # Must not raise; returns False. ok = announce_experiment_once(summary_path=_summary(tmp_path), admin_chat_id="1", send_text=boom, state_dir=tmp_path / "s") assert ok is False