Files
cyclone/backend/tests/conftest.py
T
Nora e2d4a595a4 fix(api): use request.app.state in inbox endpoints; preserve dict HTTPException detail
- inbox_lanes, inbox_dismiss_candidates, inbox_export_csv: switch
  module-level 'app' to per-request 'request.app' so per-endpoint
  state stays consistent with the test's TestClient target across
  importlib.reload() (test_api.py::test_cors_extra_origins_via_env
  reloads the api module to mutate CORS allow-lists; pre-reload
  endpoints then mutate the wrong app instance).

- _http_exc_handler: when HTTPException.detail is a dict, wrap under
  'detail' so the standard envelope stays stable and callers can
  branch on body['detail']['error'].

- conftest._auto_init_db: re-resolve cyclone.api.app each fixture
  invocation (instead of caching at module load) so the reload pattern
  doesn't leave event_bus set on a stale app.

- test_acks.test_migration_latest_idempotent_on_fresh_db: bump
  user_version assertion from 12 to 14 after auth migration renumber
  (0013 users+sessions, 0014 audit_log.user_id).

Also installs sqlcipher3 + paramiko into the backend venv so the
capability tests can run; both modules were optional deps that
test_db_crypto and test_sftp_paramiko assume are present.

Backend test results: 1008 passed, 9 skipped (gitignored prodfile
fixtures), 0 failed.
2026-06-22 16:55:55 -06:00

57 lines
2.3 KiB
Python

"""Per-test database setup for the Cyclone test suite.
Every test gets a fresh SQLite DB at ``tmp_path/test.db`` so the suite
can run in parallel and never touches the user's ``~/.local/share/cyclone``
database. ``db.init_db()`` is idempotent — tests that already call it
explicitly are unaffected (the second call short-circuits).
This fixture exists because the SQLAlchemy-backed ``CycloneStore``
requires the engine to be initialized before any DB access, whereas the
old in-memory store did not. Adding the init here keeps existing test
modules (test_api.py, test_api_835.py, test_api_gets.py,
test_api_parse_persists.py) working unchanged.
"""
from __future__ import annotations
import pytest
@pytest.fixture(autouse=True)
def _auto_init_db(tmp_path, monkeypatch):
"""Point CYCLONE_DB_URL at a per-test SQLite file and init the schema.
Also wires a fresh ``EventBus`` onto ``app.state`` because ``TestClient``
does not invoke the FastAPI lifespan handler unless used as a context
manager. The bus is reset between tests so subscribers don't leak.
Auth gating is enabled at the router/endpoint level via the
``Depends(matrix_gate)`` wiring in ``cyclone.api``. The auth tests
(``test_auth_*``) explicitly flip ``AUTH_DISABLED = False`` and
authenticate via the public login route to exercise the real
auth path. Every other test — the original test suite predates
auth — gets ``AUTH_DISABLED = True`` here so the existing tests
keep working without each one having to login first.
"""
monkeypatch.setenv("CYCLONE_DB_URL", f"sqlite:///{tmp_path}/test.db")
from cyclone import db
from cyclone.pubsub import EventBus
from cyclone.auth import deps
db._reset_for_tests()
db.init_db()
# Re-resolve `app` each fixture invocation because some tests
# (test_cors_extra_origins_via_env) call ``importlib.reload`` on
# ``cyclone.api`` to mutate the CORS allow-list. If we cached
# the app reference at conftest module load, we'd be setting
# ``event_bus`` on a stale instance that no test client is
# actually using.
from cyclone import api as _api_mod
_api_mod.app.state.event_bus = EventBus()
deps.AUTH_DISABLED = True
try:
yield
finally:
deps.AUTH_DISABLED = False
_api_mod.app.state.event_bus = None
db._reset_for_tests()