The backend had zero tests. This adds 33, all pure (no DB, no network), plus the harness to run them in the gate: - backend/Dockerfile.test: the app's deps + pinned pytest/ruff, code bind-mounted at run time so it always tests the working tree. Isolated from the prod Dockerfile, so the published image never carries test tooling. - requirements-dev.txt: pytest==8.4.2, ruff==0.15.21 (the version the gate already runs) — the backend lane is now pinned, not just host-global. - tests: normalize_title (de-shout, hashtag strip, emoji drop, trilingual letters survive); storage sanitize/rel_path/download_filename and the safe_abs_path traversal guard (../ and absolute-path escapes rejected — verified by mutation); links HMAC grants (round-trip, wrong-token, tampered sig/exp, expiry) + is_expired; a DB-free app-assembly smoke (every router wires up, OpenAPI generates). DB-backed router smoke (auth/feed/downloads) needs a test Postgres + migrations — deferred. useCardPager needs hook-test infra (jsdom/renderHook) — deferred.
13 lines
812 B
Docker
13 lines
812 B
Docker
# Test-only image — the app's Python deps + pytest/ruff, and NOTHING else. Code is bind-mounted at
|
|
# run time (not baked), so pytest always sees the working tree, and this file never touches the prod
|
|
# Dockerfile, so the published image can never carry test tooling. Same python + same pinned
|
|
# requirements.txt as the runtime stage, so tests run against the prod dependency set. Rebuilt only
|
|
# when a requirements file changes (the pip layer is cache-keyed on them); otherwise a no-op.
|
|
#
|
|
# docker build -f backend/Dockerfile.test -t siftlode-test:local backend
|
|
# docker run --rm -v "<repo>/backend:/app" -w /app siftlode-test:local python -m pytest
|
|
FROM python:3.12-slim
|
|
WORKDIR /app
|
|
COPY requirements.txt requirements-dev.txt ./
|
|
RUN pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt
|