This commit is contained in:
28
.gitea/workflows/python.yml
Normal file
28
.gitea/workflows/python.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
name: python
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt pytest httpx
|
||||
|
||||
- name: Compile checks
|
||||
run: python -m compileall -q app tests
|
||||
|
||||
- name: Run tests
|
||||
run: pytest -q
|
||||
130
tests/test_main.py
Normal file
130
tests/test_main.py
Normal file
@@ -0,0 +1,130 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app.main as main
|
||||
|
||||
|
||||
class DummySettings(SimpleNamespace):
|
||||
@property
|
||||
def auth_enabled(self):
|
||||
return bool(self.auth_token)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_settings(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
test_ui_enabled=True,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client():
|
||||
return TestClient(main.app)
|
||||
|
||||
|
||||
def test_health_reflects_settings(client):
|
||||
resp = client.get("/health")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == {
|
||||
"ok": True,
|
||||
"env": "test",
|
||||
"test_ui_enabled": True,
|
||||
"auth_enabled": False,
|
||||
"auth_header": None,
|
||||
}
|
||||
|
||||
|
||||
def test_index_shows_disabled_message_when_ui_off(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
test_ui_enabled=False,
|
||||
auth_token="",
|
||||
auth_header_name="X-API-Key",
|
||||
),
|
||||
)
|
||||
resp = TestClient(main.app).get("/")
|
||||
assert resp.status_code == 200
|
||||
assert "Test UI is disabled." in resp.text
|
||||
|
||||
|
||||
def test_focus_accepts_bearer_auth_and_returns_payload(monkeypatch, client):
|
||||
monkeypatch.setattr(
|
||||
main,
|
||||
"settings",
|
||||
DummySettings(
|
||||
env="test",
|
||||
test_ui_enabled=True,
|
||||
auth_token="secret",
|
||||
auth_header_name="X-API-Key",
|
||||
),
|
||||
)
|
||||
|
||||
def fake_process_image(image_bytes, filename, buffer_ratio=0.15, detector="subject"):
|
||||
assert image_bytes == b"image-bytes"
|
||||
assert filename == "sample.jpg"
|
||||
assert buffer_ratio == 0.2
|
||||
assert detector == "face"
|
||||
return {
|
||||
"filename": filename,
|
||||
"detector": detector,
|
||||
"method": "face_cascade",
|
||||
"buffer_ratio": buffer_ratio,
|
||||
"detected_bbox": {"x": 1, "y": 2, "w": 3, "h": 4},
|
||||
"square_bbox": {"x": 0, "y": 0, "w": 8, "h": 8},
|
||||
"source_size": {"width": 10, "height": 12},
|
||||
"crop_data_url": "data:image/jpeg;base64,AAA=",
|
||||
"annotated_data_url": "data:image/jpeg;base64,BBB=",
|
||||
"mime_type": "image/jpeg",
|
||||
"crop_bytes": b"crop",
|
||||
}
|
||||
|
||||
monkeypatch.setattr("app.vision.process_image", fake_process_image)
|
||||
|
||||
resp = client.post(
|
||||
"/api/focus",
|
||||
headers={"Authorization": "Bearer secret"},
|
||||
files={"file": ("sample.jpg", b"image-bytes", "image/jpeg")},
|
||||
data={"buffer_ratio": "0.2", "detector": "face"},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["method"] == "face_cascade"
|
||||
assert resp.json()["detected_bbox"] == {"x": 1, "y": 2, "w": 3, "h": 4}
|
||||
|
||||
|
||||
def test_focus_image_returns_jpeg_stream(monkeypatch, client):
|
||||
def fake_process_image(image_bytes, filename, buffer_ratio=0.15, detector="subject"):
|
||||
return {
|
||||
"filename": filename,
|
||||
"detector": detector,
|
||||
"method": "subject_contour",
|
||||
"buffer_ratio": buffer_ratio,
|
||||
"detected_bbox": {"x": 1, "y": 2, "w": 3, "h": 4},
|
||||
"square_bbox": {"x": 0, "y": 0, "w": 8, "h": 8},
|
||||
"source_size": {"width": 10, "height": 12},
|
||||
"crop_data_url": "data:image/jpeg;base64,AAA=",
|
||||
"annotated_data_url": "data:image/jpeg;base64,BBB=",
|
||||
"mime_type": "image/jpeg",
|
||||
"crop_bytes": b"crop-bytes",
|
||||
}
|
||||
|
||||
monkeypatch.setattr("app.vision.process_image", fake_process_image)
|
||||
|
||||
resp = client.post(
|
||||
"/api/focus/image",
|
||||
files={"file": ("sample.jpg", b"image-bytes", "image/jpeg")},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.headers["content-type"] == "image/jpeg"
|
||||
assert resp.content == b"crop-bytes"
|
||||
Reference in New Issue
Block a user