feat: Implement initial schema and add various API, service, and management command enhancements across the application.

This commit is contained in:
pacnpal
2026-01-01 15:13:01 -05:00
parent c95f99ca10
commit b243b17af7
413 changed files with 11164 additions and 17433 deletions

View File

@@ -24,9 +24,7 @@ class TestReviewSubmission:
reviews_tab.click()
# Click write review button
write_review = auth_page.locator(
"button:has-text('Write Review'), a:has-text('Write Review')"
)
write_review = auth_page.locator("button:has-text('Write Review'), a:has-text('Write Review')")
if write_review.count() > 0:
write_review.first.click()
@@ -36,9 +34,7 @@ class TestReviewSubmission:
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
):
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}/")
@@ -48,9 +44,7 @@ class TestReviewSubmission:
if reviews_tab.count() > 0:
reviews_tab.click()
write_review = auth_page.locator(
"button:has-text('Write Review'), a:has-text('Write Review')"
)
write_review = auth_page.locator("button:has-text('Write Review'), a:has-text('Write Review')")
if write_review.count() > 0:
write_review.first.click()
@@ -63,9 +57,7 @@ class TestReviewSubmission:
# 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("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."
)
@@ -75,9 +67,7 @@ class TestReviewSubmission:
# 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
):
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}/")
@@ -86,20 +76,14 @@ class TestReviewSubmission:
if reviews_tab.count() > 0:
reviews_tab.click()
write_review = auth_page.locator(
"button:has-text('Write Review'), a:has-text('Write Review')"
)
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.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()
@@ -123,9 +107,7 @@ class TestReviewDisplay:
reviews_tab.click()
# Reviews should be displayed
reviews_section = page.locator(
"[data-testid='reviews-list'], .reviews-list, .review-item"
)
reviews_section = page.locator("[data-testid='reviews-list'], .reviews-list, .review-item")
if reviews_section.count() > 0:
expect(reviews_section.first).to_be_visible()
@@ -136,9 +118,7 @@ class TestReviewDisplay:
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']"
)
rating = page.locator(".rating, .stars, [data-testid='rating']")
if rating.count() > 0:
expect(rating.first).to_be_visible()
@@ -153,9 +133,7 @@ class TestReviewDisplay:
reviews_tab.click()
# Author name should be visible in review
author = page.locator(
".review-author, .author, [data-testid='author']"
)
author = page.locator(".review-author, .author, [data-testid='author']")
if author.count() > 0:
expect(author.first).to_be_visible()
@@ -170,9 +148,7 @@ class TestReviewEditing:
# Navigate to reviews after creating one
# Look for edit button on own review
edit_button = auth_page.locator(
"button:has-text('Edit'), a:has-text('Edit 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()
@@ -180,17 +156,13 @@ class TestReviewEditing:
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')"
)
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 = 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()
@@ -204,9 +176,7 @@ class TestReviewEditing:
class TestReviewModeration:
"""E2E tests for review moderation."""
def test__moderator__sees_moderation_actions(
self, mod_page: Page, live_server, parks_data
):
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}/")
@@ -216,9 +186,7 @@ class TestReviewModeration:
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']"
)
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()
@@ -259,16 +227,12 @@ class TestReviewVoting:
reviews_tab.click()
# Look for helpful/upvote buttons
vote_buttons = page.locator(
"button:has-text('Helpful'), button[aria-label*='helpful'], .vote-button"
)
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
):
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}/")
@@ -277,9 +241,7 @@ class TestReviewVoting:
if reviews_tab.count() > 0:
reviews_tab.click()
helpful_button = auth_page.locator(
"button:has-text('Helpful'), button[aria-label*='helpful']"
)
helpful_button = auth_page.locator("button:has-text('Helpful'), button[aria-label*='helpful']")
if helpful_button.count() > 0:
helpful_button.first.click()
@@ -298,34 +260,24 @@ class TestRideReviews:
page.goto(f"{live_server.url}/rides/{ride.slug}/")
# Reviews section should be present
reviews_section = page.locator(
"[data-testid='reviews'], #reviews, .reviews-section"
)
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
):
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')"
)
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']"
)
auth_page.locator(
"input[name='wait_time'], select[name='wait_time']"
)
intensity_field = auth_page.locator("select[name='intensity'], input[name='intensity']")
auth_page.locator("input[name='wait_time'], select[name='wait_time']")
# At least one experience field should be present
if intensity_field.count() > 0:
@@ -345,9 +297,7 @@ class TestReviewFiltering:
if reviews_tab.count() > 0:
reviews_tab.click()
sort_select = page.locator(
"select[name='sort'], [data-testid='sort-reviews']"
)
sort_select = page.locator("select[name='sort'], [data-testid='sort-reviews']")
if sort_select.count() > 0:
sort_select.first.select_option("date")
@@ -362,9 +312,7 @@ class TestReviewFiltering:
if reviews_tab.count() > 0:
reviews_tab.click()
rating_filter = page.locator(
"select[name='rating'], [data-testid='rating-filter']"
)
rating_filter = page.locator("select[name='rating'], [data-testid='rating-filter']")
if rating_filter.count() > 0:
rating_filter.first.select_option("5")