207 lines
8.5 KiB
Python
207 lines
8.5 KiB
Python
"""
|
|
Unit tests for response helper functions
|
|
Tests success_response, error_response, paginated_response
|
|
"""
|
|
from django.test import TestCase, RequestFactory
|
|
from rest_framework import status
|
|
from igny8_core.api.response import success_response, error_response, paginated_response, get_request_id
|
|
|
|
|
|
class ResponseHelpersTestCase(TestCase):
|
|
"""Test cases for response helper functions"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.factory = RequestFactory()
|
|
|
|
def test_success_response_with_data(self):
|
|
"""Test success_response with data"""
|
|
data = {"id": 1, "name": "Test"}
|
|
response = success_response(data=data, message="Success")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['data'], data)
|
|
self.assertEqual(response.data['message'], "Success")
|
|
|
|
def test_success_response_without_data(self):
|
|
"""Test success_response without data"""
|
|
response = success_response(message="Success")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertTrue(response.data['success'])
|
|
self.assertNotIn('data', response.data)
|
|
self.assertEqual(response.data['message'], "Success")
|
|
|
|
def test_success_response_with_custom_status(self):
|
|
"""Test success_response with custom status code"""
|
|
data = {"id": 1}
|
|
response = success_response(data=data, status_code=status.HTTP_201_CREATED)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['data'], data)
|
|
|
|
def test_success_response_with_request_id(self):
|
|
"""Test success_response includes request_id when request provided"""
|
|
request = self.factory.get('/test/')
|
|
request.request_id = 'test-request-id-123'
|
|
|
|
response = success_response(data={"id": 1}, request=request)
|
|
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['request_id'], 'test-request-id-123')
|
|
|
|
def test_error_response_with_error_message(self):
|
|
"""Test error_response with error message"""
|
|
response = error_response(error="Validation failed")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertFalse(response.data['success'])
|
|
self.assertEqual(response.data['error'], "Validation failed")
|
|
|
|
def test_error_response_with_errors_dict(self):
|
|
"""Test error_response with field-specific errors"""
|
|
errors = {"email": ["Invalid email format"], "password": ["Too short"]}
|
|
response = error_response(error="Validation failed", errors=errors)
|
|
|
|
self.assertFalse(response.data['success'])
|
|
self.assertEqual(response.data['error'], "Validation failed")
|
|
self.assertEqual(response.data['errors'], errors)
|
|
|
|
def test_error_response_status_code_mapping(self):
|
|
"""Test error_response maps status codes to default error messages"""
|
|
# Test 401
|
|
response = error_response(status_code=status.HTTP_401_UNAUTHORIZED)
|
|
self.assertEqual(response.data['error'], 'Authentication required')
|
|
|
|
# Test 403
|
|
response = error_response(status_code=status.HTTP_403_FORBIDDEN)
|
|
self.assertEqual(response.data['error'], 'Permission denied')
|
|
|
|
# Test 404
|
|
response = error_response(status_code=status.HTTP_404_NOT_FOUND)
|
|
self.assertEqual(response.data['error'], 'Resource not found')
|
|
|
|
# Test 409
|
|
response = error_response(status_code=status.HTTP_409_CONFLICT)
|
|
self.assertEqual(response.data['error'], 'Conflict')
|
|
|
|
# Test 422
|
|
response = error_response(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
|
|
self.assertEqual(response.data['error'], 'Validation failed')
|
|
|
|
# Test 429
|
|
response = error_response(status_code=status.HTTP_429_TOO_MANY_REQUESTS)
|
|
self.assertEqual(response.data['error'], 'Rate limit exceeded')
|
|
|
|
# Test 500
|
|
response = error_response(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
self.assertEqual(response.data['error'], 'Internal server error')
|
|
|
|
def test_error_response_with_request_id(self):
|
|
"""Test error_response includes request_id when request provided"""
|
|
request = self.factory.get('/test/')
|
|
request.request_id = 'test-request-id-456'
|
|
|
|
response = error_response(error="Error occurred", request=request)
|
|
|
|
self.assertFalse(response.data['success'])
|
|
self.assertEqual(response.data['request_id'], 'test-request-id-456')
|
|
|
|
def test_error_response_with_debug_info(self):
|
|
"""Test error_response includes debug info when provided"""
|
|
debug_info = {"exception_type": "ValueError", "message": "Test error"}
|
|
response = error_response(error="Error", debug_info=debug_info)
|
|
|
|
self.assertFalse(response.data['success'])
|
|
self.assertEqual(response.data['debug'], debug_info)
|
|
|
|
def test_paginated_response_with_data(self):
|
|
"""Test paginated_response with paginated data"""
|
|
paginated_data = {
|
|
'count': 100,
|
|
'next': 'http://test.com/api/v1/test/?page=2',
|
|
'previous': None,
|
|
'results': [{"id": 1}, {"id": 2}]
|
|
}
|
|
response = paginated_response(paginated_data, message="Success")
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['count'], 100)
|
|
self.assertEqual(response.data['next'], paginated_data['next'])
|
|
self.assertEqual(response.data['previous'], None)
|
|
self.assertEqual(response.data['results'], paginated_data['results'])
|
|
self.assertEqual(response.data['message'], "Success")
|
|
|
|
def test_paginated_response_without_message(self):
|
|
"""Test paginated_response without message"""
|
|
paginated_data = {
|
|
'count': 50,
|
|
'next': None,
|
|
'previous': None,
|
|
'results': []
|
|
}
|
|
response = paginated_response(paginated_data)
|
|
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['count'], 50)
|
|
self.assertNotIn('message', response.data)
|
|
|
|
def test_paginated_response_with_request_id(self):
|
|
"""Test paginated_response includes request_id when request provided"""
|
|
request = self.factory.get('/test/')
|
|
request.request_id = 'test-request-id-789'
|
|
|
|
paginated_data = {
|
|
'count': 10,
|
|
'next': None,
|
|
'previous': None,
|
|
'results': []
|
|
}
|
|
response = paginated_response(paginated_data, request=request)
|
|
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['request_id'], 'test-request-id-789')
|
|
|
|
def test_paginated_response_fallback(self):
|
|
"""Test paginated_response handles non-dict input"""
|
|
response = paginated_response(None)
|
|
|
|
self.assertTrue(response.data['success'])
|
|
self.assertEqual(response.data['count'], 0)
|
|
self.assertIsNone(response.data['next'])
|
|
self.assertIsNone(response.data['previous'])
|
|
self.assertEqual(response.data['results'], [])
|
|
|
|
def test_get_request_id_from_request_object(self):
|
|
"""Test get_request_id retrieves from request.request_id"""
|
|
request = self.factory.get('/test/')
|
|
request.request_id = 'request-id-from-object'
|
|
|
|
request_id = get_request_id(request)
|
|
self.assertEqual(request_id, 'request-id-from-object')
|
|
|
|
def test_get_request_id_from_headers(self):
|
|
"""Test get_request_id retrieves from headers"""
|
|
request = self.factory.get('/test/', HTTP_X_REQUEST_ID='request-id-from-header')
|
|
|
|
request_id = get_request_id(request)
|
|
self.assertEqual(request_id, 'request-id-from-header')
|
|
|
|
def test_get_request_id_generates_new(self):
|
|
"""Test get_request_id generates new UUID if not found"""
|
|
request = self.factory.get('/test/')
|
|
|
|
request_id = get_request_id(request)
|
|
self.assertIsNotNone(request_id)
|
|
self.assertIsInstance(request_id, str)
|
|
# UUID format check
|
|
import uuid
|
|
try:
|
|
uuid.UUID(request_id)
|
|
except ValueError:
|
|
self.fail("Generated request_id is not a valid UUID")
|
|
|