Files
2026-07-10 15:49:55 -04:00

124 lines
4.7 KiB
Python

"""
Model-property unit tests + one authenticated route test.
The property tests need an app context (for the DB session the factories use)
but exercise pure Python logic. The final test drives the phase39 area-QR route
through the real login flow, proving the auth fixture and QR endpoint work.
"""
import pytest
from app.models.issue import Issue
# ── User.display_name ─────────────────────────────────────────────────────────
def test_display_name_prefers_full_name(make_user):
u = make_user(role='inspector', full_name=' Dana Nguyen ')
assert u.display_name == 'Dana Nguyen' # trimmed
def test_display_name_falls_back_to_username(make_user):
u = make_user(role='inspector', username='jdoe', full_name=None)
assert u.display_name == 'jdoe'
def test_display_name_falls_back_when_full_name_blank(make_user):
u = make_user(role='inspector', username='jdoe', full_name=' ')
assert u.display_name == 'jdoe'
# ── Issue.handler_label ───────────────────────────────────────────────────────
@pytest.mark.parametrize('handler,label', [
('internal', 'Janitorial Staff'),
('facility', 'Facility Staff'),
('vendor', 'External Vendor'),
])
def test_handler_label(make_facility, make_issue, handler, label):
fac = make_facility()
iss = make_issue(facility=fac, handler_type=handler)
assert iss.handler_label == label
def test_handler_label_defaults_to_internal(make_facility, make_issue):
fac = make_facility()
iss = make_issue(facility=fac) # handler_type defaults to 'internal'
assert iss.handler_label == 'Janitorial Staff'
# ── Issue.resolved_facility ───────────────────────────────────────────────────
def test_resolved_facility_direct(make_facility, make_issue):
fac = make_facility()
iss = make_issue(facility=fac)
assert iss.resolved_facility.id == fac.id
def test_resolved_facility_via_area(make_facility, make_area, make_issue):
fac = make_facility()
area = make_area(fac)
iss = make_issue(area=area) # facility_id is None; resolves via area
assert iss.resolved_facility.id == fac.id
def test_resolved_facility_none(db, make_issue):
# No facility, no area -> None
iss = Issue(severity='low', description='orphan', status='open')
db.session.add(iss)
db.session.commit()
assert iss.resolved_facility is None
# ── Public token minting ──────────────────────────────────────────────────────
def test_facility_ensure_public_token_is_idempotent(make_facility):
fac = make_facility(with_token=True)
first = fac.public_token
assert first
assert fac.ensure_public_token() == first # does not regenerate
def test_area_tokens_are_unique(make_facility, make_area):
fac = make_facility()
a1 = make_area(fac)
a2 = make_area(fac)
assert a1.public_token and a2.public_token
assert a1.public_token != a2.public_token
# ── Authenticated route: phase39 area QR ──────────────────────────────────────
def test_area_qr_page_mints_token_and_png(
client, login, make_user, make_facility, make_area):
pytest.importorskip('qrcode') # skip if optional dep absent locally
director = make_user(role='director', password='pw')
fac = make_facility()
area = make_area(fac, with_token=False) # no token yet
assert area.public_token is None
login(director, password='pw')
# Visiting the printable QR page mints and persists a token.
resp = client.get(f'/facilities/areas/{area.id}/qr')
assert resp.status_code == 200
from app.models.facility import Area
from app import db
refreshed = db.session.get(Area, area.id)
assert refreshed.public_token is not None
# The PNG endpoint returns an actual image.
png = client.get(f'/facilities/areas/{area.id}/qr.png')
assert png.status_code == 200
assert png.mimetype == 'image/png'
def test_area_qr_requires_login(client, make_facility, make_area):
fac = make_facility()
area = make_area(fac)
resp = client.get(f'/facilities/areas/{area.id}/qr', follow_redirects=False)
# Unauthenticated -> redirected to the login page.
assert resp.status_code == 302
assert '/auth/login' in resp.headers['Location']