05/06/2026 Initial commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
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()
|
||||
Reference in New Issue
Block a user