Add /visitors/ blueprint with REST API endpoints for listing profiles and visits, labeling (with consent gate), household linking, ignore/unignore, and cascading forget. Register blueprint in app.py. Add dashboard and profile detail templates (Bootstrap 5 dark, tab navigation, fetch-based JS). All six API tests pass (339 total). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
import time
|
|
import pytest
|
|
from vigilar.config import VigilarConfig
|
|
from vigilar.storage.queries import create_face_profile, insert_visit
|
|
from vigilar.web.app import create_app
|
|
|
|
|
|
@pytest.fixture
|
|
def visitor_app(test_db):
|
|
cfg = VigilarConfig()
|
|
app = create_app(cfg)
|
|
app.config["TESTING"] = True
|
|
app.config["DB_ENGINE"] = test_db
|
|
return app
|
|
|
|
|
|
@pytest.fixture
|
|
def seeded_visitors(test_db):
|
|
now = time.time()
|
|
pid1 = create_face_profile(test_db, name="Bob", first_seen_at=now - 86400, last_seen_at=now)
|
|
pid2 = create_face_profile(test_db, first_seen_at=now - 3600, last_seen_at=now)
|
|
insert_visit(test_db, pid1, "front", now - 3600)
|
|
insert_visit(test_db, pid2, "front", now - 1800)
|
|
return pid1, pid2
|
|
|
|
|
|
def test_get_profiles(visitor_app, seeded_visitors):
|
|
with visitor_app.test_client() as c:
|
|
rv = c.get("/visitors/api/profiles")
|
|
assert rv.status_code == 200
|
|
assert len(rv.get_json()["profiles"]) == 2
|
|
|
|
|
|
def test_get_visits(visitor_app, seeded_visitors):
|
|
with visitor_app.test_client() as c:
|
|
assert len(c.get("/visitors/api/visits").get_json()["visits"]) == 2
|
|
|
|
|
|
def test_label_with_consent(visitor_app, seeded_visitors, test_db):
|
|
_, pid2 = seeded_visitors
|
|
with visitor_app.test_client() as c:
|
|
rv = c.post(f"/visitors/{pid2}/label", json={"name": "Alice", "consent": True})
|
|
assert rv.status_code == 200
|
|
from vigilar.storage.queries import get_face_profile
|
|
assert get_face_profile(test_db, pid2)["name"] == "Alice"
|
|
|
|
|
|
def test_label_requires_consent(visitor_app, seeded_visitors):
|
|
_, pid2 = seeded_visitors
|
|
with visitor_app.test_client() as c:
|
|
assert c.post(
|
|
f"/visitors/{pid2}/label", json={"name": "Alice", "consent": False}
|
|
).status_code == 400
|
|
|
|
|
|
def test_forget(visitor_app, seeded_visitors, test_db):
|
|
pid1, _ = seeded_visitors
|
|
with visitor_app.test_client() as c:
|
|
assert c.delete(f"/visitors/{pid1}/forget").status_code == 200
|
|
from vigilar.storage.queries import get_face_profile
|
|
assert get_face_profile(test_db, pid1) is None
|
|
|
|
|
|
def test_ignore(visitor_app, seeded_visitors, test_db):
|
|
_, pid2 = seeded_visitors
|
|
with visitor_app.test_client() as c:
|
|
assert c.post(f"/visitors/{pid2}/ignore").status_code == 200
|
|
from vigilar.storage.queries import get_face_profile
|
|
assert get_face_profile(test_db, pid2)["ignored"] == 1
|