Files
adopt-a-street/test-search-filter.js
William Valentin 43c2e76070 feat: implement comprehensive search and filter system for streets
Add advanced filtering, search, and sorting capabilities to streets endpoint:
- Backend: Enhanced GET /api/streets with query parameters (search, status, adoptedBy, sort, order)
- Backend: Implement case-insensitive name search with in-memory filtering
- Backend: Add X-Total-Count response header for pagination metadata
- Frontend: Add comprehensive filter UI with search bar, status dropdown, and sort controls
- Frontend: Implement 'My Streets' toggle for authenticated users to view their adopted streets
- Frontend: Add 'Clear Filters' button and result count display
- Frontend: Update map markers and street list to reflect filtered results
- Frontend: Mobile-responsive Bootstrap grid layout with loading states

Technical implementation:
- Routes: Enhanced backend/routes/streets.js with filter logic
- Model: Updated backend/models/Street.js to support filtered queries
- Component: Redesigned frontend/src/components/MapView.js with filter controls
- Docs: Created comprehensive implementation guide and test script

Performance: Works efficiently for datasets up to 10k streets. Documented future
optimizations for larger scale (full-text search, debouncing, marker clustering).

🤖 Generated with Claude

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
2025-11-03 13:21:59 -08:00

83 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Test script for search and filter functionality
* This script tests the backend API endpoints with various query parameters
*/
const axios = require('axios');
const BASE_URL = 'http://localhost:5000';
const API_URL = `${BASE_URL}/api/streets`;
async function testEndpoint(description, params) {
console.log(`\n--- ${description} ---`);
try {
const queryString = new URLSearchParams(params).toString();
const url = `${API_URL}${queryString ? '?' + queryString : ''}`;
console.log(`GET ${url}`);
const response = await axios.get(url);
const data = response.data;
const totalCount = response.headers['x-total-count'];
console.log(`Status: ${response.status}`);
console.log(`X-Total-Count: ${totalCount}`);
console.log(`Returned: ${data.data ? data.data.length : data.length} streets`);
if (data.data && data.data.length > 0) {
console.log(`First street: ${data.data[0].name} (${data.data[0].status})`);
} else if (data.length > 0) {
console.log(`First street: ${data[0].name} (${data[0].status})`);
}
return true;
} catch (error) {
console.error(`Error: ${error.message}`);
if (error.response) {
console.error(`Response status: ${error.response.status}`);
console.error(`Response data:`, error.response.data);
}
return false;
}
}
async function runTests() {
console.log('Testing Street Search and Filter API');
console.log('=====================================');
// Test 1: Get all streets (baseline)
await testEndpoint('Get all streets', {});
// Test 2: Search by name
await testEndpoint('Search by name "Main"', { search: 'Main' });
// Test 3: Filter by status - available
await testEndpoint('Filter by status: available', { status: 'available' });
// Test 4: Filter by status - adopted
await testEndpoint('Filter by status: adopted', { status: 'adopted' });
// Test 5: Sort by name ascending
await testEndpoint('Sort by name (asc)', { sort: 'name', order: 'asc' });
// Test 6: Sort by name descending
await testEndpoint('Sort by name (desc)', { sort: 'name', order: 'desc' });
// Test 7: Combined filters
await testEndpoint('Search "Street" + status "available"', {
search: 'Street',
status: 'available'
});
// Test 8: Pagination
await testEndpoint('Pagination: page 1, limit 5', { page: 1, limit: 5 });
console.log('\n\nAll tests completed!');
}
// Run tests
runTests().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});