vigilar/tests/unit/test_pets_api.py
Aaron D. Lee 94c5184f46 Add pets web blueprint with API endpoints
Implements all /pets/* routes (register, status, sightings, wildlife,
unlabeled crops, label, upload, update, delete, train, training-status,
highlights), registers the blueprint in app.py, adds a placeholder
dashboard template, and covers the API with 11 passing unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 13:27:46 -04:00

110 lines
3.6 KiB
Python

"""Tests for pets web blueprint API endpoints."""
import pytest
from sqlalchemy import create_engine
from vigilar.config import VigilarConfig
from vigilar.storage.schema import metadata
from vigilar.web.app import create_app
@pytest.fixture
def client(tmp_path):
"""Flask test client wired to an in-memory test DB."""
db_path = tmp_path / "pets_test.db"
engine = create_engine(f"sqlite:///{db_path}", echo=False)
metadata.create_all(engine)
cfg = VigilarConfig()
app = create_app(cfg)
app.config["DB_ENGINE"] = engine
app.config["TESTING"] = True
with app.test_client() as c:
yield c
class TestPetsAPI:
def test_register_pet(self, client):
resp = client.post("/pets/register", json={
"name": "Angel", "species": "cat", "breed": "DSH",
"color_description": "black",
})
assert resp.status_code == 200
data = resp.get_json()
assert data["name"] == "Angel"
assert "id" in data
def test_get_pet_status(self, client):
client.post("/pets/register", json={"name": "Angel", "species": "cat"})
resp = client.get("/pets/api/status")
assert resp.status_code == 200
data = resp.get_json()
assert len(data["pets"]) == 1
assert data["pets"][0]["name"] == "Angel"
def test_get_sightings_empty(self, client):
resp = client.get("/pets/api/sightings")
assert resp.status_code == 200
data = resp.get_json()
assert data["sightings"] == []
def test_get_wildlife_empty(self, client):
resp = client.get("/pets/api/wildlife")
assert resp.status_code == 200
data = resp.get_json()
assert data["sightings"] == []
def test_get_unlabeled_empty(self, client):
resp = client.get("/pets/api/unlabeled")
assert resp.status_code == 200
data = resp.get_json()
assert data["crops"] == []
def test_pets_dashboard_loads(self, client):
resp = client.get("/pets/")
assert resp.status_code == 200
def test_register_pet_missing_fields(self, client):
resp = client.post("/pets/register", json={"name": "Buddy"})
assert resp.status_code == 400
def test_label_crop(self, client):
# Register a pet first
reg = client.post("/pets/register", json={"name": "Angel", "species": "cat"})
pet_id = reg.get_json()["id"]
# Insert an unlabeled sighting directly via DB
from vigilar.storage.queries import insert_pet_sighting
app_engine = client.application.config["DB_ENGINE"]
sighting_id = insert_pet_sighting(app_engine, species="cat", camera_id="cam1",
confidence=0.9)
resp = client.post(f"/pets/{sighting_id}/label", json={"pet_id": pet_id})
assert resp.status_code == 200
assert resp.get_json()["ok"] is True
def test_delete_pet(self, client):
reg = client.post("/pets/register", json={"name": "Ghost", "species": "cat"})
pet_id = reg.get_json()["id"]
resp = client.delete(f"/pets/{pet_id}/delete")
assert resp.status_code == 200
assert resp.get_json()["ok"] is True
status = client.get("/pets/api/status").get_json()
assert len(status["pets"]) == 0
def test_training_status(self, client):
resp = client.get("/pets/api/training-status")
assert resp.status_code == 200
data = resp.get_json()
assert "status" in data
def test_highlights(self, client):
resp = client.get("/pets/api/highlights")
assert resp.status_code == 200
data = resp.get_json()
assert "highlights" in data