diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..46bc87f --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,18 @@ +"""Shared pytest fixtures for the Peregrine test suite.""" +import pytest + + +@pytest.fixture(autouse=True) +def reset_rate_limiter(): + """Reset slowapi state before each test. + + Each importlib.reload(dev_api) re-applies @limiter.limit() decorators, + accumulating stale registrations in _route_limits on the shared limiter + singleton. One real request then triggers N limit-checks (N = reload count), + exhausting per-hour budgets prematurely. Clearing both _storage and + _route_limits before each test gives each test a clean slate. + """ + from scripts.rate_limit import limiter + limiter._storage.reset() + limiter._route_limits.clear() + yield diff --git a/tests/test_dev_api_prep.py b/tests/test_dev_api_prep.py index 4a5f964..0584f3f 100644 --- a/tests/test_dev_api_prep.py +++ b/tests/test_dev_api_prep.py @@ -5,11 +5,12 @@ from fastapi.testclient import TestClient @pytest.fixture -def client(): - import sys - sys.path.insert(0, "/Library/Development/CircuitForge/peregrine/.worktrees/feature-vue-spa") - from dev_api import app - return TestClient(app) +def client(monkeypatch): + import importlib + monkeypatch.delenv("DEMO_MODE", raising=False) + import dev_api + importlib.reload(dev_api) + return TestClient(dev_api.app) # ── /api/jobs/{id}/research ─────────────────────────────────────────────────