You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
15 KiB
335 lines
15 KiB
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}")
|