2 changed files with 452 additions and 2 deletions
@ -1,3 +1,335 @@ |
|||
from django.test import TestCase |
|||
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 |
|||
|
|||
# Create your tests here. |
|||
|
|||
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}") |
|||
@ -0,0 +1,118 @@ |
|||
#!/usr/bin/env python |
|||
""" |
|||
Simple script to test hadis API endpoints connectivity. |
|||
This script manually tests all hadis URLs to verify they return proper HTTP status codes. |
|||
""" |
|||
|
|||
import os |
|||
import sys |
|||
import django |
|||
from django.conf import settings |
|||
from django.test import override_settings |
|||
|
|||
# Setup Django |
|||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.base') |
|||
django.setup() |
|||
|
|||
from django.test import Client |
|||
from django.urls import reverse |
|||
from rest_framework import status |
|||
|
|||
|
|||
def test_endpoint(client, url_name, kwargs=None, description=""): |
|||
"""Test a single endpoint and return the result""" |
|||
try: |
|||
if kwargs: |
|||
url = reverse(url_name, kwargs=kwargs) |
|||
else: |
|||
url = reverse(url_name) |
|||
|
|||
response = client.get(url) |
|||
status_code = response.status_code |
|||
|
|||
if status_code in [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND]: |
|||
result = "✅ PASS" |
|||
else: |
|||
result = f"❌ FAIL ({status_code})" |
|||
|
|||
print(f"{result} {description}: {url} -> {status_code}") |
|||
return status_code in [status.HTTP_200_OK, status.HTTP_404_NOT_FOUND] |
|||
|
|||
except Exception as e: |
|||
print(f"❌ ERROR {description}: {url_name} -> {str(e)}") |
|||
return False |
|||
|
|||
|
|||
def main(): |
|||
"""Main test function""" |
|||
print("🧪 Testing Hadis API Endpoints Connectivity") |
|||
print("=" * 60) |
|||
|
|||
# Override ALLOWED_HOSTS for testing |
|||
with override_settings(ALLOWED_HOSTS=['testserver']): |
|||
client = Client() |
|||
total_tests = 0 |
|||
passed_tests = 0 |
|||
|
|||
# Test non-parameterized endpoints |
|||
print("\n📋 Testing non-parameterized endpoints:") |
|||
non_param_endpoints = [ |
|||
('hadis-collection-list', None, 'Collections'), |
|||
('hadis-sect-list', None, 'Sync Sects'), |
|||
('hadis-category-tree', None, 'Sync Categories Tree'), |
|||
('hadis-sync', None, 'Sync Hadis'), |
|||
('transmitter-sync', None, 'Sync Narrators'), |
|||
('reference-sync', None, 'Sync References'), |
|||
('hadis-info', None, 'Info'), |
|||
('hadis-category-tree-normal', None, 'Categories Tree Normal'), |
|||
('categories', None, 'Categories'), |
|||
('hadis-main-list', None, 'Hadis Main List (Arguments)'), |
|||
('hadis-filters', None, 'Hadis Filters'), |
|||
('narrator-filters', None, 'Narrator Filters'), |
|||
('narrators', None, 'Narrators'), |
|||
('references', None, 'References'), |
|||
] |
|||
|
|||
for url_name, kwargs, description in non_param_endpoints: |
|||
total_tests += 1 |
|||
if test_endpoint(client, url_name, kwargs, description): |
|||
passed_tests += 1 |
|||
|
|||
# Test parameterized endpoints |
|||
print("\n📋 Testing parameterized endpoints:") |
|||
param_endpoints = [ |
|||
('categories-by-sect', {'sect_type': '1'}, 'Categories by Sect (type=1)'), |
|||
('categories-tree-by-sect', {'sect_type': '1', 'slug': 'test-category'}, 'Categories Tree by Sect'), |
|||
('categories-tree-by-sect-source', {'sect_type': '1', 'slug': 'test-category', 'source_type': 'quran'}, 'Categories Tree by Sect Source'), |
|||
('hadis-list', {'category_slug': 'test-category'}, 'Hadis List by Category'), |
|||
('narrator-detail', {'narrator_slug': 'test-narrator'}, 'Narrator Detail'), |
|||
('narrator-opinions', {'narrator_slug': 'test-narrator'}, 'Narrator Opinions'), |
|||
('narrator-original-texts', {'narrator_slug': 'test-narrator'}, 'Narrator Original Texts'), |
|||
('reference-detail', {'reference_slug': 'test-reference'}, 'Reference Detail'), |
|||
('hadis-basic', {'hadis_slug': 'test-hadis'}, 'Hadis Basic'), |
|||
('hadis-detail', {'hadis_slug': 'test-hadis'}, 'Hadis Detail'), |
|||
('hadis-transmitters', {'hadis_slug': 'test-hadis'}, 'Hadis Transmitters'), |
|||
('hadis-corrections', {'hadis_slug': 'test-hadis'}, 'Hadis Corrections'), |
|||
] |
|||
|
|||
for url_name, kwargs, description in param_endpoints: |
|||
total_tests += 1 |
|||
if test_endpoint(client, url_name, kwargs, description): |
|||
passed_tests += 1 |
|||
|
|||
# Summary |
|||
print("\n" + "=" * 60) |
|||
print(f"📊 Test Results: {passed_tests}/{total_tests} endpoints accessible") |
|||
success_rate = (passed_tests / total_tests) * 100 if total_tests > 0 else 0 |
|||
print(f"📈 Success Rate: {success_rate:.1f}%") |
|||
if passed_tests == total_tests: |
|||
print("✅ All endpoints are properly configured and accessible!") |
|||
else: |
|||
print("⚠️ Some endpoints may have issues") |
|||
|
|||
return passed_tests == total_tests |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
success = main() |
|||
sys.exit(0 if success else 1) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue