Files
thrillwiki_django_no_react/backend/apps/rides/tests.py
pacnpal b508434574 Add state machine diagrams and code examples for ThrillWiki
- Created a comprehensive documentation file for state machine diagrams, detailing various states and transitions for models such as EditSubmission, ModerationReport, and Park Status.
- Included transition matrices for each state machine to clarify role requirements and guards.
- Developed a new document providing code examples for implementing state machines, including adding new state machines to models, defining custom guards, implementing callbacks, and testing state machines.
- Added examples for document approval workflows, custom guards, email notifications, and cache invalidation callbacks.
- Implemented a test suite for document workflows, covering various scenarios including approval, rejection, and transition logging.
2025-12-21 20:21:54 -05:00

927 lines
32 KiB
Python

"""
Comprehensive tests for the rides app state machine.
This module contains tests for:
- Ride status FSM transitions
- Ride transition wrapper methods
- Post-closing status automation
- Transition history logging
- Related model updates during transitions
"""
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.utils import timezone
from django_fsm import TransitionNotAllowed
from .models import Ride, RideModel, Company
from apps.parks.models import Park, Company as ParkCompany
from datetime import date, timedelta
User = get_user_model()
# ============================================================================
# Ride FSM Transition Tests
# ============================================================================
class RideTransitionTests(TestCase):
"""Comprehensive tests for Ride FSM transitions."""
def setUp(self):
"""Set up test fixtures."""
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpass123',
role='USER'
)
self.moderator = User.objects.create_user(
username='moderator',
email='moderator@example.com',
password='testpass123',
role='MODERATOR'
)
self.admin = User.objects.create_user(
username='admin',
email='admin@example.com',
password='testpass123',
role='ADMIN'
)
# Create operator and park
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park = Park.objects.create(
name='Test Park',
slug='test-park',
description='A test park',
operator=self.operator,
timezone='America/New_York'
)
# Create manufacturer
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def _create_ride(self, status='OPERATING', **kwargs):
"""Helper to create a Ride with specified status."""
defaults = {
'name': 'Test Ride',
'slug': 'test-ride',
'description': 'A test ride',
'park': self.park,
'manufacturer': self.manufacturer
}
defaults.update(kwargs)
return Ride.objects.create(status=status, **defaults)
# -------------------------------------------------------------------------
# Operating status transitions
# -------------------------------------------------------------------------
def test_operating_to_closed_temp_transition(self):
"""Test transition from OPERATING to CLOSED_TEMP."""
ride = self._create_ride(status='OPERATING')
self.assertEqual(ride.status, 'OPERATING')
ride.transition_to_closed_temp(user=self.user)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_TEMP')
def test_operating_to_sbno_transition(self):
"""Test transition from OPERATING to SBNO."""
ride = self._create_ride(status='OPERATING')
ride.transition_to_sbno(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'SBNO')
def test_operating_to_closing_transition(self):
"""Test transition from OPERATING to CLOSING."""
ride = self._create_ride(status='OPERATING')
ride.transition_to_closing(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSING')
# -------------------------------------------------------------------------
# Under construction transitions
# -------------------------------------------------------------------------
def test_under_construction_to_operating_transition(self):
"""Test transition from UNDER_CONSTRUCTION to OPERATING."""
ride = self._create_ride(status='UNDER_CONSTRUCTION')
self.assertEqual(ride.status, 'UNDER_CONSTRUCTION')
ride.transition_to_operating(user=self.user)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'OPERATING')
# -------------------------------------------------------------------------
# Closed temp transitions
# -------------------------------------------------------------------------
def test_closed_temp_to_operating_transition(self):
"""Test transition from CLOSED_TEMP to OPERATING (reopen)."""
ride = self._create_ride(status='CLOSED_TEMP')
ride.transition_to_operating(user=self.user)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'OPERATING')
def test_closed_temp_to_sbno_transition(self):
"""Test transition from CLOSED_TEMP to SBNO."""
ride = self._create_ride(status='CLOSED_TEMP')
ride.transition_to_sbno(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'SBNO')
def test_closed_temp_to_closed_perm_transition(self):
"""Test transition from CLOSED_TEMP to CLOSED_PERM."""
ride = self._create_ride(status='CLOSED_TEMP')
ride.transition_to_closed_perm(user=self.moderator)
ride.closing_date = date.today()
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_PERM')
# -------------------------------------------------------------------------
# SBNO transitions
# -------------------------------------------------------------------------
def test_sbno_to_operating_transition(self):
"""Test transition from SBNO to OPERATING (revival)."""
ride = self._create_ride(status='SBNO')
ride.transition_to_operating(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'OPERATING')
def test_sbno_to_closed_perm_transition(self):
"""Test transition from SBNO to CLOSED_PERM."""
ride = self._create_ride(status='SBNO')
ride.transition_to_closed_perm(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_PERM')
# -------------------------------------------------------------------------
# Closing transitions
# -------------------------------------------------------------------------
def test_closing_to_closed_perm_transition(self):
"""Test transition from CLOSING to CLOSED_PERM."""
ride = self._create_ride(status='CLOSING')
ride.transition_to_closed_perm(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_PERM')
def test_closing_to_sbno_transition(self):
"""Test transition from CLOSING to SBNO."""
ride = self._create_ride(status='CLOSING')
ride.transition_to_sbno(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'SBNO')
# -------------------------------------------------------------------------
# Closed perm transitions (to final states)
# -------------------------------------------------------------------------
def test_closed_perm_to_demolished_transition(self):
"""Test transition from CLOSED_PERM to DEMOLISHED."""
ride = self._create_ride(status='CLOSED_PERM')
ride.transition_to_demolished(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'DEMOLISHED')
def test_closed_perm_to_relocated_transition(self):
"""Test transition from CLOSED_PERM to RELOCATED."""
ride = self._create_ride(status='CLOSED_PERM')
ride.transition_to_relocated(user=self.moderator)
ride.save()
ride.refresh_from_db()
self.assertEqual(ride.status, 'RELOCATED')
# -------------------------------------------------------------------------
# Invalid transitions (final states)
# -------------------------------------------------------------------------
def test_demolished_cannot_transition(self):
"""Test that DEMOLISHED state cannot transition further."""
ride = self._create_ride(status='DEMOLISHED')
with self.assertRaises(TransitionNotAllowed):
ride.transition_to_operating(user=self.moderator)
def test_relocated_cannot_transition(self):
"""Test that RELOCATED state cannot transition further."""
ride = self._create_ride(status='RELOCATED')
with self.assertRaises(TransitionNotAllowed):
ride.transition_to_operating(user=self.moderator)
def test_operating_cannot_directly_demolish(self):
"""Test that OPERATING cannot directly transition to DEMOLISHED."""
ride = self._create_ride(status='OPERATING')
with self.assertRaises(TransitionNotAllowed):
ride.transition_to_demolished(user=self.moderator)
def test_operating_cannot_directly_relocate(self):
"""Test that OPERATING cannot directly transition to RELOCATED."""
ride = self._create_ride(status='OPERATING')
with self.assertRaises(TransitionNotAllowed):
ride.transition_to_relocated(user=self.moderator)
# -------------------------------------------------------------------------
# Wrapper method tests
# -------------------------------------------------------------------------
def test_open_wrapper_method(self):
"""Test the open() wrapper method."""
ride = self._create_ride(status='CLOSED_TEMP')
ride.open(user=self.user)
ride.refresh_from_db()
self.assertEqual(ride.status, 'OPERATING')
def test_close_temporarily_wrapper_method(self):
"""Test the close_temporarily() wrapper method."""
ride = self._create_ride(status='OPERATING')
ride.close_temporarily(user=self.user)
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_TEMP')
def test_mark_sbno_wrapper_method(self):
"""Test the mark_sbno() wrapper method."""
ride = self._create_ride(status='OPERATING')
ride.mark_sbno(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'SBNO')
def test_mark_closing_wrapper_method(self):
"""Test the mark_closing() wrapper method."""
ride = self._create_ride(status='OPERATING')
closing = date(2025, 12, 31)
ride.mark_closing(
closing_date=closing,
post_closing_status='DEMOLISHED',
user=self.moderator
)
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSING')
self.assertEqual(ride.closing_date, closing)
self.assertEqual(ride.post_closing_status, 'DEMOLISHED')
def test_mark_closing_requires_post_closing_status(self):
"""Test that mark_closing() requires post_closing_status."""
ride = self._create_ride(status='OPERATING')
with self.assertRaises(ValidationError):
ride.mark_closing(
closing_date=date(2025, 12, 31),
post_closing_status='',
user=self.moderator
)
def test_close_permanently_wrapper_method(self):
"""Test the close_permanently() wrapper method."""
ride = self._create_ride(status='SBNO')
ride.close_permanently(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_PERM')
def test_demolish_wrapper_method(self):
"""Test the demolish() wrapper method."""
ride = self._create_ride(status='CLOSED_PERM')
ride.demolish(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'DEMOLISHED')
def test_relocate_wrapper_method(self):
"""Test the relocate() wrapper method."""
ride = self._create_ride(status='CLOSED_PERM')
ride.relocate(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'RELOCATED')
# ============================================================================
# Ride Post-Closing Status Tests
# ============================================================================
class RidePostClosingTests(TestCase):
"""Tests for Ride post_closing_status automation."""
def setUp(self):
"""Set up test fixtures."""
self.moderator = User.objects.create_user(
username='moderator',
email='moderator@example.com',
password='testpass123',
role='MODERATOR'
)
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park = Park.objects.create(
name='Test Park',
slug='test-park',
description='A test park',
operator=self.operator,
timezone='America/New_York'
)
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def _create_ride(self, status='OPERATING', **kwargs):
"""Helper to create a Ride."""
defaults = {
'name': 'Test Ride',
'slug': 'test-ride',
'description': 'A test ride',
'park': self.park,
'manufacturer': self.manufacturer
}
defaults.update(kwargs)
return Ride.objects.create(status=status, **defaults)
def test_apply_post_closing_status_to_demolished(self):
"""Test apply_post_closing_status transitions to DEMOLISHED."""
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=yesterday,
post_closing_status='DEMOLISHED'
)
ride.apply_post_closing_status(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'DEMOLISHED')
def test_apply_post_closing_status_to_relocated(self):
"""Test apply_post_closing_status transitions to RELOCATED."""
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=yesterday,
post_closing_status='RELOCATED'
)
ride.apply_post_closing_status(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'RELOCATED')
def test_apply_post_closing_status_to_sbno(self):
"""Test apply_post_closing_status transitions to SBNO."""
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=yesterday,
post_closing_status='SBNO'
)
ride.apply_post_closing_status(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'SBNO')
def test_apply_post_closing_status_to_closed_perm(self):
"""Test apply_post_closing_status transitions to CLOSED_PERM."""
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=yesterday,
post_closing_status='CLOSED_PERM'
)
ride.apply_post_closing_status(user=self.moderator)
ride.refresh_from_db()
self.assertEqual(ride.status, 'CLOSED_PERM')
def test_apply_post_closing_status_not_yet_reached(self):
"""Test apply_post_closing_status does nothing if date not reached."""
tomorrow = date.today() + timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=tomorrow,
post_closing_status='DEMOLISHED'
)
ride.apply_post_closing_status(user=self.moderator)
ride.refresh_from_db()
# Status should remain CLOSING since date hasn't been reached
self.assertEqual(ride.status, 'CLOSING')
def test_apply_post_closing_status_requires_closing_status(self):
"""Test apply_post_closing_status requires CLOSING status."""
ride = self._create_ride(status='OPERATING')
with self.assertRaises(ValidationError) as ctx:
ride.apply_post_closing_status(user=self.moderator)
self.assertIn('CLOSING', str(ctx.exception))
def test_apply_post_closing_status_requires_closing_date(self):
"""Test apply_post_closing_status requires closing_date."""
ride = self._create_ride(
status='CLOSING',
post_closing_status='DEMOLISHED'
)
ride.closing_date = None
ride.save()
with self.assertRaises(ValidationError) as ctx:
ride.apply_post_closing_status(user=self.moderator)
self.assertIn('closing_date', str(ctx.exception))
def test_apply_post_closing_status_requires_post_closing_status(self):
"""Test apply_post_closing_status requires post_closing_status."""
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(
status='CLOSING',
closing_date=yesterday
)
ride.post_closing_status = None
ride.save()
with self.assertRaises(ValidationError) as ctx:
ride.apply_post_closing_status(user=self.moderator)
self.assertIn('post_closing_status', str(ctx.exception))
# ============================================================================
# Ride Transition History Tests
# ============================================================================
class RideTransitionHistoryTests(TestCase):
"""Tests for Ride transition history logging."""
def setUp(self):
"""Set up test fixtures."""
self.moderator = User.objects.create_user(
username='moderator',
email='moderator@example.com',
password='testpass123',
role='MODERATOR'
)
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park = Park.objects.create(
name='Test Park',
slug='test-park',
description='A test park',
operator=self.operator,
timezone='America/New_York'
)
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def _create_ride(self, status='OPERATING'):
"""Helper to create a Ride."""
return Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer,
status=status
)
def test_transition_creates_state_log(self):
"""Test that transitions create StateLog entries."""
from django_fsm_log.models import StateLog
ride = self._create_ride(status='OPERATING')
ride.transition_to_closed_temp(user=self.moderator)
ride.save()
ride_ct = ContentType.objects.get_for_model(ride)
log = StateLog.objects.filter(
content_type=ride_ct,
object_id=ride.id
).first()
self.assertIsNotNone(log)
self.assertEqual(log.state, 'CLOSED_TEMP')
self.assertEqual(log.by, self.moderator)
def test_multiple_transitions_create_multiple_logs(self):
"""Test that multiple transitions create multiple log entries."""
from django_fsm_log.models import StateLog
ride = self._create_ride(status='OPERATING')
ride_ct = ContentType.objects.get_for_model(ride)
# First transition
ride.transition_to_closed_temp(user=self.moderator)
ride.save()
# Second transition
ride.transition_to_operating(user=self.moderator)
ride.save()
logs = StateLog.objects.filter(
content_type=ride_ct,
object_id=ride.id
).order_by('timestamp')
self.assertEqual(logs.count(), 2)
self.assertEqual(logs[0].state, 'CLOSED_TEMP')
self.assertEqual(logs[1].state, 'OPERATING')
def test_transition_log_includes_user(self):
"""Test that transition logs include the user who made the change."""
from django_fsm_log.models import StateLog
ride = self._create_ride(status='OPERATING')
ride.transition_to_sbno(user=self.moderator)
ride.save()
ride_ct = ContentType.objects.get_for_model(ride)
log = StateLog.objects.filter(
content_type=ride_ct,
object_id=ride.id
).first()
self.assertEqual(log.by, self.moderator)
def test_post_closing_transition_logged(self):
"""Test that post_closing_status transitions are logged."""
from django_fsm_log.models import StateLog
yesterday = date.today() - timedelta(days=1)
ride = self._create_ride(status='CLOSING')
ride.closing_date = yesterday
ride.post_closing_status = 'DEMOLISHED'
ride.save()
ride.apply_post_closing_status(user=self.moderator)
ride_ct = ContentType.objects.get_for_model(ride)
log = StateLog.objects.filter(
content_type=ride_ct,
object_id=ride.id,
state='DEMOLISHED'
).first()
self.assertIsNotNone(log)
self.assertEqual(log.by, self.moderator)
# ============================================================================
# Ride Model Business Logic Tests
# ============================================================================
class RideBusinessLogicTests(TestCase):
"""Tests for Ride model business logic."""
def setUp(self):
"""Set up test fixtures."""
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park = Park.objects.create(
name='Test Park',
slug='test-park',
description='A test park',
operator=self.operator,
timezone='America/New_York'
)
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def test_ride_creates_with_valid_park(self):
"""Test ride can be created with valid park."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer
)
self.assertEqual(ride.park, self.park)
def test_ride_slug_auto_generated(self):
"""Test that ride slug is auto-generated from name."""
ride = Ride.objects.create(
name='My Amazing Roller Coaster',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer
)
self.assertEqual(ride.slug, 'my-amazing-roller-coaster')
def test_ride_url_generated(self):
"""Test that frontend URL is generated on save."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer
)
self.assertIn('test-park', ride.url)
self.assertIn('test-ride', ride.url)
def test_opening_year_computed_from_opening_date(self):
"""Test that opening_year is computed from opening_date."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer,
opening_date=date(2020, 6, 15)
)
self.assertEqual(ride.opening_year, 2020)
def test_search_text_populated(self):
"""Test that search_text is populated on save."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A thrilling roller coaster',
park=self.park,
manufacturer=self.manufacturer
)
self.assertIn('test ride', ride.search_text)
self.assertIn('thrilling roller coaster', ride.search_text)
self.assertIn('test park', ride.search_text)
self.assertIn('test manufacturer', ride.search_text)
def test_ride_slug_unique_within_park(self):
"""Test that ride slugs are unique within a park."""
Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='First ride',
park=self.park,
manufacturer=self.manufacturer
)
# Creating another ride with same name should get different slug
ride2 = Ride.objects.create(
name='Test Ride',
description='Second ride',
park=self.park,
manufacturer=self.manufacturer
)
self.assertNotEqual(ride2.slug, 'test-ride')
self.assertTrue(ride2.slug.startswith('test-ride'))
# ============================================================================
# Ride Move to Park Tests
# ============================================================================
class RideMoveTests(TestCase):
"""Tests for moving rides between parks."""
def setUp(self):
"""Set up test fixtures."""
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park1 = Park.objects.create(
name='Park One',
slug='park-one',
description='First park',
operator=self.operator,
timezone='America/New_York'
)
self.park2 = Park.objects.create(
name='Park Two',
slug='park-two',
description='Second park',
operator=self.operator,
timezone='America/Los_Angeles'
)
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def test_move_ride_to_different_park(self):
"""Test moving a ride to a different park."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park1,
manufacturer=self.manufacturer
)
changes = ride.move_to_park(self.park2)
ride.refresh_from_db()
self.assertEqual(ride.park, self.park2)
self.assertEqual(changes['old_park']['id'], self.park1.id)
self.assertEqual(changes['new_park']['id'], self.park2.id)
def test_move_ride_updates_url(self):
"""Test that moving a ride updates the URL."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park1,
manufacturer=self.manufacturer
)
old_url = ride.url
changes = ride.move_to_park(self.park2)
ride.refresh_from_db()
self.assertNotEqual(ride.url, old_url)
self.assertIn('park-two', ride.url)
self.assertTrue(changes['url_changed'])
def test_move_ride_handles_slug_conflict(self):
"""Test that moving a ride handles slug conflicts in destination park."""
# Create ride in park1
ride1 = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park1,
manufacturer=self.manufacturer
)
# Create ride with same slug in park2
Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='Another test ride',
park=self.park2,
manufacturer=self.manufacturer
)
# Move ride1 to park2
changes = ride1.move_to_park(self.park2)
ride1.refresh_from_db()
self.assertEqual(ride1.park, self.park2)
# Slug should have been modified to avoid conflict
self.assertNotEqual(ride1.slug, 'test-ride')
self.assertTrue(changes['slug_changed'])
# ============================================================================
# Ride Historical Slug Tests
# ============================================================================
class RideSlugHistoryTests(TestCase):
"""Tests for Ride historical slug tracking."""
def setUp(self):
"""Set up test fixtures."""
self.operator = ParkCompany.objects.create(
name='Test Operator',
description='Test operator company',
roles=['OPERATOR']
)
self.park = Park.objects.create(
name='Test Park',
slug='test-park',
description='A test park',
operator=self.operator,
timezone='America/New_York'
)
self.manufacturer = Company.objects.create(
name='Test Manufacturer',
description='Test manufacturer company',
roles=['MANUFACTURER']
)
def test_get_by_slug_finds_current_slug(self):
"""Test get_by_slug finds ride by current slug."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer
)
found_ride, is_historical = Ride.get_by_slug('test-ride', park=self.park)
self.assertEqual(found_ride, ride)
self.assertFalse(is_historical)
def test_get_by_slug_with_park_filter(self):
"""Test get_by_slug filters by park."""
ride = Ride.objects.create(
name='Test Ride',
slug='test-ride',
description='A test ride',
park=self.park,
manufacturer=self.manufacturer
)
# Should find ride in correct park
found_ride, is_historical = Ride.get_by_slug('test-ride', park=self.park)
self.assertEqual(found_ride, ride)
# Should not find ride in different park
other_park = Park.objects.create(
name='Other Park',
slug='other-park',
description='Another park',
operator=self.operator,
timezone='America/New_York'
)
with self.assertRaises(Ride.DoesNotExist):
Ride.get_by_slug('test-ride', park=other_park)