from django.test import TestCase, Client from django.urls import reverse from django.contrib.auth import get_user_model from common.models import UserConfig, Thematic from projects.models import Project, ProjectTag import json User = get_user_model() class ProjectFiltersPreferencesTest(TestCase): def setUp(self): # Create users self.user = User.objects.create_user(username="testuser", password="password123") self.user_config = UserConfig.objects.create(user=self.user, is_intern=True) # Create thematics self.thematic_a = Thematic.objects.create(code="them_a", name_fr="Thématique A", name_nl="Thema A") self.thematic_b = Thematic.objects.create(code="them_b", name_fr="Thématique B", name_nl="Thema B") # Create projects self.project_a = Project.objects.create( name="Project A", created_by=self.user, status="in_preparation", start_date="2026-06-01", end_date="2026-06-30" ) self.project_a.thematics.add(self.thematic_a) self.project_b = Project.objects.create( name="Project B", created_by=self.user, status="in_progress", start_date="2026-07-01", end_date="2026-07-31" ) self.project_b.thematics.add(self.thematic_b) # Client setup self.client = Client() self.client.login(username="testuser", password="password123") def test_projects_index_view(self): # Ensure view loads and context contains necessary choices response = self.client.get(reverse('projects:projects_index')) self.assertEqual(response.status_code, 200) self.assertIn('thematic_choices', response.context) self.assertIn('selected_thematics', response.context) self.assertIn('saved_sort', response.context) # Check that thematic choices are populated thematics = list(response.context['thematic_choices']) self.assertEqual(len(thematics), 2) def test_projects_geojson_thematic_filter(self): # Without filter, return all (within permissions limit) response = self.client.get(reverse('projects:projects_geojson')) self.assertEqual(response.status_code, 200) data = json.loads(response.content) self.assertEqual(len(data['features']), 2) # Filter by thematic_a response = self.client.get(reverse('projects:projects_geojson'), {'thematic': ['them_a']}) self.assertEqual(response.status_code, 200) data = json.loads(response.content) self.assertEqual(len(data['features']), 1) self.assertEqual(data['features'][0]['id'], self.project_a.id) # Filter by thematic_b response = self.client.get(reverse('projects:projects_geojson'), {'thematic': ['them_b']}) self.assertEqual(response.status_code, 200) data = json.loads(response.content) self.assertEqual(len(data['features']), 1) self.assertEqual(data['features'][0]['id'], self.project_b.id) def test_projects_geojson_date_filter(self): # Date filter should successfully map start_date / end_date response = self.client.get(reverse('projects:projects_geojson'), {'begin_date': '2026-06-15'}) self.assertEqual(response.status_code, 200) data = json.loads(response.content) # Should return Project B since its start_date is 2026-07-01 >= 2026-06-15 (Project A start_date is 2026-06-01 < 2026-06-15) self.assertEqual(len(data['features']), 1) self.assertEqual(data['features'][0]['id'], self.project_b.id) response = self.client.get(reverse('projects:projects_geojson'), {'end_date': '2026-07-15'}) self.assertEqual(response.status_code, 200) data = json.loads(response.content) # Should return Project A since its end_date is 2026-06-30 <= 2026-07-15 (Project B end_date is 2026-07-31 > 2026-07-15) self.assertEqual(len(data['features']), 1) self.assertEqual(data['features'][0]['id'], self.project_a.id) def test_save_preferences_endpoint(self): filters_data = { 'status': ['in_preparation'], 'thematic': ['them_a'], 'begin_date': '2026-06-01' } sort_data = { 'sortName': 'title', 'sortOrder': 'desc' } # Save preferences POST request response = self.client.post( reverse('common:save_project_list_preferences'), data=json.dumps({'filters': filters_data, 'sort': sort_data}), content_type='application/json', HTTP_X_REQUESTED_WITH='XMLHttpRequest' ) self.assertEqual(response.status_code, 200) # Verify db persistence self.user_config.refresh_from_db() self.assertEqual(self.user_config.project_list_filters, filters_data) self.assertEqual(self.user_config.project_list_sort, sort_data) def test_saved_preferences_redirect(self): # Populate saved preferences first filters_data = {'status': ['in_preparation'], 'thematic': ['them_a']} self.user_config.project_list_filters = filters_data self.user_config.save() # Visit index page without GET params response = self.client.get(reverse('projects:projects_index')) # Should redirect to index page with query parameters self.assertEqual(response.status_code, 302) self.assertIn("status=in_preparation", response.url) self.assertIn("thematic=them_a", response.url)