Implement Phase 3 participant self-management features: Story 6.3 - Reminder Preferences: - Add ReminderPreferenceForm to participant forms - Add update_preferences route for preference updates - Update dashboard template with reminder preference toggle - Participants can enable/disable reminder emails at any time Story 6.2 - Withdrawal from Exchange: - Add can_withdraw utility function for state validation - Create WithdrawalService to handle withdrawal process - Add WithdrawForm with explicit confirmation requirement - Add withdraw route with GET (confirmation) and POST (process) - Add withdrawal confirmation email template - Update dashboard to show withdraw link when allowed - Withdrawal only allowed before registration closes - Session cleared after withdrawal, user redirected to registration All acceptance criteria met for both stories. Test coverage: 90.02% (156 tests passing) Linting and type checking: passed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
2.4 KiB
Python
84 lines
2.4 KiB
Python
"""Integration tests for reminder preferences."""
|
|
|
|
from flask import url_for
|
|
|
|
|
|
def get_csrf_token(client, url):
|
|
"""Extract CSRF token from a page.
|
|
|
|
Args:
|
|
client: Flask test client.
|
|
url: URL to fetch the CSRF token from.
|
|
|
|
Returns:
|
|
CSRF token string.
|
|
"""
|
|
response = client.get(url)
|
|
# Extract CSRF token from the form
|
|
data = response.data.decode()
|
|
start = data.find('name="csrf_token" value="') + len('name="csrf_token" value="')
|
|
end = data.find('"', start)
|
|
return data[start:end]
|
|
|
|
|
|
def test_dashboard_shows_reminder_preference_form(client, auth_participant):
|
|
"""Test that dashboard shows reminder preference form."""
|
|
response = client.get(
|
|
url_for("participant.dashboard", id=auth_participant.exchange_id)
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Email Reminders" in response.data or b"Send me reminders" in response.data
|
|
|
|
|
|
def test_update_preferences_enable(client, auth_participant, db):
|
|
"""Enable reminder emails."""
|
|
auth_participant.reminder_enabled = False
|
|
db.session.commit()
|
|
|
|
csrf_token = get_csrf_token(
|
|
client, url_for("participant.dashboard", id=auth_participant.exchange_id)
|
|
)
|
|
|
|
response = client.post(
|
|
url_for("participant.update_preferences"),
|
|
data={"reminder_enabled": True, "csrf_token": csrf_token},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Reminder emails enabled" in response.data
|
|
|
|
db.session.refresh(auth_participant)
|
|
assert auth_participant.reminder_enabled is True
|
|
|
|
|
|
def test_update_preferences_disable(client, auth_participant, db):
|
|
"""Disable reminder emails."""
|
|
auth_participant.reminder_enabled = True
|
|
db.session.commit()
|
|
|
|
csrf_token = get_csrf_token(
|
|
client, url_for("participant.dashboard", id=auth_participant.exchange_id)
|
|
)
|
|
|
|
response = client.post(
|
|
url_for("participant.update_preferences"),
|
|
data={"csrf_token": csrf_token},
|
|
follow_redirects=True,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert b"Reminder emails disabled" in response.data
|
|
|
|
db.session.refresh(auth_participant)
|
|
assert auth_participant.reminder_enabled is False
|
|
|
|
|
|
def test_update_preferences_requires_login(client):
|
|
"""Test that update_preferences requires login."""
|
|
response = client.post(url_for("participant.update_preferences"))
|
|
|
|
# Should redirect to login or show error
|
|
assert response.status_code in [302, 401, 403]
|