Files
livef12rocks/tests/test_main.py
Frank Schwenk dec74a46d7 feat: serve responsive WebP srcsets for faster mobile browsing
On-demand ?w= resize with a disk cache under webcache/; downloads stay full-resolution.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 13:04:33 +02:00

104 lines
3.2 KiB
Python

"""Tests for FastAPI routes and validation."""
from __future__ import annotations
from pathlib import Path
import pytest
from app import config, images, pipeline
from app.main import _safe_job_file, _validate_job_id, app
from fastapi import HTTPException
from fastapi.testclient import TestClient
from PIL import Image
@pytest.fixture
def client(data_dir: Path) -> TestClient:
return TestClient(app)
def _write_test_png(path: Path, size: tuple[int, int] = (1200, 800)) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
Image.new("RGB", size, color=(40, 80, 120)).save(path, format="PNG")
def test_validate_job_id_sanitizes_input() -> None:
assert _validate_job_id("foo@bar") == "foo_bar"
assert _validate_job_id("photo01") == "photo01"
def test_validate_job_id_rejects_path_like() -> None:
with pytest.raises(HTTPException) as exc:
_validate_job_id("a/b")
assert exc.value.status_code == 400
with pytest.raises(HTTPException):
_validate_job_id("../evil")
with pytest.raises(HTTPException):
_validate_job_id("")
def test_safe_job_file_rejects_wrong_prefix(data_dir: Path) -> None:
stem = "photo01"
paths = pipeline.job_paths(stem)
paths.variants.mkdir(parents=True, exist_ok=True)
target = paths.variants / f"{stem}_v1.png"
target.write_bytes(b"x")
with pytest.raises(HTTPException):
_safe_job_file(stem, "other_v1.png")
def test_index_empty(client: TestClient) -> None:
response = client.get("/")
assert response.status_code == 200
assert config.SITE_TITLE in response.text
def test_job_not_found(client: TestClient) -> None:
response = client.get("/jobs/does-not-exist")
assert response.status_code == 404
def test_job_file_srcset_resize(client: TestClient, data_dir: Path) -> None:
stem = "photo01"
paths = pipeline.job_paths(stem)
png = paths.variants / f"{stem}_v1.png"
_write_test_png(png)
pipeline.write_status(paths, "done", created_at="2026-01-01T00:00:00")
pipeline.write_manifest(
paths,
{
"variants": [{"id": "v1", "file": png.name}],
"created_at": "2026-01-01T00:00:00",
},
)
full = client.get(f"/jobs/{stem}/files/{png.name}")
assert full.status_code == 200
assert full.headers["content-type"].startswith("image/")
bad = client.get(f"/jobs/{stem}/files/{png.name}?w=999")
assert bad.status_code == 400
resized = client.get(f"/jobs/{stem}/files/{png.name}?w=320")
assert resized.status_code == 200
assert resized.headers["content-type"] == "image/webp"
assert len(resized.content) < len(full.content)
cached = config.WEB_CACHE_DIR / f"{png.name}.w320.webp"
assert cached.is_file()
with Image.open(cached) as img:
assert img.width == 320
index = client.get("/")
assert index.status_code == 200
assert f"/jobs/{stem}/files/{png.name}?w=640" in index.text
assert "srcset=" in index.text
assert "data-full-src=" in index.text
def test_img_attrs_builds_srcset() -> None:
attrs = images.img_attrs("job1", "job1_v1.png")
assert attrs["src"].endswith("?w=640")
assert "320w" in attrs["srcset"]
assert attrs["full_src"].endswith("?w=1280")