from django.test import TestCase, override_settings from django.urls import reverse, resolve from rest_framework.test import APITestCase from rest_framework import status from django.test.utils import override_settings class HadisAPIConnectivityTests(APITestCase): """ Test suite for hadis app API endpoints connectivity. Tests that all endpoints return proper HTTP responses. """ # Comment out fixtures for now to avoid migration issues # fixtures = [ # 'backend/apps/hadis/fixtures/new_categories.json', # 'backend/apps/hadis/fixtures/hadises1_reformatted.json', # 'backend/apps/hadis/fixtures/transmitters_reformatted.json', # ] def test_collections_endpoint(self): """Test collections endpoint returns 200""" url = reverse('hadis-collection-list') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_sync_sects_endpoint(self): """Test sync sects endpoint returns 200""" url = reverse('hadis-sect-list') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_sync_categories_tree_endpoint(self): """Test sync categories tree endpoint returns 200""" url = reverse('hadis-category-tree') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_sync_hadis_endpoint(self): """Test sync hadis endpoint returns 200""" url = reverse('hadis-sync') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_sync_narrators_endpoint(self): """Test sync narrators endpoint returns 200""" url = reverse('transmitter-sync') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_sync_references_endpoint(self): """Test sync references endpoint returns 200""" url = reverse('reference-sync') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_info_endpoint(self): """Test info endpoint returns 200""" url = reverse('hadis-info') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_categories_tree_normal_endpoint(self): """Test categories tree normal endpoint returns 200""" url = reverse('hadis-category-tree-normal') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_categories_endpoint(self): """Test categories endpoint returns 200""" url = reverse('categories') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_categories_by_sect_endpoint(self): """Test categories by sect endpoint is accessible""" # Using a common sect type url = reverse('categories-by-sect', kwargs={'sect_type': '1'}) response = self.client.get(url) # May return 200 if data exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_categories_by_sect_with_slug_endpoint(self): """Test categories by sect with slug endpoint is accessible""" # Using common parameters url = reverse('categories-tree-by-sect', kwargs={ 'sect_type': '1', 'slug': 'test-category' }) response = self.client.get(url) # May return 200 if data exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_categories_by_sect_source_endpoint(self): """Test categories by sect source endpoint is accessible""" # Using common parameters url = reverse('categories-tree-by-sect-source', kwargs={ 'sect_type': '1', 'slug': 'test-category', 'source_type': 'quran' }) response = self.client.get(url) # May return 200 if data exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_hadis_main_list_endpoint(self): """Test hadis main list (arguments) endpoint returns 200""" url = reverse('hadis-main-list') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_hadis_filters_endpoint(self): """Test hadis filters endpoint returns 200""" url = reverse('hadis-filters') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_narrators_endpoint(self): """Test narrators endpoint returns 200""" url = reverse('narrators') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_narrator_filters_endpoint(self): """Test narrator filters endpoint returns 200""" url = reverse('narrator-filters') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_narrator_detail_endpoint(self): """Test narrator detail endpoint is accessible""" # Using a test narrator slug url = reverse('narrator-detail', kwargs={'narrator_slug': 'test-narrator'}) response = self.client.get(url) # May return 200 if narrator exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_narrator_opinions_endpoint(self): """Test narrator opinions endpoint is accessible""" # Using a test narrator slug url = reverse('narrator-opinions', kwargs={'narrator_slug': 'test-narrator'}) response = self.client.get(url) # May return 200 if narrator exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_narrator_original_texts_endpoint(self): """Test narrator original texts endpoint is accessible""" # Using a test narrator slug url = reverse('narrator-original-texts', kwargs={'narrator_slug': 'test-narrator'}) response = self.client.get(url) # May return 200 if narrator exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_references_endpoint(self): """Test references endpoint returns 200""" url = reverse('references') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_category_hadis_list_endpoint(self): """Test category hadis list endpoint is accessible""" # Using a test category slug url = reverse('hadis-list', kwargs={'category_slug': 'test-category'}) response = self.client.get(url) # May return 200 if category exists, or 404 if not - but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) # Parameterized endpoints that may not have data - these might return 404 but should still be accessible def test_reference_detail_endpoint(self): """Test reference detail endpoint is accessible (may return 404 if no data)""" url = reverse('reference-detail', kwargs={'reference_slug': 'test-reference'}) response = self.client.get(url) # This might return 404 if reference doesn't exist, but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_hadis_basic_endpoint(self): """Test hadis basic endpoint is accessible (may return 404 if no data)""" url = reverse('hadis-basic', kwargs={'hadis_slug': 'test-hadis'}) response = self.client.get(url) # This might return 404 if hadis doesn't exist, but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_hadis_detail_endpoint(self): """Test hadis detail endpoint is accessible (may return 404 if no data)""" url = reverse('hadis-detail', kwargs={'hadis_slug': 'test-hadis'}) response = self.client.get(url) # This might return 404 if hadis doesn't exist, but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_hadis_transmitters_endpoint(self): """Test hadis transmitters endpoint is accessible (may return 404 if no data)""" url = reverse('hadis-transmitters', kwargs={'hadis_slug': 'test-hadis'}) response = self.client.get(url) # This might return 404 if hadis doesn't exist, but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) def test_hadis_corrections_endpoint(self): """Test hadis corrections endpoint is accessible (may return 404 if no data)""" url = reverse('hadis-corrections', kwargs={'hadis_slug': 'test-hadis'}) response = self.client.get(url) # This might return 404 if hadis doesn't exist, but endpoint should be accessible self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]) class HadisAPIResponseStructureTests(APITestCase): """ Additional tests to ensure API responses have proper structure """ # Comment out fixtures for now to avoid migration issues # fixtures = [ # 'backend/apps/hadis/fixtures/new_categories.json', # 'backend/apps/hadis/fixtures/hadises1_reformatted.json', # 'backend/apps/hadis/fixtures/transmitters_reformatted.json', # ] def test_api_returns_json_content_type(self): """Test that API endpoints return JSON content type""" endpoints = [ reverse('hadis-collection-list'), reverse('hadis-info'), reverse('categories'), reverse('hadis-main-list'), reverse('narrators'), ] for url in endpoints: with self.subTest(url=url): response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response['Content-Type'], 'application/json') def test_api_endpoints_are_cached(self): """Test that API endpoints have cache headers (from cached_view decorator)""" url = reverse('hadis-info') response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) # Check if cache headers are present (this indicates caching is working) cache_headers = ['Cache-Control', 'Expires', 'ETag'] has_cache_header = any(header in response for header in cache_headers) self.assertTrue(has_cache_header, "API endpoint should have cache headers") class HadisURLResolutionTests(TestCase): """ Test that all hadis URLs are properly configured and resolvable. These tests don't require database access. """ def test_all_url_names_are_resolvable(self): """Test that all URL names can be reversed without parameters""" url_names = [ 'hadis-collection-list', 'hadis-sect-list', 'hadis-category-tree', 'hadis-sync', 'transmitter-sync', 'reference-sync', 'hadis-info', 'hadis-category-tree-normal', 'categories', 'hadis-main-list', 'hadis-filters', 'narrator-filters', 'narrators', 'references', ] for url_name in url_names: with self.subTest(url_name=url_name): try: url = reverse(url_name) # If we get here, the URL is resolvable self.assertIsInstance(url, str) self.assertTrue(url.startswith('/')) except Exception as e: self.fail(f"URL name '{url_name}' could not be reversed: {e}") def test_parameterized_url_names_are_resolvable(self): """Test that parameterized URL names can be reversed with test parameters""" parameterized_urls = [ ('categories-by-sect', {'sect_type': '1'}), ('categories-tree-by-sect', {'sect_type': '1', 'slug': 'test'}), ('categories-tree-by-sect-source', {'sect_type': '1', 'slug': 'test', 'source_type': 'quran'}), ('hadis-list', {'category_slug': 'test'}), ('narrator-detail', {'narrator_slug': 'test'}), ('narrator-opinions', {'narrator_slug': 'test'}), ('narrator-original-texts', {'narrator_slug': 'test'}), ('reference-detail', {'reference_slug': 'test'}), ('hadis-basic', {'hadis_slug': 'test'}), ('hadis-detail', {'hadis_slug': 'test'}), ('hadis-transmitters', {'hadis_slug': 'test'}), ('hadis-corrections', {'hadis_slug': 'test'}), ] for url_name, kwargs in parameterized_urls: with self.subTest(url_name=url_name): try: url = reverse(url_name, kwargs=kwargs) # If we get here, the URL is resolvable self.assertIsInstance(url, str) self.assertTrue(url.startswith('/')) except Exception as e: self.fail(f"URL name '{url_name}' could not be reversed with kwargs {kwargs}: {e}") def test_urls_resolve_to_correct_views(self): """Test that URLs resolve to the correct view functions/classes""" test_urls = [ ('/hadis/collections/', 'hadis-collection-list'), ('/hadis/sync/sects/', 'hadis-sect-list'), ('/hadis/sync/categories/tree/', 'hadis-category-tree'), ('/hadis/sync/hadis/', 'hadis-sync'), ('/hadis/sync/narrators/', 'transmitter-sync'), ('/hadis/sync/references/', 'reference-sync'), ('/hadis/info/', 'hadis-info'), ('/hadis/categories/tree/', 'hadis-category-tree-normal'), ('/hadis/categories/', 'categories'), ('/hadis/arguments/', 'hadis-main-list'), ('/hadis/arguments/filters/', 'hadis-filters'), ('/hadis/narrators/filters/', 'narrator-filters'), ('/hadis/narrators/', 'narrators'), ('/hadis/references/', 'references'), ] for url_path, expected_url_name in test_urls: with self.subTest(url_path=url_path): try: resolved = resolve(url_path) # Check that the URL resolves self.assertIsNotNone(resolved) # Check that we can reverse back to the same URL reversed_url = reverse(expected_url_name) self.assertEqual(url_path, reversed_url) except Exception as e: self.fail(f"URL '{url_path}' could not be resolved: {e}")