""" Integration test for custom task status DELETE endpoint Tests the complete workflow with real database operations """ import requests import json BASE_URL = "http://localhost:8000" def login(): """Login and get access token""" response = requests.post( f"{BASE_URL}/auth/login", json={"email": "admin@vfx.com", "password": "admin123"} ) return response.json()["access_token"] if response.status_code == 200 else None def headers(token): return {"Authorization": f"Bearer {token}"} def test_complete_workflow(): """Test complete workflow: create, use, delete with reassignment""" print("\n" + "="*60) print("INTEGRATION TEST: Complete Custom Status Delete Workflow") print("="*60) token = login() if not token: print("❌ Login failed") return False # Get project projects = requests.get(f"{BASE_URL}/projects/", headers=headers(token)).json() project_id = projects[0]["id"] print(f"\n✓ Using project ID: {project_id}") # Step 1: Create two custom statuses with unique names print("\n--- Step 1: Create two custom statuses ---") import time timestamp = int(time.time()) status1_response = requests.post( f"{BASE_URL}/projects/{project_id}/task-statuses", headers=headers(token), json={"name": f"IntTest1_{timestamp}", "color": "#FF0000"} ) if status1_response.status_code != 201: print(f"❌ Failed to create status 1: {status1_response.text}") return False status1 = status1_response.json()["status"] status2_response = requests.post( f"{BASE_URL}/projects/{project_id}/task-statuses", headers=headers(token), json={"name": f"IntTest2_{timestamp}", "color": "#00FF00"} ) if status2_response.status_code != 201: print(f"❌ Failed to create status 2: {status2_response.text}") return False status2 = status2_response.json()["status"] print(f"✓ Created status 1: {status1['name']} (ID: {status1['id']})") print(f"✓ Created status 2: {status2['name']} (ID: {status2['id']})") # Step 2: Set status1 as default print("\n--- Step 2: Set status 1 as default ---") requests.put( f"{BASE_URL}/projects/{project_id}/task-statuses/{status1['id']}", headers=headers(token), json={"is_default": True} ) print(f"✓ Set '{status1['name']}' as default") # Step 3: Get an existing task and update its status print("\n--- Step 3: Update existing task to status 1 ---") # Get tasks for the project tasks_response = requests.get( f"{BASE_URL}/tasks/?project_id={project_id}", headers=headers(token) ) if tasks_response.status_code != 200: print(f"❌ Failed to get tasks: {tasks_response.text}") return False tasks = tasks_response.json() if not tasks: print("❌ No tasks found in project") return False task = tasks[0] task_id = task['id'] # Update task status to status1 update_response = requests.put( f"{BASE_URL}/tasks/{task_id}/status", headers=headers(token), json={"status": status1['id']} ) if update_response.status_code != 200: print(f"❌ Failed to update task status: {update_response.text}") return False print(f"✓ Updated task ID: {task_id} to status '{status1['name']}'") # Step 4: Try to delete status1 without reassignment (should fail) print("\n--- Step 4: Try to delete status 1 without reassignment ---") delete_response = requests.delete( f"{BASE_URL}/projects/{project_id}/task-statuses/{status1['id']}", headers=headers(token) ) if delete_response.status_code == 422: error = delete_response.json()["detail"] print(f"✓ Expected error received:") print(f" - Task count: {error['task_count']}") print(f" - Task IDs: {error['task_ids']}") else: print(f"❌ Unexpected response: {delete_response.status_code}") return False # Step 5: Delete status1 with reassignment to status2 print("\n--- Step 5: Delete status 1 with reassignment to status 2 ---") delete_response = requests.delete( f"{BASE_URL}/projects/{project_id}/task-statuses/{status1['id']}?reassign_to_status_id={status2['id']}", headers=headers(token) ) if delete_response.status_code == 200: result = delete_response.json() print(f"✓ {result['message']}") print(f"✓ New default status: {result['all_statuses']['default_status_id']}") else: print(f"❌ Delete failed: {delete_response.status_code}") print(delete_response.text) return False # Step 6: Verify task was reassigned print("\n--- Step 6: Verify task was reassigned ---") updated_task = requests.get( f"{BASE_URL}/tasks/{task_id}", headers=headers(token) ).json() if updated_task['status'] == status2['id']: print(f"✓ Task status updated to '{status2['name']}'") else: print(f"❌ Task status not updated correctly: {updated_task['status']}") return False # Step 7: Verify status1 no longer exists print("\n--- Step 7: Verify status 1 no longer exists ---") all_statuses = requests.get( f"{BASE_URL}/projects/{project_id}/task-statuses", headers=headers(token) ).json() status1_exists = any(s['id'] == status1['id'] for s in all_statuses['statuses']) status2_exists = any(s['id'] == status2['id'] for s in all_statuses['statuses']) if not status1_exists and status2_exists: print(f"✓ Status 1 deleted successfully") print(f"✓ Status 2 still exists") else: print(f"❌ Status verification failed") return False # Step 8: Verify new default was assigned print("\n--- Step 8: Verify new default was assigned ---") if all_statuses['default_status_id'] == status2['id']: print(f"✓ Status 2 is now the default (auto-assigned)") else: print(f"⚠ Default status: {all_statuses['default_status_id']}") # Cleanup: Reset task status and delete status2 print("\n--- Cleanup ---") requests.put( f"{BASE_URL}/tasks/{task_id}/status", headers=headers(token), json={"status": "not_started"} ) print(f"✓ Reset task status to 'not_started'") # Note: We can't delete status2 if it's the last one, so we'll leave it print("\n" + "="*60) print("✅ ALL INTEGRATION TESTS PASSED") print("="*60) return True if __name__ == "__main__": success = test_complete_workflow() exit(0 if success else 1)