mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 09:31:09 -05:00
- Implemented extensive test cases for the Parks API, covering endpoints for listing, retrieving, creating, updating, and deleting parks. - Added tests for filtering, searching, and ordering parks in the API. - Created tests for error handling in the API, including malformed JSON and unsupported methods. - Developed model tests for Park, ParkArea, Company, and ParkReview models, ensuring validation and constraints are enforced. - Introduced utility mixins for API and model testing to streamline assertions and enhance test readability. - Included integration tests to validate complete workflows involving park creation, retrieval, updating, and deletion.
245 lines
9.6 KiB
Python
245 lines
9.6 KiB
Python
"""
|
|
Test cases for Parks models following Django styleguide patterns.
|
|
Uses proper naming conventions and comprehensive coverage.
|
|
"""
|
|
|
|
from decimal import Decimal
|
|
from datetime import date, timedelta
|
|
from django.test import TestCase
|
|
from django.core.exceptions import ValidationError
|
|
from django.db import IntegrityError
|
|
from django.utils import timezone
|
|
|
|
from parks.models import Park, ParkArea, Company, ParkReview
|
|
from accounts.models import User
|
|
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']
|
|
rides = 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)
|