05/06/2026 Initial commit

This commit is contained in:
2026-05-06 14:19:07 -04:00
parent 9da1dffd9a
commit dde18a2cd2
116 changed files with 4276 additions and 7 deletions
+93
View File
@@ -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 # "46 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()