import pytest from unittest.mock import patch, MagicMock from openvpncertupdate import send_email def make_popen(returncode=0): proc = MagicMock() proc.communicate.return_value = (b"", b"") proc.returncode = returncode return proc def test_calls_mail_binary(tmp_path): tmpl = tmp_path / "t.txt"; tmpl.write_text("{cn} {url} {config_name}") att = tmp_path / "c.ovpn"; att.write_text("x") captured = {} def fake_popen(cmd, **kw): captured["cmd"] = cmd; return make_popen() with patch("openvpncertupdate.subprocess.Popen", side_effect=fake_popen): send_email("to@x.com", "alice", "http://u", str(att), "f@x.com", "Subj", str(tmpl), "msmtp") assert captured["cmd"] == ["msmtp", "-t"] def test_body_contains_cn_and_url(tmp_path): tmpl = tmp_path / "t.txt"; tmpl.write_text("Dear {cn}, see {url} for {config_name}") att = tmp_path / "c.ovpn"; att.write_text("") received = {} def fake_popen(cmd, **kw): p = MagicMock() p.communicate = lambda input=None: (received.update({"data": input}) or b"", b"") p.returncode = 0 return p with patch("openvpncertupdate.subprocess.Popen", side_effect=fake_popen): send_email("to@x.com", "bob", "http://secret", str(att), "f@x.com", "s", str(tmpl), "msmtp") body = received["data"].decode() assert "bob" in body assert "http://secret" in body def test_raises_on_failure(tmp_path): tmpl = tmp_path / "t.txt"; tmpl.write_text("{cn} {url} {config_name}") att = tmp_path / "c.ovpn"; att.write_text("") with patch("openvpncertupdate.subprocess.Popen", return_value=make_popen(returncode=1)): with pytest.raises(RuntimeError, match="mail"): send_email("x@y.com", "cn", "url", str(att), "f@x.com", "s", str(tmpl), "msmtp")