""" 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']