mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 11:11:10 -05:00
184 lines
6.2 KiB
Python
184 lines
6.2 KiB
Python
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']
|