""" Root pytest configuration for ThrillWiki backend tests. This file contains shared fixtures and configuration used across all test modules (unit, integration, e2e). """ import os import django import pytest from django.conf import settings # Configure Django settings before any tests run os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.django.test") django.setup() # ============================================================================= # Database Fixtures # ============================================================================= # Note: pytest-django uses the DATABASES setting from the test settings module # (config.django.test). Do NOT override DATABASES to SQLite here as it breaks # GeoDjango models that require PostGIS (or properly configured SpatiaLite). @pytest.fixture def db_session(db): """Provide database access with automatic cleanup.""" yield db # ============================================================================= # User Fixtures # ============================================================================= @pytest.fixture def user(db): """Create a regular test user.""" from tests.factories import UserFactory return UserFactory() @pytest.fixture def staff_user(db): """Create a staff test user.""" from tests.factories import StaffUserFactory return StaffUserFactory() @pytest.fixture def superuser(db): """Create a superuser test user.""" from tests.factories import SuperUserFactory return SuperUserFactory() @pytest.fixture def moderator_user(db): """Create a moderator test user.""" from tests.factories import StaffUserFactory user = StaffUserFactory(username="moderator") return user # ============================================================================= # API Client Fixtures # ============================================================================= @pytest.fixture def api_client(): """Create an unauthenticated API client.""" from rest_framework.test import APIClient return APIClient() @pytest.fixture def authenticated_api_client(api_client, user): """Create an authenticated API client.""" api_client.force_authenticate(user=user) return api_client @pytest.fixture def staff_api_client(api_client, staff_user): """Create an API client authenticated as staff.""" api_client.force_authenticate(user=staff_user) return api_client @pytest.fixture def superuser_api_client(api_client, superuser): """Create an API client authenticated as superuser.""" api_client.force_authenticate(user=superuser) return api_client # ============================================================================= # Model Fixtures # ============================================================================= @pytest.fixture def park(db): """Create a test park.""" from tests.factories import ParkFactory return ParkFactory() @pytest.fixture def operating_park(db): """Create an operating test park.""" from tests.factories import ParkFactory return ParkFactory(status="OPERATING") @pytest.fixture def ride(db, park): """Create a test ride.""" from tests.factories import RideFactory return RideFactory(park=park) @pytest.fixture def operating_ride(db, operating_park): """Create an operating test ride.""" from tests.factories import RideFactory return RideFactory(park=operating_park, status="OPERATING") @pytest.fixture def park_photo(db, park, user): """Create a test park photo.""" from tests.factories import ParkPhotoFactory return ParkPhotoFactory(park=park, uploaded_by=user) @pytest.fixture def ride_photo(db, ride, user): """Create a test ride photo.""" from tests.factories import RidePhotoFactory return RidePhotoFactory(ride=ride, uploaded_by=user) @pytest.fixture def company(db): """Create a test company.""" from tests.factories import CompanyFactory return CompanyFactory() @pytest.fixture def park_area(db, park): """Create a test park area.""" from tests.factories import ParkAreaFactory return ParkAreaFactory(park=park) # ============================================================================= # Request Fixtures # ============================================================================= @pytest.fixture def request_factory(): """Create a Django request factory.""" from django.test import RequestFactory return RequestFactory() @pytest.fixture def rf(): """Alias for request_factory (common pytest-django convention).""" from django.test import RequestFactory return RequestFactory() # ============================================================================= # Utility Fixtures # ============================================================================= @pytest.fixture def mock_cloudflare_image(): """Create a mock Cloudflare image.""" from tests.factories import CloudflareImageFactory return CloudflareImageFactory() @pytest.fixture def temp_image(): """Create a temporary image file for upload testing.""" from io import BytesIO from django.core.files.uploadedfile import SimpleUploadedFile from PIL import Image # Create a simple test image image = Image.new("RGB", (100, 100), color="red") image_io = BytesIO() image.save(image_io, format="JPEG") image_io.seek(0) return SimpleUploadedFile( name="test_image.jpg", content=image_io.read(), content_type="image/jpeg", ) @pytest.fixture(autouse=True) def enable_db_access_for_all_tests(db): """ Enable database access for all tests by default. This is useful for integration tests that need database access without explicitly requesting the 'db' fixture. """ pass # ============================================================================= # Cleanup Fixtures # ============================================================================= @pytest.fixture(autouse=True) def clear_cache(): """Clear Django cache before each test.""" from django.core.cache import cache cache.clear() yield cache.clear() # ============================================================================= # Marker Registration # ============================================================================= def pytest_configure(config): """Register custom pytest markers.""" config.addinivalue_line("markers", "unit: Unit tests (fast, isolated)") config.addinivalue_line( "markers", "integration: Integration tests (may use database)" ) config.addinivalue_line( "markers", "e2e: End-to-end browser tests (slow, requires server)" ) config.addinivalue_line("markers", "slow: Tests that take a long time to run") config.addinivalue_line("markers", "api: API endpoint tests")