LinkDesk/backend/test_custom_status_delete_i...

202 lines
6.7 KiB
Python

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