"""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