mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 12:51:09 -05:00
Add standardized HTMX conventions, interaction patterns, and migration guide for ThrillWiki UX
This commit is contained in:
230
backend/tests/integration/test_fsm_transition_workflow.py
Normal file
230
backend/tests/integration/test_fsm_transition_workflow.py
Normal file
@@ -0,0 +1,230 @@
|
||||
"""
|
||||
Integration tests for FSM (Finite State Machine) transition workflows.
|
||||
|
||||
These tests verify the complete state transition workflows for
|
||||
Parks and Rides using the FSM implementation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from datetime import date, timedelta
|
||||
from django.test import TestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from apps.parks.models import Park
|
||||
from apps.rides.models import Ride
|
||||
|
||||
from tests.factories import (
|
||||
ParkFactory,
|
||||
RideFactory,
|
||||
UserFactory,
|
||||
ParkAreaFactory,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkFSMTransitions(TestCase):
|
||||
"""Integration tests for Park FSM transitions."""
|
||||
|
||||
def test__park_operating_to_closed_temp__transition_succeeds(self):
|
||||
"""Test transitioning operating park to temporarily closed."""
|
||||
park = ParkFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
park.close_temporarily(user=user)
|
||||
|
||||
assert park.status == "CLOSED_TEMP"
|
||||
|
||||
def test__park_closed_temp_to_operating__transition_succeeds(self):
|
||||
"""Test reopening temporarily closed park."""
|
||||
park = ParkFactory(status="CLOSED_TEMP")
|
||||
user = UserFactory()
|
||||
|
||||
park.open(user=user)
|
||||
|
||||
assert park.status == "OPERATING"
|
||||
|
||||
def test__park_operating_to_closed_perm__transition_succeeds(self):
|
||||
"""Test closing operating park permanently."""
|
||||
park = ParkFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
park.close_permanently(user=user)
|
||||
|
||||
assert park.status == "CLOSED_PERM"
|
||||
|
||||
def test__park_closed_perm_to_operating__transition_not_allowed(self):
|
||||
"""Test permanently closed park cannot reopen."""
|
||||
park = ParkFactory(status="CLOSED_PERM")
|
||||
user = UserFactory()
|
||||
|
||||
# This should fail - can't reopen permanently closed park
|
||||
with pytest.raises(Exception):
|
||||
park.open(user=user)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestRideFSMTransitions(TestCase):
|
||||
"""Integration tests for Ride FSM transitions."""
|
||||
|
||||
def test__ride_operating_to_closed_temp__transition_succeeds(self):
|
||||
"""Test transitioning operating ride to temporarily closed."""
|
||||
ride = RideFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
ride.close_temporarily(user=user)
|
||||
|
||||
assert ride.status == "CLOSED_TEMP"
|
||||
|
||||
def test__ride_closed_temp_to_operating__transition_succeeds(self):
|
||||
"""Test reopening temporarily closed ride."""
|
||||
ride = RideFactory(status="CLOSED_TEMP")
|
||||
user = UserFactory()
|
||||
|
||||
ride.open(user=user)
|
||||
|
||||
assert ride.status == "OPERATING"
|
||||
|
||||
def test__ride_operating_to_sbno__transition_succeeds(self):
|
||||
"""Test transitioning operating ride to SBNO (Standing But Not Operating)."""
|
||||
ride = RideFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
ride.mark_sbno(user=user)
|
||||
|
||||
assert ride.status == "SBNO"
|
||||
|
||||
def test__ride_sbno_to_operating__transition_succeeds(self):
|
||||
"""Test reopening SBNO ride."""
|
||||
ride = RideFactory(status="SBNO")
|
||||
user = UserFactory()
|
||||
|
||||
ride.open(user=user)
|
||||
|
||||
assert ride.status == "OPERATING"
|
||||
|
||||
def test__ride_operating_to_closing__with_date__transition_succeeds(self):
|
||||
"""Test scheduling ride for closing."""
|
||||
ride = RideFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
closing_date = date.today() + timedelta(days=30)
|
||||
|
||||
ride.mark_closing(
|
||||
closing_date=closing_date,
|
||||
post_closing_status="DEMOLISHED",
|
||||
user=user,
|
||||
)
|
||||
|
||||
assert ride.status == "CLOSING"
|
||||
assert ride.closing_date == closing_date
|
||||
assert ride.post_closing_status == "DEMOLISHED"
|
||||
|
||||
def test__ride_closing_to_demolished__transition_succeeds(self):
|
||||
"""Test transitioning closing ride to demolished."""
|
||||
ride = RideFactory(status="CLOSING")
|
||||
ride.post_closing_status = "DEMOLISHED"
|
||||
ride.save()
|
||||
user = UserFactory()
|
||||
|
||||
ride.demolish(user=user)
|
||||
|
||||
assert ride.status == "DEMOLISHED"
|
||||
|
||||
def test__ride_operating_to_relocated__transition_succeeds(self):
|
||||
"""Test marking ride as relocated."""
|
||||
ride = RideFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
ride.relocate(user=user)
|
||||
|
||||
assert ride.status == "RELOCATED"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestRideRelocationWorkflow(TestCase):
|
||||
"""Integration tests for ride relocation workflow."""
|
||||
|
||||
def test__relocate_ride__to_new_park__updates_park(self):
|
||||
"""Test relocating ride to new park updates the park relationship."""
|
||||
old_park = ParkFactory(name="Old Park")
|
||||
new_park = ParkFactory(name="New Park")
|
||||
ride = RideFactory(park=old_park, status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
# Mark as relocated first
|
||||
ride.relocate(user=user)
|
||||
assert ride.status == "RELOCATED"
|
||||
|
||||
# Move to new park
|
||||
ride.move_to_park(new_park, clear_park_area=True)
|
||||
|
||||
assert ride.park == new_park
|
||||
assert ride.park_area is None # Cleared during relocation
|
||||
|
||||
def test__relocate_ride__clears_park_area(self):
|
||||
"""Test relocating ride clears park area."""
|
||||
park = ParkFactory()
|
||||
area = ParkAreaFactory(park=park)
|
||||
new_park = ParkFactory()
|
||||
|
||||
ride = RideFactory(park=park, park_area=area, status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
ride.relocate(user=user)
|
||||
ride.move_to_park(new_park, clear_park_area=True)
|
||||
|
||||
assert ride.park_area is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestRideStatusTransitionHistory(TestCase):
|
||||
"""Integration tests for ride status transition history."""
|
||||
|
||||
def test__multiple_transitions__records_status_since(self):
|
||||
"""Test multiple transitions update status_since correctly."""
|
||||
ride = RideFactory(status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
# First transition
|
||||
ride.close_temporarily(user=user)
|
||||
first_status_since = ride.status_since
|
||||
|
||||
assert ride.status == "CLOSED_TEMP"
|
||||
|
||||
# Second transition
|
||||
ride.open(user=user)
|
||||
second_status_since = ride.status_since
|
||||
|
||||
assert ride.status == "OPERATING"
|
||||
# status_since should be updated for new transition
|
||||
assert second_status_since >= first_status_since
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkRideCascadeStatus(TestCase):
|
||||
"""Integration tests for park status affecting rides."""
|
||||
|
||||
def test__close_park__does_not_auto_close_rides(self):
|
||||
"""Test closing park doesn't automatically close rides."""
|
||||
park = ParkFactory(status="OPERATING")
|
||||
ride = RideFactory(park=park, status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
# Close the park
|
||||
park.close_temporarily(user=user)
|
||||
|
||||
# Ride should still be operating (business decision)
|
||||
ride.refresh_from_db()
|
||||
assert ride.status == "OPERATING" # Rides keep their independent status
|
||||
|
||||
def test__reopen_park__allows_ride_operation(self):
|
||||
"""Test reopening park allows rides to continue operating."""
|
||||
park = ParkFactory(status="CLOSED_TEMP")
|
||||
ride = RideFactory(park=park, status="OPERATING")
|
||||
user = UserFactory()
|
||||
|
||||
# Reopen park
|
||||
park.open(user=user)
|
||||
|
||||
assert park.status == "OPERATING"
|
||||
ride.refresh_from_db()
|
||||
assert ride.status == "OPERATING"
|
||||
233
backend/tests/integration/test_park_creation_workflow.py
Normal file
233
backend/tests/integration/test_park_creation_workflow.py
Normal file
@@ -0,0 +1,233 @@
|
||||
"""
|
||||
Integration tests for park creation workflow.
|
||||
|
||||
These tests verify the complete workflow of park creation including
|
||||
validation, location creation, and related operations.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
from django.db import transaction
|
||||
|
||||
from apps.parks.models import Park, ParkArea, ParkReview
|
||||
from apps.parks.forms import ParkForm
|
||||
|
||||
from tests.factories import (
|
||||
ParkFactory,
|
||||
ParkAreaFactory,
|
||||
OperatorCompanyFactory,
|
||||
UserFactory,
|
||||
RideFactory,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkCreationWorkflow(TestCase):
|
||||
"""Integration tests for complete park creation workflow."""
|
||||
|
||||
def test__create_park_with_form__valid_data__creates_park_and_location(self):
|
||||
"""Test creating a park with form creates both park and location."""
|
||||
operator = OperatorCompanyFactory()
|
||||
|
||||
data = {
|
||||
"name": "New Test Park",
|
||||
"operator": operator.pk,
|
||||
"status": "OPERATING",
|
||||
"latitude": "37.123456",
|
||||
"longitude": "-122.654321",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "USA",
|
||||
}
|
||||
|
||||
form = ParkForm(data=data)
|
||||
|
||||
if form.is_valid():
|
||||
park = form.save()
|
||||
|
||||
# Verify park was created
|
||||
assert park.pk is not None
|
||||
assert park.name == "New Test Park"
|
||||
assert park.operator == operator
|
||||
|
||||
# Verify location was created
|
||||
if park.location.exists():
|
||||
location = park.location.first()
|
||||
assert location.city == "San Francisco"
|
||||
assert location.country == "USA"
|
||||
|
||||
def test__create_park__with_areas__creates_complete_structure(self):
|
||||
"""Test creating a park with areas creates complete structure."""
|
||||
park = ParkFactory()
|
||||
|
||||
# Add areas
|
||||
area1 = ParkAreaFactory(park=park, name="Main Entrance")
|
||||
area2 = ParkAreaFactory(park=park, name="Thrill Zone")
|
||||
area3 = ParkAreaFactory(park=park, name="Kids Area")
|
||||
|
||||
# Verify structure
|
||||
assert park.areas.count() == 3
|
||||
assert park.areas.filter(name="Main Entrance").exists()
|
||||
assert park.areas.filter(name="Thrill Zone").exists()
|
||||
assert park.areas.filter(name="Kids Area").exists()
|
||||
|
||||
def test__create_park__with_rides__updates_counts(self):
|
||||
"""Test creating a park with rides updates ride counts."""
|
||||
park = ParkFactory()
|
||||
|
||||
# Add rides
|
||||
RideFactory(park=park, category="RC") # Roller coaster
|
||||
RideFactory(park=park, category="RC") # Roller coaster
|
||||
RideFactory(park=park, category="TR") # Thrill ride
|
||||
RideFactory(park=park, category="DR") # Dark ride
|
||||
|
||||
# Verify ride counts
|
||||
assert park.rides.count() == 4
|
||||
assert park.rides.filter(category="RC").count() == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkUpdateWorkflow(TestCase):
|
||||
"""Integration tests for park update workflow."""
|
||||
|
||||
def test__update_park__changes_status__updates_correctly(self):
|
||||
"""Test updating park status updates correctly."""
|
||||
park = ParkFactory(status="OPERATING")
|
||||
|
||||
# Update via FSM transition
|
||||
park.close_temporarily()
|
||||
|
||||
park.refresh_from_db()
|
||||
assert park.status == "CLOSED_TEMP"
|
||||
|
||||
def test__update_park_location__updates_location_record(self):
|
||||
"""Test updating park location updates the location record."""
|
||||
park = ParkFactory()
|
||||
|
||||
form_data = {
|
||||
"name": park.name,
|
||||
"operator": park.operator.pk,
|
||||
"status": park.status,
|
||||
"city": "New City",
|
||||
"state": "NY",
|
||||
"country": "USA",
|
||||
}
|
||||
|
||||
form = ParkForm(instance=park, data=form_data)
|
||||
|
||||
if form.is_valid():
|
||||
updated_park = form.save()
|
||||
|
||||
# Verify location was updated
|
||||
if updated_park.location.exists():
|
||||
location = updated_park.location.first()
|
||||
assert location.city == "New City"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkReviewWorkflow(TestCase):
|
||||
"""Integration tests for park review workflow."""
|
||||
|
||||
def test__add_review__updates_park_rating(self):
|
||||
"""Test adding a review affects park's average rating."""
|
||||
park = ParkFactory()
|
||||
user1 = UserFactory()
|
||||
user2 = UserFactory()
|
||||
|
||||
# Add reviews
|
||||
from tests.factories import ParkReviewFactory
|
||||
|
||||
ParkReviewFactory(park=park, user=user1, rating=8, is_published=True)
|
||||
ParkReviewFactory(park=park, user=user2, rating=10, is_published=True)
|
||||
|
||||
# Calculate average
|
||||
avg = park.reviews.filter(is_published=True).values_list(
|
||||
"rating", flat=True
|
||||
)
|
||||
calculated_avg = sum(avg) / len(avg)
|
||||
|
||||
assert calculated_avg == 9.0
|
||||
|
||||
def test__unpublish_review__excludes_from_rating(self):
|
||||
"""Test unpublishing a review excludes it from rating calculation."""
|
||||
park = ParkFactory()
|
||||
user1 = UserFactory()
|
||||
user2 = UserFactory()
|
||||
|
||||
from tests.factories import ParkReviewFactory
|
||||
|
||||
review1 = ParkReviewFactory(park=park, user=user1, rating=10, is_published=True)
|
||||
review2 = ParkReviewFactory(park=park, user=user2, rating=2, is_published=True)
|
||||
|
||||
# Unpublish the low rating
|
||||
review2.is_published = False
|
||||
review2.save()
|
||||
|
||||
# Calculate average - should only include published reviews
|
||||
published_reviews = park.reviews.filter(is_published=True)
|
||||
assert published_reviews.count() == 1
|
||||
assert published_reviews.first().rating == 10
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkAreaRideWorkflow(TestCase):
|
||||
"""Integration tests for park area and ride workflow."""
|
||||
|
||||
def test__add_ride_to_area__associates_correctly(self):
|
||||
"""Test adding a ride to an area associates them correctly."""
|
||||
park = ParkFactory()
|
||||
area = ParkAreaFactory(park=park, name="Thrill Zone")
|
||||
|
||||
ride = RideFactory(park=park, park_area=area, name="Super Coaster")
|
||||
|
||||
assert ride.park_area == area
|
||||
assert ride in area.rides.all()
|
||||
|
||||
def test__delete_area__handles_rides_correctly(self):
|
||||
"""Test deleting an area handles associated rides."""
|
||||
park = ParkFactory()
|
||||
area = ParkAreaFactory(park=park)
|
||||
ride = RideFactory(park=park, park_area=area)
|
||||
|
||||
ride_pk = ride.pk
|
||||
|
||||
# Delete area - ride should have park_area set to NULL
|
||||
area.delete()
|
||||
|
||||
ride.refresh_from_db()
|
||||
assert ride.park_area is None
|
||||
assert ride.pk == ride_pk # Ride still exists
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkOperatorWorkflow(TestCase):
|
||||
"""Integration tests for park operator workflow."""
|
||||
|
||||
def test__change_operator__updates_park(self):
|
||||
"""Test changing park operator updates the relationship."""
|
||||
old_operator = OperatorCompanyFactory(name="Old Operator")
|
||||
new_operator = OperatorCompanyFactory(name="New Operator")
|
||||
park = ParkFactory(operator=old_operator)
|
||||
|
||||
# Change operator
|
||||
park.operator = new_operator
|
||||
park.save()
|
||||
|
||||
park.refresh_from_db()
|
||||
assert park.operator == new_operator
|
||||
assert park.operator.name == "New Operator"
|
||||
|
||||
def test__operator_with_multiple_parks__lists_all_parks(self):
|
||||
"""Test operator with multiple parks lists all parks."""
|
||||
operator = OperatorCompanyFactory()
|
||||
|
||||
park1 = ParkFactory(operator=operator, name="Park One")
|
||||
park2 = ParkFactory(operator=operator, name="Park Two")
|
||||
park3 = ParkFactory(operator=operator, name="Park Three")
|
||||
|
||||
# Verify operator's parks
|
||||
operator_parks = operator.operated_parks.all()
|
||||
assert operator_parks.count() == 3
|
||||
assert park1 in operator_parks
|
||||
assert park2 in operator_parks
|
||||
assert park3 in operator_parks
|
||||
224
backend/tests/integration/test_photo_upload_workflow.py
Normal file
224
backend/tests/integration/test_photo_upload_workflow.py
Normal file
@@ -0,0 +1,224 @@
|
||||
"""
|
||||
Integration tests for photo upload workflow.
|
||||
|
||||
These tests verify the complete workflow of photo uploads including
|
||||
validation, processing, and moderation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch
|
||||
from django.test import TestCase
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
|
||||
from apps.parks.models import ParkPhoto
|
||||
from apps.rides.models import RidePhoto
|
||||
from apps.parks.services.media_service import ParkMediaService
|
||||
|
||||
from tests.factories import (
|
||||
ParkFactory,
|
||||
RideFactory,
|
||||
ParkPhotoFactory,
|
||||
RidePhotoFactory,
|
||||
UserFactory,
|
||||
StaffUserFactory,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestParkPhotoUploadWorkflow(TestCase):
|
||||
"""Integration tests for park photo upload workflow."""
|
||||
|
||||
@patch("apps.parks.services.media_service.MediaService.validate_image_file")
|
||||
@patch("apps.parks.services.media_service.MediaService.process_image")
|
||||
@patch("apps.parks.services.media_service.MediaService.generate_default_caption")
|
||||
@patch("apps.parks.services.media_service.MediaService.extract_exif_date")
|
||||
def test__upload_photo__creates_pending_photo(
|
||||
self, mock_exif, mock_caption, mock_process, mock_validate
|
||||
):
|
||||
"""Test uploading photo creates a pending photo."""
|
||||
mock_validate.return_value = (True, None)
|
||||
mock_process.return_value = Mock()
|
||||
mock_caption.return_value = "Photo by testuser"
|
||||
mock_exif.return_value = None
|
||||
|
||||
park = ParkFactory()
|
||||
user = UserFactory()
|
||||
image = SimpleUploadedFile("test.jpg", b"image data", content_type="image/jpeg")
|
||||
|
||||
photo = ParkMediaService.upload_photo(
|
||||
park=park,
|
||||
image_file=image,
|
||||
user=user,
|
||||
caption="Test photo",
|
||||
auto_approve=False,
|
||||
)
|
||||
|
||||
assert photo.is_approved is False
|
||||
assert photo.uploaded_by == user
|
||||
assert photo.park == park
|
||||
|
||||
@patch("apps.parks.services.media_service.MediaService.validate_image_file")
|
||||
@patch("apps.parks.services.media_service.MediaService.process_image")
|
||||
@patch("apps.parks.services.media_service.MediaService.generate_default_caption")
|
||||
@patch("apps.parks.services.media_service.MediaService.extract_exif_date")
|
||||
def test__upload_photo__auto_approve__creates_approved_photo(
|
||||
self, mock_exif, mock_caption, mock_process, mock_validate
|
||||
):
|
||||
"""Test uploading photo with auto_approve creates approved photo."""
|
||||
mock_validate.return_value = (True, None)
|
||||
mock_process.return_value = Mock()
|
||||
mock_caption.return_value = "Photo by testuser"
|
||||
mock_exif.return_value = None
|
||||
|
||||
park = ParkFactory()
|
||||
user = UserFactory()
|
||||
image = SimpleUploadedFile("test.jpg", b"image data", content_type="image/jpeg")
|
||||
|
||||
photo = ParkMediaService.upload_photo(
|
||||
park=park,
|
||||
image_file=image,
|
||||
user=user,
|
||||
auto_approve=True,
|
||||
)
|
||||
|
||||
assert photo.is_approved is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestPhotoModerationWorkflow(TestCase):
|
||||
"""Integration tests for photo moderation workflow."""
|
||||
|
||||
def test__approve_photo__marks_as_approved(self):
|
||||
"""Test approving a photo marks it as approved."""
|
||||
photo = ParkPhotoFactory(is_approved=False)
|
||||
moderator = StaffUserFactory()
|
||||
|
||||
result = ParkMediaService.approve_photo(photo, moderator)
|
||||
|
||||
photo.refresh_from_db()
|
||||
assert result is True
|
||||
assert photo.is_approved is True
|
||||
|
||||
def test__bulk_approve_photos__approves_all(self):
|
||||
"""Test bulk approving photos approves all photos."""
|
||||
park = ParkFactory()
|
||||
photos = [
|
||||
ParkPhotoFactory(park=park, is_approved=False),
|
||||
ParkPhotoFactory(park=park, is_approved=False),
|
||||
ParkPhotoFactory(park=park, is_approved=False),
|
||||
]
|
||||
moderator = StaffUserFactory()
|
||||
|
||||
count = ParkMediaService.bulk_approve_photos(photos, moderator)
|
||||
|
||||
assert count == 3
|
||||
for photo in photos:
|
||||
photo.refresh_from_db()
|
||||
assert photo.is_approved is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestPrimaryPhotoWorkflow(TestCase):
|
||||
"""Integration tests for primary photo workflow."""
|
||||
|
||||
def test__set_primary_photo__unsets_previous_primary(self):
|
||||
"""Test setting primary photo unsets previous primary."""
|
||||
park = ParkFactory()
|
||||
old_primary = ParkPhotoFactory(park=park, is_primary=True)
|
||||
new_primary = ParkPhotoFactory(park=park, is_primary=False)
|
||||
|
||||
result = ParkMediaService.set_primary_photo(park, new_primary)
|
||||
|
||||
old_primary.refresh_from_db()
|
||||
new_primary.refresh_from_db()
|
||||
|
||||
assert result is True
|
||||
assert old_primary.is_primary is False
|
||||
assert new_primary.is_primary is True
|
||||
|
||||
def test__get_primary_photo__returns_correct_photo(self):
|
||||
"""Test get_primary_photo returns the primary photo."""
|
||||
park = ParkFactory()
|
||||
ParkPhotoFactory(park=park, is_primary=False, is_approved=True)
|
||||
primary = ParkPhotoFactory(park=park, is_primary=True, is_approved=True)
|
||||
ParkPhotoFactory(park=park, is_primary=False, is_approved=True)
|
||||
|
||||
result = ParkMediaService.get_primary_photo(park)
|
||||
|
||||
assert result == primary
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestPhotoStatsWorkflow(TestCase):
|
||||
"""Integration tests for photo statistics workflow."""
|
||||
|
||||
def test__get_photo_stats__returns_accurate_counts(self):
|
||||
"""Test get_photo_stats returns accurate statistics."""
|
||||
park = ParkFactory()
|
||||
|
||||
# Create various photos
|
||||
ParkPhotoFactory(park=park, is_approved=True)
|
||||
ParkPhotoFactory(park=park, is_approved=True)
|
||||
ParkPhotoFactory(park=park, is_approved=False)
|
||||
ParkPhotoFactory(park=park, is_approved=True, is_primary=True)
|
||||
|
||||
stats = ParkMediaService.get_photo_stats(park)
|
||||
|
||||
assert stats["total_photos"] == 4
|
||||
assert stats["approved_photos"] == 3
|
||||
assert stats["pending_photos"] == 1
|
||||
assert stats["has_primary"] is True
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestPhotoDeleteWorkflow(TestCase):
|
||||
"""Integration tests for photo deletion workflow."""
|
||||
|
||||
def test__delete_photo__removes_photo(self):
|
||||
"""Test deleting a photo removes it from database."""
|
||||
photo = ParkPhotoFactory()
|
||||
photo_id = photo.pk
|
||||
moderator = StaffUserFactory()
|
||||
|
||||
result = ParkMediaService.delete_photo(photo, moderator)
|
||||
|
||||
assert result is True
|
||||
assert not ParkPhoto.objects.filter(pk=photo_id).exists()
|
||||
|
||||
def test__delete_primary_photo__removes_primary(self):
|
||||
"""Test deleting primary photo removes primary status."""
|
||||
park = ParkFactory()
|
||||
primary = ParkPhotoFactory(park=park, is_primary=True)
|
||||
moderator = StaffUserFactory()
|
||||
|
||||
ParkMediaService.delete_photo(primary, moderator)
|
||||
|
||||
# Park should no longer have a primary photo
|
||||
result = ParkMediaService.get_primary_photo(park)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestRidePhotoWorkflow(TestCase):
|
||||
"""Integration tests for ride photo workflow."""
|
||||
|
||||
def test__ride_photo__includes_park_info(self):
|
||||
"""Test ride photo includes park information."""
|
||||
ride = RideFactory()
|
||||
photo = RidePhotoFactory(ride=ride)
|
||||
|
||||
# Photo should have access to park through ride
|
||||
assert photo.ride.park is not None
|
||||
assert photo.ride.park.name is not None
|
||||
|
||||
def test__ride_photo__different_types(self):
|
||||
"""Test ride photos can have different types."""
|
||||
ride = RideFactory()
|
||||
|
||||
exterior = RidePhotoFactory(ride=ride, photo_type="exterior")
|
||||
queue = RidePhotoFactory(ride=ride, photo_type="queue")
|
||||
onride = RidePhotoFactory(ride=ride, photo_type="onride")
|
||||
|
||||
assert ride.photos.filter(photo_type="exterior").count() == 1
|
||||
assert ride.photos.filter(photo_type="queue").count() == 1
|
||||
assert ride.photos.filter(photo_type="onride").count() == 1
|
||||
Reference in New Issue
Block a user