""" tests/test_staff_login.py Tests for staff phone+passcode login flow and brute-force lockout. """ import pytest from app.extensions import db, bcrypt as _bcrypt from app.models.platform import Tenant, Plan from app.models.salon import Staff, Location def _seed_staff(app, phone="5551234567", passcode="1234"): with app.app_context(): plan = Plan.query.first() tenant = Tenant( slug=f"staff-test-{phone}", name="Staff Test Salon", owner_email="owner@stafftest.com", plan_id=plan.id, status="active", ) db.session.add(tenant) db.session.flush() location = Location( tenant_id=tenant.id, name="Main", is_primary=True, is_active=True, ) db.session.add(location) db.session.flush() staff = Staff( tenant_id=tenant.id, name="Jane Nail Tech", phone=phone, passcode_hash=_bcrypt.generate_password_hash(passcode).decode("utf-8"), staff_type="full_time", pay_type="hourly", is_active=True, ) staff.locations.append(location) db.session.add(staff) db.session.commit() return staff.id class TestStaffLogin: def test_staff_login_page_loads(self, tenant_client): resp = tenant_client.get("/staff-login") assert resp.status_code == 200 assert b"Staff Login" in resp.data def test_valid_staff_login(self, tenant_app, tenant_client): _seed_staff(tenant_app, phone="5550000001", passcode="1234") resp = tenant_client.post( "/staff-login", data={"phone": "5550000001", "passcode": "1234"}, follow_redirects=True, ) assert resp.status_code == 200 def test_invalid_passcode(self, tenant_app, tenant_client): _seed_staff(tenant_app, phone="5550000002", passcode="5678") resp = tenant_client.post( "/staff-login", data={"phone": "5550000002", "passcode": "9999"}, follow_redirects=True, ) assert b"Invalid" in resp.data def test_passcode_too_short(self, tenant_client): resp = tenant_client.post( "/staff-login", data={"phone": "5550000003", "passcode": "12"}, follow_redirects=True, ) assert b"4" in resp.data # "4–6 digits" error message def test_brute_force_lockout(self, tenant_app, tenant_client): _seed_staff(tenant_app, phone="5550000009", passcode="1234") for _ in range(5): tenant_client.post( "/staff-login", data={"phone": "5550000009", "passcode": "9999"}, ) resp = tenant_client.post( "/staff-login", data={"phone": "5550000009", "passcode": "1234"}, follow_redirects=True, ) assert b"locked" in resp.data.lower()