""" 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)