| """ |
| Pytest configuration + shared fixtures. |
| |
| Provides: |
| - test_settings: Settings instance with all optional providers disabled, |
| in-memory DB, temp dirs. |
| - test_container: fully wired ServiceContainer for integration tests. |
| - sample_image_bytes: a synthetic JPEG with no faces (for negative tests). |
| - sample_face_image_bytes: a synthetic JPEG with a face-like shape. |
| - sample_image_b64: base64-encoded sample_image_bytes. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import base64 |
| import io |
| import sys |
| from pathlib import Path |
|
|
| import cv2 |
| import numpy as np |
| import pytest |
|
|
| |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) |
|
|
| from config.settings import Settings, DATA_DIR |
| from api.container import build_container |
|
|
|
|
| @pytest.fixture |
| def test_settings(tmp_path) -> Settings: |
| """Settings with all optional providers disabled + temp DB.""" |
| return Settings( |
| environment="test", |
| enable_dnn=False, |
| enable_mtcnn=False, |
| enable_retinaface=False, |
| enable_face_recognition=False, |
| enable_deepface=False, |
| enable_insightface=False, |
| enable_beautifulsoup_scraper=False, |
| enable_selenium_scraper=False, |
| enable_bing_scraper=False, |
| enable_duckduckgo_scraper=False, |
| enable_google_lens=False, |
| enable_serpapi=False, |
| enable_yandex=False, |
| enable_tineye=False, |
| enable_visual_features=False, |
| enable_xmp=False, |
| enable_manipulation_analyzer=False, |
| db_path=":memory:", |
| cache_enabled=False, |
| rate_limit_per_minute=10000, |
| ) |
|
|
|
|
| @pytest.fixture |
| def test_container(test_settings): |
| """Fully wired container for integration tests.""" |
| return build_container(test_settings) |
|
|
|
|
| @pytest.fixture |
| def sample_image_bytes() -> bytes: |
| """A 200x200 black image with a white square — no faces.""" |
| img = np.zeros((200, 200, 3), dtype=np.uint8) |
| cv2.rectangle(img, (50, 50), (150, 150), (255, 255, 255), -1) |
| ok, buf = cv2.imencode(".jpg", img) |
| assert ok |
| return buf.tobytes() |
|
|
|
|
| @pytest.fixture |
| def sample_face_image_bytes() -> bytes: |
| """A 300x300 image with a face-like shape (circle for head, dots for eyes).""" |
| img = np.zeros((300, 300, 3), dtype=np.uint8) |
| |
| cv2.circle(img, (150, 150), 80, (200, 200, 200), -1) |
| |
| cv2.circle(img, (125, 130), 8, (50, 50, 50), -1) |
| cv2.circle(img, (175, 130), 8, (50, 50, 50), -1) |
| |
| cv2.ellipse(img, (150, 180), (30, 10), 0, 0, 180, (50, 50, 50), 2) |
| ok, buf = cv2.imencode(".jpg", img) |
| assert ok |
| return buf.tobytes() |
|
|
|
|
| @pytest.fixture |
| def sample_image_b64(sample_image_bytes) -> str: |
| return base64.b64encode(sample_image_bytes).decode() |
|
|
|
|
| @pytest.fixture |
| def sample_face_b64(sample_face_image_bytes) -> str: |
| return base64.b64encode(sample_face_image_bytes).decode() |
|
|