""" E2E tests for review submission and moderation flows. These tests verify the complete user journey for submitting, editing, and moderating reviews using Playwright for browser automation. """ import pytest from playwright.sync_api import Page, expect @pytest.mark.e2e class TestReviewSubmission: """E2E tests for review submission flow.""" def test__review_form__displays_fields(self, auth_page: Page, live_server, parks_data): """Test review form displays all required fields.""" park = parks_data[0] auth_page.goto(f"{live_server.url}/parks/{park.slug}/") # Find and click reviews tab or section reviews_tab = auth_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() # Click write review button write_review = auth_page.locator( "button:has-text('Write Review'), a:has-text('Write Review')" ) if write_review.count() > 0: write_review.first.click() # Verify form fields expect(auth_page.locator("select[name='rating'], input[name='rating']").first).to_be_visible() expect(auth_page.locator("input[name='title'], textarea[name='title']").first).to_be_visible() expect(auth_page.locator("textarea[name='content'], textarea[name='review']").first).to_be_visible() def test__review_submission__valid_data__creates_review( self, auth_page: Page, live_server, parks_data ): """Test submitting a valid review creates it.""" park = parks_data[0] auth_page.goto(f"{live_server.url}/parks/{park.slug}/") # Navigate to reviews reviews_tab = auth_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() write_review = auth_page.locator( "button:has-text('Write Review'), a:has-text('Write Review')" ) if write_review.count() > 0: write_review.first.click() # Fill the form rating_select = auth_page.locator("select[name='rating']") if rating_select.count() > 0: rating_select.select_option("5") else: # May be radio buttons or stars auth_page.locator("input[name='rating'][value='5']").click() auth_page.locator("input[name='title'], textarea[name='title']").first.fill( "E2E Test Review Title" ) auth_page.locator("textarea[name='content'], textarea[name='review']").first.fill( "This is an E2E test review content." ) auth_page.get_by_role("button", name="Submit").click() # Should show success or redirect auth_page.wait_for_timeout(500) def test__review_submission__missing_rating__shows_error( self, auth_page: Page, live_server, parks_data ): """Test submitting review without rating shows error.""" park = parks_data[0] auth_page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = auth_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() write_review = auth_page.locator( "button:has-text('Write Review'), a:has-text('Write Review')" ) if write_review.count() > 0: write_review.first.click() # Fill only title and content, skip rating auth_page.locator("input[name='title'], textarea[name='title']").first.fill( "Missing Rating Review" ) auth_page.locator("textarea[name='content'], textarea[name='review']").first.fill( "Review without rating" ) auth_page.get_by_role("button", name="Submit").click() # Should show validation error error = auth_page.locator(".error, .errorlist, [role='alert']") expect(error.first).to_be_visible() @pytest.mark.e2e class TestReviewDisplay: """E2E tests for review display.""" def test__reviews_list__displays_reviews(self, page: Page, live_server, parks_data): """Test reviews list displays existing reviews.""" park = parks_data[0] page.goto(f"{live_server.url}/parks/{park.slug}/") # Navigate to reviews section reviews_tab = page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() # Reviews should be displayed reviews_section = page.locator( "[data-testid='reviews-list'], .reviews-list, .review-item" ) if reviews_section.count() > 0: expect(reviews_section.first).to_be_visible() def test__review__shows_rating(self, page: Page, live_server, test_review): """Test review displays rating.""" # test_review fixture creates a review page.goto(f"{page.url}") # Stay on current page after fixture # Rating should be visible (stars, number, etc.) rating = page.locator( ".rating, .stars, [data-testid='rating']" ) if rating.count() > 0: expect(rating.first).to_be_visible() def test__review__shows_author(self, page: Page, live_server, parks_data): """Test review displays author name.""" park = parks_data[0] page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() # Author name should be visible in review author = page.locator( ".review-author, .author, [data-testid='author']" ) if author.count() > 0: expect(author.first).to_be_visible() @pytest.mark.e2e class TestReviewEditing: """E2E tests for review editing.""" def test__own_review__shows_edit_button(self, auth_page: Page, live_server, test_review): """Test user's own review shows edit button.""" # Navigate to reviews after creating one park_url = auth_page.url # Look for edit button on own review edit_button = auth_page.locator( "button:has-text('Edit'), a:has-text('Edit Review')" ) if edit_button.count() > 0: expect(edit_button.first).to_be_visible() def test__edit_review__updates_content(self, auth_page: Page, live_server, test_review): """Test editing review updates the content.""" # Find and click edit edit_button = auth_page.locator( "button:has-text('Edit'), a:has-text('Edit Review')" ) if edit_button.count() > 0: edit_button.first.click() # Update content content_field = auth_page.locator( "textarea[name='content'], textarea[name='review']" ) content_field.first.fill("Updated review content from E2E test") auth_page.get_by_role("button", name="Save").click() # Should show updated content auth_page.wait_for_timeout(500) expect(auth_page.get_by_text("Updated review content")).to_be_visible() @pytest.mark.e2e class TestReviewModeration: """E2E tests for review moderation.""" def test__moderator__sees_moderation_actions( self, mod_page: Page, live_server, parks_data ): """Test moderator sees moderation actions on reviews.""" park = parks_data[0] mod_page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = mod_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() # Moderator should see moderation buttons mod_actions = mod_page.locator( "button:has-text('Remove'), button:has-text('Flag'), [data-testid='mod-action']" ) if mod_actions.count() > 0: expect(mod_actions.first).to_be_visible() def test__moderator__can_remove_review(self, mod_page: Page, live_server, parks_data): """Test moderator can remove a review.""" park = parks_data[0] mod_page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = mod_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() remove_button = mod_page.locator("button:has-text('Remove')") if remove_button.count() > 0: remove_button.first.click() # Confirm if dialog appears confirm = mod_page.locator("button:has-text('Confirm')") if confirm.count() > 0: confirm.click() mod_page.wait_for_timeout(500) @pytest.mark.e2e class TestReviewVoting: """E2E tests for review voting (helpful/not helpful).""" def test__review__shows_vote_buttons(self, page: Page, live_server, parks_data): """Test reviews show vote buttons.""" park = parks_data[0] page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() # Look for helpful/upvote buttons vote_buttons = page.locator( "button:has-text('Helpful'), button[aria-label*='helpful'], .vote-button" ) if vote_buttons.count() > 0: expect(vote_buttons.first).to_be_visible() def test__vote__authenticated__registers_vote( self, auth_page: Page, live_server, parks_data ): """Test authenticated user can vote on review.""" park = parks_data[0] auth_page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = auth_page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() helpful_button = auth_page.locator( "button:has-text('Helpful'), button[aria-label*='helpful']" ) if helpful_button.count() > 0: helpful_button.first.click() # Button should show voted state auth_page.wait_for_timeout(500) @pytest.mark.e2e class TestRideReviews: """E2E tests for ride-specific reviews.""" def test__ride_page__shows_reviews(self, page: Page, live_server, rides_data): """Test ride page shows reviews section.""" ride = rides_data[0] page.goto(f"{live_server.url}/rides/{ride.slug}/") # Reviews section should be present reviews_section = page.locator( "[data-testid='reviews'], #reviews, .reviews-section" ) if reviews_section.count() > 0: expect(reviews_section.first).to_be_visible() def test__ride_review__includes_ride_experience_fields( self, auth_page: Page, live_server, rides_data ): """Test ride review form includes experience fields.""" ride = rides_data[0] auth_page.goto(f"{live_server.url}/rides/{ride.slug}/") write_review = auth_page.locator( "button:has-text('Write Review'), a:has-text('Write Review')" ) if write_review.count() > 0: write_review.first.click() # Ride-specific fields intensity_field = auth_page.locator( "select[name='intensity'], input[name='intensity']" ) wait_time_field = auth_page.locator( "input[name='wait_time'], select[name='wait_time']" ) # At least one experience field should be present if intensity_field.count() > 0: expect(intensity_field.first).to_be_visible() @pytest.mark.e2e class TestReviewFiltering: """E2E tests for review filtering and sorting.""" def test__reviews__sort_by_date(self, page: Page, live_server, parks_data): """Test reviews can be sorted by date.""" park = parks_data[0] page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() sort_select = page.locator( "select[name='sort'], [data-testid='sort-reviews']" ) if sort_select.count() > 0: sort_select.first.select_option("date") page.wait_for_timeout(500) def test__reviews__filter_by_rating(self, page: Page, live_server, parks_data): """Test reviews can be filtered by rating.""" park = parks_data[0] page.goto(f"{live_server.url}/parks/{park.slug}/") reviews_tab = page.get_by_role("tab", name="Reviews") if reviews_tab.count() > 0: reviews_tab.click() rating_filter = page.locator( "select[name='rating'], [data-testid='rating-filter']" ) if rating_filter.count() > 0: rating_filter.first.select_option("5") page.wait_for_timeout(500)