Jul 10 - Add test suite
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
"""
|
||||
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']
|
||||
Reference in New Issue
Block a user