first round of review
This commit is contained in:
parent
870804e7b9
commit
23049da55a
15 changed files with 325 additions and 182 deletions
|
|
@ -397,6 +397,47 @@ async def test_created_invite_persisted_in_db(client_factory, admin_user, regula
|
|||
assert invite.status == InviteStatus.READY
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_invite_retries_on_collision(client_factory, admin_user, regular_user):
|
||||
"""Create invite retries with new identifier on collision."""
|
||||
from unittest.mock import patch
|
||||
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as client:
|
||||
async with client_factory.get_db_session() as db:
|
||||
result = await db.execute(
|
||||
select(User).where(User.email == regular_user["email"])
|
||||
)
|
||||
godfather = result.scalar_one()
|
||||
|
||||
# Create first invite normally
|
||||
response1 = await client.post(
|
||||
"/api/admin/invites",
|
||||
json={"godfather_id": godfather.id},
|
||||
)
|
||||
assert response1.status_code == 200
|
||||
identifier1 = response1.json()["identifier"]
|
||||
|
||||
# Mock generator to first return the same identifier (collision), then a new one
|
||||
call_count = 0
|
||||
def mock_generator():
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
if call_count == 1:
|
||||
return identifier1 # Will collide
|
||||
return f"unique-word-{call_count:02d}" # Won't collide
|
||||
|
||||
with patch("main.generate_invite_identifier", side_effect=mock_generator):
|
||||
response2 = await client.post(
|
||||
"/api/admin/invites",
|
||||
json={"godfather_id": godfather.id},
|
||||
)
|
||||
|
||||
assert response2.status_code == 200
|
||||
# Should have retried and gotten a new identifier
|
||||
assert response2.json()["identifier"] != identifier1
|
||||
assert call_count >= 2 # At least one retry
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Invite Check API Tests (Phase 3)
|
||||
# ============================================================================
|
||||
|
|
@ -441,6 +482,32 @@ async def test_check_invite_not_found(client_factory):
|
|||
assert "not found" in data["error"].lower()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_invite_invalid_format(client_factory):
|
||||
"""Check endpoint returns error for invalid format without querying DB."""
|
||||
async with client_factory.create() as client:
|
||||
# Missing number part
|
||||
response = await client.get("/api/invites/word-word/check")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["valid"] is False
|
||||
assert "format" in data["error"].lower()
|
||||
|
||||
# Single digit number
|
||||
response = await client.get("/api/invites/word-word-1/check")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["valid"] is False
|
||||
assert "format" in data["error"].lower()
|
||||
|
||||
# Too many parts
|
||||
response = await client.get("/api/invites/word-word-word-00/check")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["valid"] is False
|
||||
assert "format" in data["error"].lower()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_invite_case_insensitive(client_factory, admin_user, regular_user):
|
||||
"""Check endpoint handles case-insensitive identifiers."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue