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>
339 lines
11 KiB
Python
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
|