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>
110 lines
3.6 KiB
Python
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
|