Files
sneakyklaus/tests/integration/test_registration_link.py
Phil Skentelbery 2f667f3718 feat: add comprehensive tests for Story 2.6 Generate Registration Link
Add integration tests covering all acceptance criteria:
- Unique link generated for each exchange
- Link is copyable to clipboard
- Link is displayed when exchange is in appropriate state
- Link leads to registration page for that specific exchange
- Link uses slug instead of numeric ID for security
- Link contains full URL for easy sharing

Story: 2.6

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 13:00:15 -07:00

339 lines
11 KiB
Python

"""Integration tests for Story 2.6: Generate Registration Link."""
from datetime import datetime, timedelta
from src.models import Exchange
class TestGenerateRegistrationLink:
"""Test cases for registration link generation (Story 2.6)."""
def test_registration_link_generated_for_exchange(self, client, db, admin): # noqa: ARG002
"""Test that unique link is generated for each exchange.
Acceptance Criteria:
- Unique link generated for each exchange
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create two exchanges
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange1 = Exchange(
slug=Exchange.generate_slug(),
name="Exchange 1",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
exchange2 = Exchange(
slug=Exchange.generate_slug(),
name="Exchange 2",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange1)
db.session.add(exchange2)
db.session.commit()
# View first exchange details
response1 = client.get(f"/admin/exchange/{exchange1.id}")
assert response1.status_code == 200
# View second exchange details
response2 = client.get(f"/admin/exchange/{exchange2.id}")
assert response2.status_code == 200
# Verify different slugs in registration links
assert exchange1.slug.encode() in response1.data
assert exchange2.slug.encode() in response2.data
assert exchange1.slug != exchange2.slug
def test_registration_link_is_copyable(self, client, db, admin): # noqa: ARG002
"""Test that link is copyable to clipboard.
Acceptance Criteria:
- Link is copyable to clipboard
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create an exchange
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange = Exchange(
slug=Exchange.generate_slug(),
name="Test Exchange",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify copy button or mechanism exists
assert b"copy" in response.data.lower() or b"clipboard" in response.data.lower()
def test_registration_link_displayed_in_detail_view(self, client, db, admin): # noqa: ARG002
"""Test that link is displayed when exchange is in appropriate state.
Acceptance Criteria:
- Link is displayed when exchange is in appropriate state
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create exchange
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange = Exchange(
slug=Exchange.generate_slug(),
name="Test Exchange",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify registration link section exists
assert (
b"Registration Link" in response.data
or b"registration link" in response.data.lower()
)
def test_registration_link_leads_to_correct_page(self, client, db, admin): # noqa: ARG002
"""Test that link leads to registration page for that specific exchange.
Acceptance Criteria:
- Link leads to registration page for that specific exchange
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create exchange
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange = Exchange(
slug=Exchange.generate_slug(),
name="Test Exchange",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify the link format contains the slug
expected_link_part = f"/exchange/{exchange.slug}/register"
assert expected_link_part.encode() in response.data
def test_registration_link_uses_slug_not_id(self, client, db, admin): # noqa: ARG002
"""Test that registration link uses slug instead of numeric ID.
Acceptance Criteria:
- Unique link generated for each exchange
- Link uses slug (not ID) for security
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create exchange
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange = Exchange(
slug=Exchange.generate_slug(),
name="Test Exchange",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify slug is in the link
assert exchange.slug.encode() in response.data
# Verify numeric ID is NOT in the registration link part
# (It will be in admin URLs, but not in the public registration link)
response_text = response.data.decode()
# Extract registration link section
if "Registration Link" in response_text:
# Find the registration link
assert f"/exchange/{exchange.slug}/register" in response_text
# Should NOT contain /exchange/{id}/register
assert f"/exchange/{exchange.id}/register" not in response_text
def test_registration_link_contains_full_url(self, client, db, admin): # noqa: ARG002
"""Test that registration link is a complete URL.
Acceptance Criteria:
- Link is copyable (implies full URL)
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
# Create exchange
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
exchange = Exchange(
slug=Exchange.generate_slug(),
name="Test Exchange",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=Exchange.STATE_DRAFT,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify full URL is displayed (starts with http:// or https://)
assert (
b"http://" in response.data or b"https://" in response.data
), "Registration link should be a full URL"
def test_registration_link_available_in_all_states(self, client, db, admin): # noqa: ARG002
"""Test that registration link is available regardless of exchange state.
Acceptance Criteria:
- Link is displayed when exchange is in appropriate state
- Note: Based on design, link is always shown but may have different behavior
"""
# Login first
client.post(
"/admin/login",
data={
"email": "admin@example.com",
"password": "testpassword123",
},
follow_redirects=True,
)
future_close_date = datetime.utcnow() + timedelta(days=7)
future_exchange_date = datetime.utcnow() + timedelta(days=14)
# Test in different states
for state in [
Exchange.STATE_DRAFT,
Exchange.STATE_REGISTRATION_OPEN,
]:
exchange = Exchange(
slug=Exchange.generate_slug(),
name=f"Exchange in {state}",
budget="$20-30",
max_participants=10,
registration_close_date=future_close_date,
exchange_date=future_exchange_date,
timezone="America/New_York",
state=state,
)
db.session.add(exchange)
db.session.commit()
# View exchange details
response = client.get(f"/admin/exchange/{exchange.id}")
assert response.status_code == 200
# Verify registration link is displayed
assert exchange.slug.encode() in response.data
assert b"/exchange/" in response.data
assert b"/register" in response.data