import pytest from django.urls import reverse from django.test import Client from parks.models import Park from parks.forms import ParkAutocomplete, ParkSearchForm @pytest.mark.django_db class TestParkSearch: def test_autocomplete_results(self, client: Client): """Test that autocomplete returns correct results""" # Create test parks park1 = Park.objects.create(name="Test Park") park2 = Park.objects.create(name="Another Park") park3 = Park.objects.create(name="Test Garden") # Get autocomplete results url = reverse('parks:suggest_parks') response = client.get(url, {'search': 'Test'}) # Check response assert response.status_code == 200 content = response.content.decode() assert park1.name in content assert park3.name in content assert park2.name not in content def test_search_form_valid(self): """Test ParkSearchForm validation""" form = ParkSearchForm(data={}) assert form.is_valid() def test_autocomplete_class(self): """Test ParkAutocomplete configuration""" ac = ParkAutocomplete() assert ac.model == Park assert 'name' in ac.search_attrs def test_search_with_filters(self, client: Client): """Test search works with filters""" park = Park.objects.create(name="Test Park", status="OPERATING") # Search with status filter url = reverse('parks:park_list') response = client.get(url, { 'park': str(park.pk), 'status': 'OPERATING' }) assert response.status_code == 200 assert park.name in response.content.decode() def test_empty_search(self, client: Client): """Test empty search returns all parks""" Park.objects.create(name="Test Park") Park.objects.create(name="Another Park") url = reverse('parks:park_list') response = client.get(url) assert response.status_code == 200 content = response.content.decode() assert "Test Park" in content assert "Another Park" in content def test_partial_match_search(self, client: Client): """Test partial matching in search""" Park.objects.create(name="Adventure World") Park.objects.create(name="Water Adventure") url = reverse('parks:suggest_parks') response = client.get(url, {'search': 'Adv'}) assert response.status_code == 200 content = response.content.decode() assert "Adventure World" in content assert "Water Adventure" in content def test_htmx_request_handling(self, client: Client): """Test HTMX-specific request handling""" Park.objects.create(name="Test Park") url = reverse('parks:suggest_parks') response = client.get( url, {'search': 'Test'}, HTTP_HX_REQUEST='true' ) assert response.status_code == 200 assert "Test Park" in response.content.decode() def test_view_mode_persistence(self, client: Client): """Test view mode is maintained during search""" Park.objects.create(name="Test Park") url = reverse('parks:park_list') response = client.get(url, { 'park': 'Test', 'view_mode': 'list' }) assert response.status_code == 200 assert 'data-view-mode="list"' in response.content.decode() def test_suggestion_limit(self, client: Client): """Test that suggestions are limited to 8 items""" # Create 10 parks for i in range(10): Park.objects.create(name=f"Test Park {i}") url = reverse('parks:suggest_parks') response = client.get(url, {'search': 'Test'}) content = response.content.decode() result_count = content.count('Test Park') assert result_count == 8 # Verify limit is enforced def test_search_json_format(self, client: Client): """Test that search returns properly formatted JSON""" park = Park.objects.create( name="Test Park", status="OPERATING", city="Test City", state="Test State" ) url = reverse('parks:suggest_parks') response = client.get(url, {'search': 'Test'}) assert response.status_code == 200 data = response.json() assert 'results' in data assert len(data['results']) == 1 result = data['results'][0] assert result['id'] == str(park.pk) assert result['name'] == "Test Park" assert result['status'] == "Operating" assert result['location'] == park.formatted_location assert result['url'] == reverse('parks:park_detail', kwargs={'slug': park.slug}) def test_empty_search_json(self, client: Client): """Test empty search returns empty results array""" url = reverse('parks:suggest_parks') response = client.get(url, {'search': ''}) assert response.status_code == 200 data = response.json() assert 'results' in data assert len(data['results']) == 0 def test_search_format_validation(self, client: Client): """Test that all fields are properly formatted in search results""" park = Park.objects.create( name="Test Park", status="OPERATING", city="Test City", state="Test State", country="Test Country" ) expected_fields = {'id', 'name', 'status', 'location', 'url'} url = reverse('parks:suggest_parks') response = client.get(url, {'search': 'Test'}) data = response.json() result = data['results'][0] # Check all expected fields are present assert set(result.keys()) == expected_fields # Check field types assert isinstance(result['id'], str) assert isinstance(result['name'], str) assert isinstance(result['status'], str) assert isinstance(result['location'], str) assert isinstance(result['url'], str) # Check formatted location includes city and state assert 'Test City' in result['location'] assert 'Test State' in result['location']