feat: enhance face-lock service with improved upload handling and response structure
python / test (push) Failing after 8s
python / test (push) Failing after 8s
- Updated README.md to reflect new features and API changes. - Introduced versioning in app initialization. - Enhanced configuration management in app/config.py with new validation functions. - Refactored main.py to improve request handling and response generation. - Added new models in app/models.py for structured API responses. - Implemented a dedicated UI rendering function in app/ui.py. - Improved Docker configuration for better security and health checks. - Updated tests to cover new validation rules and response formats. - Added CLAUDE.md for project guidelines and working rules.
This commit is contained in:
@@ -4,6 +4,7 @@ import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.main as main
|
||||
from app import __version__
|
||||
|
||||
|
||||
class DummySettings(SimpleNamespace):
|
||||
@@ -19,9 +20,12 @@ def reset_settings(monkeypatch):
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=True,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=1024 * 1024,
|
||||
allowed_mime_types=("image/jpeg", "image/png", "image/webp", "image/gif"),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -37,9 +41,13 @@ def test_health_reflects_settings(client):
|
||||
assert resp.json() == {
|
||||
"ok": True,
|
||||
"env": "test",
|
||||
"version": __version__,
|
||||
"docs_enabled": True,
|
||||
"test_ui_enabled": True,
|
||||
"auth_enabled": False,
|
||||
"auth_header": None,
|
||||
"max_upload_bytes": 1024 * 1024,
|
||||
"allowed_mime_types": ["image/jpeg", "image/png", "image/webp", "image/gif"],
|
||||
}
|
||||
|
||||
|
||||
@@ -49,14 +57,18 @@ def test_index_shows_disabled_message_when_ui_off(monkeypatch):
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=False,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=1024 * 1024,
|
||||
allowed_mime_types=("image/jpeg", "image/png", "image/webp", "image/gif"),
|
||||
),
|
||||
)
|
||||
resp = TestClient(main.app).get("/")
|
||||
assert resp.status_code == 200
|
||||
assert "Test UI is disabled." in resp.text
|
||||
assert resp.headers["cache-control"] == "no-store"
|
||||
|
||||
|
||||
def test_focus_accepts_bearer_auth_and_returns_payload(monkeypatch, client):
|
||||
@@ -65,9 +77,12 @@ def test_focus_accepts_bearer_auth_and_returns_payload(monkeypatch, client):
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=True,
|
||||
auth_token="secret",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=1024 * 1024,
|
||||
allowed_mime_types=("image/jpeg", "image/png", "image/webp", "image/gif"),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -101,6 +116,76 @@ def test_focus_accepts_bearer_auth_and_returns_payload(monkeypatch, client):
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["method"] == "face_cascade"
|
||||
assert resp.json()["detected_bbox"] == {"x": 1, "y": 2, "w": 3, "h": 4}
|
||||
assert resp.json()["mime_type"] == "image/jpeg"
|
||||
|
||||
|
||||
def test_focus_rejects_unauthorized_request(monkeypatch, client):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=True,
|
||||
auth_token="secret",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=1024 * 1024,
|
||||
allowed_mime_types=("image/jpeg", "image/png", "image/webp", "image/gif"),
|
||||
),
|
||||
)
|
||||
|
||||
resp = client.post(
|
||||
"/api/focus",
|
||||
files={"file": ("sample.jpg", b"image-bytes", "image/jpeg")},
|
||||
)
|
||||
assert resp.status_code == 401
|
||||
assert resp.json() == {"detail": "unauthorized"}
|
||||
|
||||
|
||||
def test_focus_rejects_unsupported_content_type(monkeypatch, client):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=True,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=1024 * 1024,
|
||||
allowed_mime_types=("image/jpeg",),
|
||||
),
|
||||
)
|
||||
|
||||
resp = client.post(
|
||||
"/api/focus",
|
||||
files={"file": ("sample.txt", b"image-bytes", "text/plain")},
|
||||
)
|
||||
assert resp.status_code == 415
|
||||
assert resp.json() == {"detail": "unsupported content type: text/plain"}
|
||||
|
||||
|
||||
def test_focus_rejects_large_upload(monkeypatch, client):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
docs_enabled=True,
|
||||
test_ui_enabled=True,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
max_upload_bytes=4,
|
||||
allowed_mime_types=("image/jpeg",),
|
||||
),
|
||||
)
|
||||
|
||||
resp = client.post(
|
||||
"/api/focus",
|
||||
files={"file": ("sample.jpg", b"image-bytes", "image/jpeg")},
|
||||
)
|
||||
assert resp.status_code == 413
|
||||
assert resp.json() == {"detail": "upload exceeds FACE_LOCK_MAX_UPLOAD_BYTES (4 bytes)"}
|
||||
|
||||
|
||||
def test_focus_image_returns_jpeg_stream(monkeypatch, client):
|
||||
@@ -127,4 +212,5 @@ def test_focus_image_returns_jpeg_stream(monkeypatch, client):
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.headers["content-type"] == "image/jpeg"
|
||||
assert resp.headers["content-disposition"] == 'inline; filename="sample-crop.jpg"'
|
||||
assert resp.content == b"crop-bytes"
|
||||
|
||||
Reference in New Issue
Block a user