Files

148 lines
5.0 KiB
Python
Raw Permalink Normal View History

2026-04-18 07:23:55 +12:00
import hashlib
import pytest
from httpx import AsyncClient
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.contact_lead import ContactLead
from app.models.member import MemberVerificationCode
pytestmark = pytest.mark.asyncio
async def test_public_contact_submission_creates_lead(client: AsyncClient, db_session: AsyncSession):
response = await client.post(
"/api/contact",
json={
"name": "Jamie Smith",
"email": "jamie@example.com",
"phone": "021 333 4444",
"services": ["Pack Walks", "Puppy Visits"],
"petName": "Buddy",
"petBreed": "Shih Tzu",
"location": "Ponsonby",
"serviceAreaStatus": "in_area",
"message": "Interested in a meet and greet.",
},
)
assert response.status_code == 201
body = response.json()
assert body["status"] == "invite"
assert body["email"] == "jamie@example.com"
result = await db_session.execute(select(ContactLead).where(ContactLead.email == "jamie@example.com"))
lead = result.scalars().first()
assert lead is not None
assert lead.requested_services == "Pack Walks, Puppy Visits"
assert lead.pet_name == "Buddy"
async def test_admin_can_invite_lead_into_onboarding(client: AsyncClient, admin_token: str):
create_response = await client.post(
"/api/contact",
json={
"name": "Jamie Smith",
"email": "jamie@example.com",
"phone": "021 333 4444",
"services": ["Pack Walks"],
"petName": "Buddy",
"petBreed": "Shih Tzu",
"location": "Ponsonby",
"message": "Interested in a meet and greet.",
},
)
lead_id = create_response.json()["id"]
invite_response = await client.post(
f"/api/v1/admin/leads/{lead_id}/invite",
headers={"Authorization": f"Bearer {admin_token}"},
json={"send_email": False},
)
assert invite_response.status_code == 200
body = invite_response.json()
assert body["lead"]["status"] == "invited"
assert body["member_status"] == "invited"
assert body["member_id"]
members_response = await client.get(
"/api/v1/admin/members",
headers={"Authorization": f"Bearer {admin_token}"},
)
assert any(member["email"] == "jamie@example.com" for member in members_response.json())
async def test_lead_becomes_converted_after_member_activation(
client: AsyncClient,
admin_token: str,
db_session: AsyncSession,
):
create_response = await client.post(
"/api/contact",
json={
"name": "Jamie Smith",
"email": "jamie@example.com",
"services": ["Pack Walks"],
"petName": "Buddy",
},
)
lead_id = create_response.json()["id"]
invite_response = await client.post(
f"/api/v1/admin/leads/{lead_id}/invite",
headers={"Authorization": f"Bearer {admin_token}"},
json={"send_email": False},
)
member_id = invite_response.json()["member_id"]
await client.post("/api/v1/members/claim/request", json={"email": "jamie@example.com"})
await db_session.execute(
MemberVerificationCode.__table__.update()
.values(code_hash=hashlib.sha256("AABBCC".encode()).hexdigest())
)
await db_session.commit()
await client.post(
"/api/v1/members/claim/complete",
json={"email": "jamie@example.com", "code": "AABBCC", "password": "NewPass99!"},
)
await client.post(
"/api/v1/members/auth/login",
json={"email": "jamie@example.com", "password": "NewPass99!"},
)
await db_session.execute(
MemberVerificationCode.__table__.update()
.where(MemberVerificationCode.purpose == "login_2fa")
.values(code_hash=hashlib.sha256("112233".encode()).hexdigest())
)
await db_session.commit()
verify_response = await client.post(
"/api/v1/members/auth/login/verify",
json={"email": "jamie@example.com", "code": "112233"},
)
access_token = verify_response.json()["access_token"]
await client.put(
"/api/v1/members/onboarding",
headers={"Authorization": f"Bearer {access_token}"},
json={"onboarding_data": {"dog_name": "Buddy"}, "complete_onboarding": True},
)
await client.post(
"/api/v1/members/onboarding/contract",
headers={"Authorization": f"Bearer {access_token}"},
json={"signer_name": "Jamie Smith", "agreed": True},
)
activate_response = await client.post(
f"/api/v1/admin/members/{member_id}/activate",
headers={"Authorization": f"Bearer {admin_token}"},
)
assert activate_response.status_code == 200
leads_response = await client.get(
"/api/v1/admin/leads",
headers={"Authorization": f"Bearer {admin_token}"},
)
matching_lead = next(lead for lead in leads_response.json() if lead["id"] == lead_id)
assert matching_lead["status"] == "converted"