""" 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 # 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")