vigilar/tests/unit/test_visitors_api.py
Aaron D. Lee 23d5bf062a feat(S3): visitors blueprint with profiles, visits, labeling, privacy controls
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>
2026-04-03 19:01:33 -04:00

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