""" Integration tests for Planner module endpoints Tests CRUD operations and AI actions return unified format """ from rest_framework import status from igny8_core.api.tests.test_integration_base import IntegrationTestBase from igny8_core.modules.planner.models import Keywords, Clusters, ContentIdeas class PlannerIntegrationTestCase(IntegrationTestBase): """Integration tests for Planner module""" def test_list_keywords_returns_unified_format(self): """Test GET /api/v1/planner/keywords/ returns unified format""" response = self.client.get('/api/v1/planner/keywords/') # May get 429 if rate limited - both should have unified format if response.status_code == status.HTTP_429_TOO_MANY_REQUESTS: self.assert_unified_response_format(response, expected_success=False) else: self.assertEqual(response.status_code, status.HTTP_200_OK) self.assert_paginated_response(response) def test_create_keyword_returns_unified_format(self): """Test POST /api/v1/planner/keywords/ returns unified format""" data = { 'seed_keyword_id': self.seed_keyword.id, 'site_id': self.site.id, 'sector_id': self.sector.id, 'status': 'active' } response = self.client.post('/api/v1/planner/keywords/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assert_unified_response_format(response, expected_success=True) self.assertIn('data', response.data) self.assertIn('id', response.data['data']) def test_retrieve_keyword_returns_unified_format(self): """Test GET /api/v1/planner/keywords/{id}/ returns unified format""" keyword = Keywords.objects.create( seed_keyword=self.seed_keyword, site=self.site, sector=self.sector, account=self.account, status='active' ) response = self.client.get(f'/api/v1/planner/keywords/{keyword.id}/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assert_unified_response_format(response, expected_success=True) self.assertIn('data', response.data) self.assertEqual(response.data['data']['id'], keyword.id) def test_update_keyword_returns_unified_format(self): """Test PUT /api/v1/planner/keywords/{id}/ returns unified format""" keyword = Keywords.objects.create( seed_keyword=self.seed_keyword, site=self.site, sector=self.sector, account=self.account, status='active' ) data = { 'seed_keyword_id': self.seed_keyword.id, 'site_id': self.site.id, 'sector_id': self.sector.id, 'status': 'archived' } response = self.client.put(f'/api/v1/planner/keywords/{keyword.id}/', data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assert_unified_response_format(response, expected_success=True) self.assertIn('data', response.data) def test_delete_keyword_returns_unified_format(self): """Test DELETE /api/v1/planner/keywords/{id}/ returns unified format""" keyword = Keywords.objects.create( seed_keyword=self.seed_keyword, site=self.site, sector=self.sector, account=self.account, status='active' ) response = self.client.delete(f'/api/v1/planner/keywords/{keyword.id}/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) def test_list_clusters_returns_unified_format(self): """Test GET /api/v1/planner/clusters/ returns unified format""" response = self.client.get('/api/v1/planner/clusters/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assert_paginated_response(response) def test_create_cluster_returns_unified_format(self): """Test POST /api/v1/planner/clusters/ returns unified format""" data = { 'name': 'Test Cluster', 'description': 'Test description', 'site_id': self.site.id, 'sector_id': self.sector.id, 'status': 'active' } response = self.client.post('/api/v1/planner/clusters/', data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assert_unified_response_format(response, expected_success=True) self.assertIn('data', response.data) def test_list_ideas_returns_unified_format(self): """Test GET /api/v1/planner/ideas/ returns unified format""" response = self.client.get('/api/v1/planner/ideas/') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assert_paginated_response(response) def test_auto_cluster_returns_unified_format(self): """Test POST /api/v1/planner/keywords/auto_cluster/ returns unified format""" keyword = Keywords.objects.create( seed_keyword=self.seed_keyword, site=self.site, sector=self.sector, account=self.account, status='active' ) data = { 'ids': [keyword.id], 'sector_id': self.sector.id } response = self.client.post('/api/v1/planner/keywords/auto_cluster/', data, format='json') # Should return either task_id (async) or success response self.assertIn(response.status_code, [status.HTTP_200_OK, status.HTTP_202_ACCEPTED]) self.assert_unified_response_format(response, expected_success=True) def test_keyword_validation_error_returns_unified_format(self): """Test validation errors return unified format""" # 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('error', response.data) self.assertIn('errors', response.data) self.assertIn('request_id', response.data) def test_keyword_not_found_returns_unified_format(self): """Test 404 errors return 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.assertIn('request_id', response.data)