mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 11:31:07 -05:00
- Add complete backend/ directory with full Django application - Add frontend/ directory with Vite + TypeScript setup ready for Next.js - Add comprehensive shared/ directory with: - Complete documentation and memory-bank archives - Media files and avatars (letters, park/ride images) - Deployment scripts and automation tools - Shared types and utilities - Add architecture/ directory with migration guides - Configure pnpm workspace for monorepo development - Update .gitignore to exclude .django_tailwind_cli/ build artifacts - Preserve all historical documentation in shared/docs/memory-bank/ - Set up proper structure for full-stack development with shared resources
250 lines
9.2 KiB
Python
250 lines
9.2 KiB
Python
"""
|
|
Test cases for Parks models following Django styleguide patterns.
|
|
Uses proper naming conventions and comprehensive coverage.
|
|
"""
|
|
|
|
from datetime import date, timedelta
|
|
from django.test import TestCase
|
|
from django.db import IntegrityError
|
|
from django.utils import timezone
|
|
|
|
from apps.parks.models import Park, Company
|
|
from tests.factories import (
|
|
UserFactory,
|
|
CompanyFactory,
|
|
ParkFactory,
|
|
ParkAreaFactory,
|
|
ParkReviewFactory,
|
|
TestScenarios,
|
|
)
|
|
|
|
|
|
class TestParkModel(TestCase):
|
|
"""Test cases for the Park model."""
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.company = CompanyFactory(roles=["OPERATOR"])
|
|
self.user = UserFactory()
|
|
|
|
def test__park_creation__with_valid_data__succeeds(self):
|
|
"""Test that park can be created with valid data."""
|
|
park = ParkFactory(operator=self.company)
|
|
|
|
self.assertIsInstance(park.id, int)
|
|
self.assertEqual(park.operator, self.company)
|
|
self.assertEqual(park.status, "OPERATING")
|
|
self.assertIsNotNone(park.created_at)
|
|
|
|
def test__park_str_representation__returns_park_name(self):
|
|
"""Test that park string representation returns the name."""
|
|
park = ParkFactory(name="Test Park", operator=self.company)
|
|
|
|
self.assertEqual(str(park), "Test Park")
|
|
|
|
def test__park_slug__is_automatically_generated(self):
|
|
"""Test that park slug is generated from name."""
|
|
park = ParkFactory(name="Amazing Theme Park", operator=self.company)
|
|
|
|
self.assertEqual(park.slug, "amazing-theme-park")
|
|
|
|
def test__park_constraints__closing_date_after_opening__is_enforced(self):
|
|
"""Test that closing date must be after opening date."""
|
|
with self.assertRaises(IntegrityError):
|
|
ParkFactory(
|
|
operator=self.company,
|
|
opening_date=date(2020, 6, 1),
|
|
closing_date=date(2020, 5, 1), # Before opening
|
|
)
|
|
|
|
def test__park_constraints__positive_size__is_enforced(self):
|
|
"""Test that park size must be positive."""
|
|
with self.assertRaises(IntegrityError):
|
|
ParkFactory(operator=self.company, size_acres=-10)
|
|
|
|
def test__park_constraints__rating_range__is_enforced(self):
|
|
"""Test that rating must be within valid range."""
|
|
# Test upper bound
|
|
with self.assertRaises(IntegrityError):
|
|
ParkFactory(operator=self.company, average_rating=11)
|
|
|
|
# Test lower bound
|
|
with self.assertRaises(IntegrityError):
|
|
ParkFactory(operator=self.company, average_rating=0)
|
|
|
|
def test__park_constraints__coaster_count_lte_ride_count__is_enforced(
|
|
self,
|
|
):
|
|
"""Test that coaster count cannot exceed ride count."""
|
|
with self.assertRaises(IntegrityError):
|
|
ParkFactory(
|
|
operator=self.company,
|
|
ride_count=5,
|
|
coaster_count=10, # More coasters than total rides
|
|
)
|
|
|
|
def test__park_relationships__operator_is_required(self):
|
|
"""Test that park must have an operator."""
|
|
with self.assertRaises(IntegrityError):
|
|
Park.objects.create(
|
|
name="Test Park",
|
|
slug="test-park",
|
|
# Missing operator
|
|
)
|
|
|
|
def test__park_relationships__property_owner_is_optional(self):
|
|
"""Test that property owner is optional."""
|
|
park = ParkFactory(operator=self.company, property_owner=None)
|
|
|
|
self.assertIsNone(park.property_owner)
|
|
self.assertEqual(park.operator, self.company)
|
|
|
|
|
|
class TestParkModelManagers(TestCase):
|
|
"""Test cases for Park model custom managers."""
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.company = CompanyFactory(roles=["OPERATOR"])
|
|
self.operating_park = ParkFactory(operator=self.company, status="OPERATING")
|
|
self.closed_park = ParkFactory(operator=self.company, status="CLOSED_TEMP")
|
|
|
|
def test__park_manager__operating_filter__returns_only_operating_parks(
|
|
self,
|
|
):
|
|
"""Test that operating() filter returns only operating parks."""
|
|
operating_parks = Park.objects.operating()
|
|
|
|
self.assertEqual(operating_parks.count(), 1)
|
|
self.assertEqual(operating_parks.first(), self.operating_park)
|
|
|
|
def test__park_manager__closed_filter__returns_only_closed_parks(self):
|
|
"""Test that closed() filter returns only closed parks."""
|
|
closed_parks = Park.objects.closed()
|
|
|
|
self.assertEqual(closed_parks.count(), 1)
|
|
self.assertEqual(closed_parks.first(), self.closed_park)
|
|
|
|
def test__park_manager__optimized_for_list__includes_stats(self):
|
|
"""Test that optimized_for_list includes statistical annotations."""
|
|
parks = Park.objects.optimized_for_list()
|
|
park = parks.first()
|
|
|
|
# Check that statistical fields are available
|
|
self.assertTrue(hasattr(park, "ride_count_calculated"))
|
|
self.assertTrue(hasattr(park, "coaster_count_calculated"))
|
|
self.assertTrue(hasattr(park, "area_count"))
|
|
|
|
|
|
class TestParkAreaModel(TestCase):
|
|
"""Test cases for the ParkArea model."""
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.company = CompanyFactory(roles=["OPERATOR"])
|
|
self.park = ParkFactory(operator=self.company)
|
|
|
|
def test__park_area_creation__with_valid_data__succeeds(self):
|
|
"""Test that park area can be created with valid data."""
|
|
area = ParkAreaFactory(park=self.park)
|
|
|
|
self.assertIsInstance(area.id, int)
|
|
self.assertEqual(area.park, self.park)
|
|
self.assertIsNotNone(area.created_at)
|
|
|
|
def test__park_area_unique_constraint__park_and_slug__is_enforced(self):
|
|
"""Test that park+slug combination must be unique."""
|
|
ParkAreaFactory(park=self.park, slug="test-area")
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
ParkAreaFactory(park=self.park, slug="test-area") # Duplicate
|
|
|
|
|
|
class TestCompanyModel(TestCase):
|
|
"""Test cases for the Company model."""
|
|
|
|
def test__company_creation__with_valid_data__succeeds(self):
|
|
"""Test that company can be created with valid data."""
|
|
company = CompanyFactory()
|
|
|
|
self.assertIsInstance(company.id, int)
|
|
self.assertIsInstance(company.roles, list)
|
|
self.assertIsNotNone(company.created_at)
|
|
|
|
def test__company_manager__operators_filter__returns_only_operators(self):
|
|
"""Test that operators() filter works correctly."""
|
|
operator = CompanyFactory(roles=["OPERATOR"])
|
|
manufacturer = CompanyFactory(roles=["MANUFACTURER"])
|
|
|
|
operators = Company.objects.operators()
|
|
|
|
self.assertIn(operator, operators)
|
|
self.assertNotIn(manufacturer, operators)
|
|
|
|
|
|
class TestParkReviewModel(TestCase):
|
|
"""Test cases for the ParkReview model."""
|
|
|
|
def setUp(self):
|
|
"""Set up test data."""
|
|
self.company = CompanyFactory(roles=["OPERATOR"])
|
|
self.park = ParkFactory(operator=self.company)
|
|
self.user = UserFactory()
|
|
|
|
def test__park_review_creation__with_valid_data__succeeds(self):
|
|
"""Test that park review can be created with valid data."""
|
|
review = ParkReviewFactory(park=self.park, user=self.user)
|
|
|
|
self.assertIsInstance(review.id, int)
|
|
self.assertEqual(review.park, self.park)
|
|
self.assertEqual(review.user, self.user)
|
|
self.assertTrue(1 <= review.rating <= 10)
|
|
|
|
def test__park_review_constraints__rating_range__is_enforced(self):
|
|
"""Test that review rating must be within valid range."""
|
|
with self.assertRaises(IntegrityError):
|
|
ParkReviewFactory(park=self.park, user=self.user, rating=11)
|
|
|
|
def test__park_review_constraints__visit_date_not_future__is_enforced(
|
|
self,
|
|
):
|
|
"""Test that visit date cannot be in the future."""
|
|
future_date = timezone.now().date() + timedelta(days=1)
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
ParkReviewFactory(park=self.park, user=self.user, visit_date=future_date)
|
|
|
|
def test__park_review_unique_constraint__park_and_user__is_enforced(self):
|
|
"""Test that user can only review each park once."""
|
|
ParkReviewFactory(park=self.park, user=self.user)
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
ParkReviewFactory(park=self.park, user=self.user) # Duplicate
|
|
|
|
|
|
class TestParkModelIntegration(TestCase):
|
|
"""Integration tests for Park model with related models."""
|
|
|
|
def test__complete_park_scenario__with_all_relationships__works_correctly(
|
|
self,
|
|
):
|
|
"""Test complete park creation with all relationships."""
|
|
scenario = TestScenarios.complete_park_with_rides(num_rides=3)
|
|
|
|
park = scenario["park"]
|
|
scenario["rides"]
|
|
areas = scenario["areas"]
|
|
reviews = scenario["reviews"]
|
|
|
|
# Verify all relationships are properly created
|
|
self.assertEqual(park.rides.count(), 3)
|
|
self.assertEqual(park.areas.count(), len(areas))
|
|
self.assertEqual(park.reviews.filter(is_published=True).count(), len(reviews))
|
|
|
|
# Test that park statistics are calculated correctly
|
|
parks_with_stats = Park.objects.with_complete_stats()
|
|
park_with_stats = parks_with_stats.get(id=park.id)
|
|
|
|
self.assertEqual(park_with_stats.ride_count_calculated, 3)
|
|
self.assertIsNotNone(park_with_stats.average_rating_calculated)
|