mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 23:51:09 -05:00
Implement park search suggestions with HTMX integration: replace legacy redirect with real-time suggestions and enhance UI for better user experience
This commit is contained in:
@@ -5,6 +5,7 @@ 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):
|
||||
@@ -13,11 +14,11 @@ class TestParkSearch:
|
||||
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:park_list')
|
||||
response = client.get(url, {'park': 'Test'})
|
||||
|
||||
url = reverse('parks:suggest_parks')
|
||||
response = client.get(url, {'search': 'Test'})
|
||||
|
||||
# Check response
|
||||
assert response.status_code == 200
|
||||
content = response.content.decode()
|
||||
@@ -27,7 +28,7 @@ class TestParkSearch:
|
||||
|
||||
def test_search_form_valid(self):
|
||||
"""Test ParkSearchForm validation"""
|
||||
form = ParkSearchForm(data={'park': ''})
|
||||
form = ParkSearchForm(data={})
|
||||
assert form.is_valid()
|
||||
|
||||
def test_autocomplete_class(self):
|
||||
@@ -39,14 +40,14 @@ class TestParkSearch:
|
||||
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()
|
||||
|
||||
@@ -54,10 +55,10 @@ class TestParkSearch:
|
||||
"""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
|
||||
@@ -67,10 +68,10 @@ class TestParkSearch:
|
||||
"""Test partial matching in search"""
|
||||
Park.objects.create(name="Adventure World")
|
||||
Park.objects.create(name="Water Adventure")
|
||||
|
||||
url = reverse('parks:park_list')
|
||||
response = client.get(url, {'park': 'Adv'})
|
||||
|
||||
|
||||
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
|
||||
@@ -79,41 +80,49 @@ class TestParkSearch:
|
||||
def test_htmx_request_handling(self, client: Client):
|
||||
"""Test HTMX-specific request handling"""
|
||||
Park.objects.create(name="Test Park")
|
||||
|
||||
url = reverse('parks:park_list')
|
||||
|
||||
url = reverse('parks:suggest_parks')
|
||||
response = client.get(
|
||||
url,
|
||||
{'park': 'Test'},
|
||||
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_unauthenticated_access(self, client: Client):
|
||||
"""Test that unauthorized users can access search but not autocomplete"""
|
||||
park = Park.objects.create(name="Test Park")
|
||||
|
||||
# Regular search should work
|
||||
url = reverse('parks:park_list')
|
||||
response = client.get(url, {'park_name': 'Test'})
|
||||
assert response.status_code == 200
|
||||
assert "Test Park" in response.content.decode()
|
||||
|
||||
# Autocomplete should require authentication
|
||||
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'})
|
||||
assert response.status_code == 302 # Redirects to login
|
||||
|
||||
content = response.content.decode()
|
||||
result_count = content.count('Test Park')
|
||||
assert result_count == 8 # Verify limit is enforced
|
||||
|
||||
def test_search_debounce(self, client: Client):
|
||||
"""Test that search has proper headers for debouncing"""
|
||||
Park.objects.create(name="Test Park")
|
||||
|
||||
url = reverse('parks:suggest_parks')
|
||||
response = client.get(url, {'search': 'Test'})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'HX-Trigger' in response
|
||||
|
||||
Reference in New Issue
Block a user