feat: add comprehensive tests for Story 2.3 View Exchange Details
Add integration tests covering all acceptance criteria: - Clicking an exchange opens detail view - Shows all exchange information - Shows list of registered participants - Shows current state - Shows registration link (when applicable) - Handle missing optional fields gracefully - Navigation back to dashboard Story: 2.3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
330
tests/integration/test_view_exchange_details.py
Normal file
330
tests/integration/test_view_exchange_details.py
Normal file
@@ -0,0 +1,330 @@
|
||||
"""Integration tests for Story 2.3: View Exchange Details."""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from src.models import Exchange
|
||||
|
||||
|
||||
class TestViewExchangeDetails:
|
||||
"""Test cases for viewing exchange details (Story 2.3)."""
|
||||
|
||||
def test_view_exchange_details_page(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that exchange detail page loads.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Clicking an exchange opens detail view
|
||||
"""
|
||||
# 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",
|
||||
description="Test description",
|
||||
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
|
||||
|
||||
def test_exchange_details_shows_all_information(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that all exchange information is displayed.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Shows all exchange information
|
||||
"""
|
||||
# Login first
|
||||
client.post(
|
||||
"/admin/login",
|
||||
data={
|
||||
"email": "admin@example.com",
|
||||
"password": "testpassword123",
|
||||
},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# Create an exchange with all fields
|
||||
future_close_date = datetime.utcnow() + timedelta(days=7)
|
||||
future_exchange_date = datetime.utcnow() + timedelta(days=14)
|
||||
|
||||
exchange = Exchange(
|
||||
slug=Exchange.generate_slug(),
|
||||
name="Family Christmas 2025",
|
||||
description="Annual family gift exchange",
|
||||
budget="$20-30",
|
||||
max_participants=20,
|
||||
registration_close_date=future_close_date,
|
||||
exchange_date=future_exchange_date,
|
||||
timezone="America/New_York",
|
||||
state=Exchange.STATE_REGISTRATION_OPEN,
|
||||
)
|
||||
|
||||
db.session.add(exchange)
|
||||
db.session.commit()
|
||||
|
||||
# View exchange details
|
||||
response = client.get(f"/admin/exchange/{exchange.id}")
|
||||
assert response.status_code == 200
|
||||
|
||||
# Verify all exchange information is displayed
|
||||
assert b"Family Christmas 2025" in response.data
|
||||
assert b"Annual family gift exchange" in response.data
|
||||
assert b"$20-30" in response.data
|
||||
assert b"20" in response.data # max_participants
|
||||
assert b"America/New_York" in response.data
|
||||
assert b"registration_open" in response.data
|
||||
|
||||
def test_exchange_details_shows_current_state(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that current state is displayed.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Shows current state
|
||||
"""
|
||||
# Login first
|
||||
client.post(
|
||||
"/admin/login",
|
||||
data={
|
||||
"email": "admin@example.com",
|
||||
"password": "testpassword123",
|
||||
},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# Create exchanges in different states
|
||||
future_close_date = datetime.utcnow() + timedelta(days=7)
|
||||
future_exchange_date = datetime.utcnow() + timedelta(days=14)
|
||||
|
||||
draft_exchange = Exchange(
|
||||
slug=Exchange.generate_slug(),
|
||||
name="Draft 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(draft_exchange)
|
||||
db.session.commit()
|
||||
|
||||
# View details
|
||||
response = client.get(f"/admin/exchange/{draft_exchange.id}")
|
||||
assert response.status_code == 200
|
||||
assert b"draft" in response.data
|
||||
|
||||
def test_exchange_details_shows_registration_link(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that registration link is shown.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Shows registration link (when applicable)
|
||||
"""
|
||||
# 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 registration link is displayed with the exchange slug
|
||||
assert exchange.slug.encode() in response.data
|
||||
assert b"/exchange/" in response.data
|
||||
assert b"/register" in response.data
|
||||
|
||||
def test_exchange_details_shows_participant_list(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that participant list is shown (empty initially).
|
||||
|
||||
Acceptance Criteria:
|
||||
- Shows list of registered participants
|
||||
"""
|
||||
# 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 participant section exists
|
||||
assert b"Participants" in response.data or b"participants" in response.data
|
||||
# Since no participants yet, should show empty message
|
||||
assert (
|
||||
b"No participants yet" in response.data
|
||||
or b"no participants" in response.data.lower()
|
||||
)
|
||||
|
||||
def test_exchange_details_not_found(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that 404 is returned for non-existent exchange.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Handle non-existent exchange gracefully
|
||||
"""
|
||||
# Login first
|
||||
client.post(
|
||||
"/admin/login",
|
||||
data={
|
||||
"email": "admin@example.com",
|
||||
"password": "testpassword123",
|
||||
},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# Try to view non-existent exchange
|
||||
response = client.get("/admin/exchange/99999")
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_exchange_details_handles_missing_description(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that missing optional fields are handled gracefully.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Shows all exchange information
|
||||
- Handle optional fields (description)
|
||||
"""
|
||||
# Login first
|
||||
client.post(
|
||||
"/admin/login",
|
||||
data={
|
||||
"email": "admin@example.com",
|
||||
"password": "testpassword123",
|
||||
},
|
||||
follow_redirects=True,
|
||||
)
|
||||
|
||||
# Create exchange without description
|
||||
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",
|
||||
description=None, # No description
|
||||
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
|
||||
|
||||
# Should handle missing description gracefully
|
||||
assert (
|
||||
b"No description" in response.data
|
||||
or b"no description" in response.data.lower()
|
||||
)
|
||||
|
||||
def test_exchange_details_navigation(self, client, db, admin): # noqa: ARG002
|
||||
"""Test that navigation back to dashboard exists.
|
||||
|
||||
Acceptance Criteria:
|
||||
- Provide navigation back to dashboard
|
||||
"""
|
||||
# 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 back link to dashboard exists
|
||||
assert b"dashboard" in response.data.lower() or b"back" in response.data.lower()
|
||||
Reference in New Issue
Block a user