93 lines
4.2 KiB
Python
93 lines
4.2 KiB
Python
"""
|
|
Integration tests for error scenarios
|
|
Tests 400, 401, 403, 404, 429, 500 responses return unified format
|
|
"""
|
|
from rest_framework import status
|
|
from django.test import TestCase
|
|
from rest_framework.test import APIClient
|
|
from igny8_core.auth.models import User, Account, Plan
|
|
from igny8_core.api.tests.test_integration_base import IntegrationTestBase
|
|
|
|
|
|
class ErrorScenariosTestCase(IntegrationTestBase):
|
|
"""Integration tests for error scenarios"""
|
|
|
|
def test_400_bad_request_returns_unified_format(self):
|
|
"""Test 400 Bad Request returns unified format"""
|
|
# Invalid data
|
|
data = {'invalid': 'data'}
|
|
response = self.client.post('/api/v1/planner/keywords/', data, format='json')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
self.assertIn('error', response.data)
|
|
self.assertIn('errors', response.data)
|
|
self.assertIn('request_id', response.data)
|
|
|
|
def test_401_unauthorized_returns_unified_format(self):
|
|
"""Test 401 Unauthorized returns unified format"""
|
|
# Create unauthenticated client
|
|
unauthenticated_client = APIClient()
|
|
response = unauthenticated_client.get('/api/v1/planner/keywords/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
self.assertIn('error', response.data)
|
|
self.assertEqual(response.data['error'], 'Authentication required')
|
|
self.assertIn('request_id', response.data)
|
|
|
|
def test_403_forbidden_returns_unified_format(self):
|
|
"""Test 403 Forbidden returns unified format"""
|
|
# Create viewer user (limited permissions)
|
|
viewer_user = User.objects.create_user(
|
|
username='viewer',
|
|
email='viewer@test.com',
|
|
password='testpass123',
|
|
role='viewer',
|
|
account=self.account
|
|
)
|
|
|
|
viewer_client = APIClient()
|
|
viewer_client.force_authenticate(user=viewer_user)
|
|
|
|
# Try to access admin-only endpoint (if exists)
|
|
# For now, test with a protected endpoint that requires editor+
|
|
response = viewer_client.post('/api/v1/planner/keywords/auto_cluster/', {}, format='json')
|
|
|
|
# May return 400 (validation) or 403 (permission), both should be unified
|
|
self.assertIn(response.status_code, [status.HTTP_400_BAD_REQUEST, status.HTTP_403_FORBIDDEN])
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
self.assertIn('error', response.data)
|
|
self.assertIn('request_id', response.data)
|
|
|
|
def test_404_not_found_returns_unified_format(self):
|
|
"""Test 404 Not Found returns unified format"""
|
|
response = self.client.get('/api/v1/planner/keywords/99999/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
self.assertIn('error', response.data)
|
|
self.assertEqual(response.data['error'], 'Resource not found')
|
|
self.assertIn('request_id', response.data)
|
|
|
|
def test_404_invalid_endpoint_returns_unified_format(self):
|
|
"""Test 404 for invalid endpoint returns unified format"""
|
|
response = self.client.get('/api/v1/nonexistent/endpoint/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
# DRF may return different format for URL not found, but our handler should catch it
|
|
if 'success' in response.data:
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
|
|
def test_validation_error_returns_unified_format(self):
|
|
"""Test validation errors return unified format with field-specific errors"""
|
|
# Missing required fields
|
|
response = self.client.post('/api/v1/planner/keywords/', {}, format='json')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assert_unified_response_format(response, expected_success=False)
|
|
self.assertIn('errors', response.data)
|
|
# Should have field-specific errors
|
|
self.assertIsInstance(response.data['errors'], dict)
|
|
|