fix: test suite sent real push notifications via the developer's .env

This commit is contained in:
JesseMarkowitz
2026-08-18 14:26:05 -04:00
parent 2d5fcb26f5
commit d3745e1de4
3 changed files with 83 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
"""Shared test fixtures.
The autouse fixture here exists because of a real incident (2026-08-18): the
`sync` CLI tests invoke the actual command, which calls `load_config()`, which
calls `load_dotenv()` — so the developer's real `.env` was loaded and its
`NTFY_TOPIC` used. Every `pytest` run fired real push notifications at the
developer's phone, including a fabricated "3 conversations failed to export"
from a fixture. Nothing appeared in the log to explain it, because the tests
pass `--no-log-file`.
The lesson generalises past ntfy: any test that exercises a command end to end
inherits whatever is in `.env` unless the environment is neutralised first.
"""
import pytest
@pytest.fixture(autouse=True)
def _no_outbound_side_effects(monkeypatch):
"""Neutralise every environment variable that could reach a real service.
Set to empty/unroutable values rather than deleted: `load_dotenv` is called
with ``override=False``, which only skips keys **already present** in the
environment. Deleting a key would let the developer's `.env` put it back.
Individual tests may still `monkeypatch.setenv` these — that is how the
notification tests point at a dead local port on purpose.
"""
# Notifications: an empty topic disables sending outright (`is_configured`
# strips and checks truthiness), and the server is pointed at a closed port
# so even a test that sets its own topic cannot reach the internet.
monkeypatch.setenv("NTFY_TOPIC", "")
monkeypatch.setenv("NTFY_SERVER", "http://127.0.0.1:9")
monkeypatch.setenv("NTFY_TOKEN", "")
# Joplin: a test that reached the developer's running desktop instance would
# create or overwrite real notes in their archive.
monkeypatch.setenv("JOPLIN_API_URL", "http://127.0.0.1:9")
monkeypatch.setenv("JOPLIN_API_TOKEN", "")
+37
View File
@@ -624,3 +624,40 @@ class TestNotifySend:
monkeypatch.setenv("NTFY_TOPIC", "unit-test-topic")
monkeypatch.setenv("NTFY_NOTIFY", "off")
assert notify_mod.is_configured() is False
class TestNoRealNotificationsDuringTests:
"""Regression guard for the 2026-08-18 incident: the suite pushed to the
developer's real ntfy topic because `sync` loads `.env` via `load_dotenv`.
Asserts the conftest neutralisation holds even though a real `.env` with a
live NTFY_TOPIC sits beside the tests.
"""
def test_notifications_are_disabled(self):
from src import notify as notify_mod
assert notify_mod.is_configured() is False
def test_dotenv_cannot_reintroduce_a_topic(self):
"""`load_dotenv(override=False)` skips keys already present — including
empty ones. Deleting the var instead of emptying it would reopen this."""
import os
from dotenv import load_dotenv
from src import notify as notify_mod
load_dotenv(override=False)
assert os.getenv("NTFY_TOPIC", "").strip() == ""
assert notify_mod.is_configured() is False
def test_send_cannot_reach_the_public_server(self, monkeypatch):
"""Even a test that sets its own topic is pinned to a dead local port."""
import os
from src import notify as notify_mod
monkeypatch.setenv("NTFY_TOPIC", "some-topic")
assert "127.0.0.1" in os.getenv("NTFY_SERVER", "")
assert notify_mod.send("t", "m") is False