from django.test import TestCase, RequestFactory, override_settings from django.contrib.auth import get_user_model from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied from search.mixins import RideAutocomplete from rides.models import Ride from parks.models import Park from operators.models import Operator User = get_user_model() class RideAutocompleteTest(TestCase): """Test cases for RideAutocomplete functionality.""" def setUp(self): """Set up test data.""" self.factory = RequestFactory() self.user = User.objects.create_user( username='testuser', password='testpass123' ) # Create test operator and park self.operator = Operator.objects.create( name='Test Operator' ) self.park = Park.objects.create( name='Test Park', operator=self.operator, status='OPERATING' ) # Create test rides self.ride1 = Ride.objects.create( name='Thunder Mountain', park=self.park, category='RC', status='OPERATING' ) self.ride2 = Ride.objects.create( name='Space Mountain', park=self.park, category='RC', status='OPERATING' ) self.ride3 = Ride.objects.create( name='Pirates Adventure', park=self.park, category='DR', status='OPERATING' ) @override_settings(AUTOCOMPLETE_BLOCK_UNAUTHENTICATED=True) def test_autocomplete_requires_authentication(self): """Test that autocomplete requires authentication.""" request = self.factory.get('/search/rides/autocomplete/?q=mountain') request.user = AnonymousUser() autocomplete = RideAutocomplete() with self.assertRaises(PermissionDenied): autocomplete.auth_check(request) def test_autocomplete_allows_authenticated_users(self): """Test that autocomplete allows authenticated users.""" request = self.factory.get('/search/rides/autocomplete/?q=mountain') request.user = self.user autocomplete = RideAutocomplete() # Should not raise an exception autocomplete.auth_check(request) def test_search_results_filtering(self): """Test that search results are properly filtered.""" autocomplete = RideAutocomplete() # Search for "mountain" should return both mountain rides results = autocomplete.get_search_results('mountain', {}) self.assertEqual(results.count(), 2) # Search for "space" should return only Space Mountain results = autocomplete.get_search_results('space', {}) self.assertEqual(results.count(), 1) self.assertEqual(results.first().name, 'Space Mountain') # Search for "pirates" should return Pirates Adventure results = autocomplete.get_search_results('pirates', {}) self.assertEqual(results.count(), 1) self.assertEqual(results.first().name, 'Pirates Adventure') def test_search_results_include_park_data(self): """Test that search results include related park data.""" autocomplete = RideAutocomplete() results = autocomplete.get_search_results('mountain', {}) # Verify park data is accessible (select_related working) for ride in results: self.assertEqual(ride.park.name, 'Test Park') def test_search_results_limited_to_ten(self): """Test that search results are limited to 10 items.""" # Create 15 rides with similar names for i in range(15): Ride.objects.create( name=f'Test Coaster {i}', park=self.park, category='RC', status='OPERATING' ) autocomplete = RideAutocomplete() results = autocomplete.get_search_results('test', {}) # Should be limited to 10 results self.assertEqual(results.count(), 10) def test_format_result(self): """Test that results are properly formatted.""" autocomplete = RideAutocomplete() formatted = autocomplete.format_result(self.ride1) self.assertEqual(formatted['key'], str(self.ride1.pk)) self.assertEqual(formatted['label'], 'Thunder Mountain') self.assertEqual(formatted['extra'], 'at Test Park') def test_case_insensitive_search(self): """Test that search is case insensitive.""" autocomplete = RideAutocomplete() # Test different cases results_lower = autocomplete.get_search_results('thunder', {}) results_upper = autocomplete.get_search_results('THUNDER', {}) results_mixed = autocomplete.get_search_results('Thunder', {}) self.assertEqual(results_lower.count(), 1) self.assertEqual(results_upper.count(), 1) self.assertEqual(results_mixed.count(), 1)