mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 01:51:09 -05:00
373 lines
13 KiB
Python
373 lines
13 KiB
Python
"""
|
|
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)
|