346 lines
12 KiB
Python
346 lines
12 KiB
Python
"""
|
|
Test script for DELETE custom task status endpoint
|
|
|
|
Tests:
|
|
1. Delete unused custom status
|
|
2. Delete status in use without reassignment (should fail)
|
|
3. Delete status in use with reassignment
|
|
4. Delete default status (should auto-assign new default)
|
|
5. Prevent deletion of last status
|
|
6. Delete non-existent status (should fail)
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
|
|
BASE_URL = "http://localhost:8000"
|
|
|
|
def login_as_admin():
|
|
"""Login and get access token"""
|
|
response = requests.post(
|
|
f"{BASE_URL}/auth/login",
|
|
json={
|
|
"email": "admin@vfx.com",
|
|
"password": "admin123"
|
|
}
|
|
)
|
|
if response.status_code == 200:
|
|
return response.json()["access_token"]
|
|
else:
|
|
print(f"Login failed: {response.status_code}")
|
|
print(response.text)
|
|
return None
|
|
|
|
def get_headers(token):
|
|
"""Get authorization headers"""
|
|
return {"Authorization": f"Bearer {token}"}
|
|
|
|
def test_delete_unused_status(token, project_id):
|
|
"""Test 1: Delete unused custom status"""
|
|
print("\n=== Test 1: Delete unused custom status ===")
|
|
|
|
# First, create a custom status
|
|
create_response = requests.post(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token),
|
|
json={"name": "Test Delete Status", "color": "#FF0000"}
|
|
)
|
|
|
|
if create_response.status_code != 201:
|
|
print(f"Failed to create status: {create_response.status_code}")
|
|
print(create_response.text)
|
|
return
|
|
|
|
created_status = create_response.json()["status"]
|
|
status_id = created_status["id"]
|
|
print(f"Created status: {created_status['name']} (ID: {status_id})")
|
|
|
|
# Now delete it
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status_id}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 200:
|
|
result = delete_response.json()
|
|
print(f"Message: {result['message']}")
|
|
print(f"Remaining custom statuses: {len(result['all_statuses']['statuses'])}")
|
|
else:
|
|
print(f"Error: {delete_response.text}")
|
|
|
|
def test_delete_status_in_use_without_reassignment(token, project_id):
|
|
"""Test 2: Delete status in use without reassignment (should fail)"""
|
|
print("\n=== Test 2: Delete status in use without reassignment ===")
|
|
|
|
# First, create a custom status
|
|
create_response = requests.post(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token),
|
|
json={"name": "In Use Status", "color": "#00FF00"}
|
|
)
|
|
|
|
if create_response.status_code != 201:
|
|
print(f"Failed to create status: {create_response.status_code}")
|
|
return
|
|
|
|
created_status = create_response.json()["status"]
|
|
status_id = created_status["id"]
|
|
print(f"Created status: {created_status['name']} (ID: {status_id})")
|
|
|
|
# Get a task and update its status to the new custom status
|
|
tasks_response = requests.get(
|
|
f"{BASE_URL}/tasks/?project_id={project_id}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
if tasks_response.status_code == 200:
|
|
tasks = tasks_response.json()
|
|
if tasks:
|
|
task_id = tasks[0]["id"]
|
|
print(f"Found task ID: {task_id}")
|
|
|
|
# Update task status
|
|
update_response = requests.put(
|
|
f"{BASE_URL}/tasks/{task_id}/status",
|
|
headers=get_headers(token),
|
|
json={"status": status_id}
|
|
)
|
|
|
|
if update_response.status_code == 200:
|
|
print(f"Updated task {task_id} to status {status_id}")
|
|
else:
|
|
print(f"Failed to update task: {update_response.status_code}")
|
|
print(update_response.text)
|
|
return
|
|
|
|
# Try to delete the status without reassignment
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status_id}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 422:
|
|
error_detail = delete_response.json()["detail"]
|
|
print(f"Expected error received:")
|
|
print(f" Error: {error_detail.get('error', 'N/A')}")
|
|
print(f" Task count: {error_detail.get('task_count', 'N/A')}")
|
|
print(f" Task IDs: {error_detail.get('task_ids', 'N/A')}")
|
|
else:
|
|
print(f"Unexpected response: {delete_response.text}")
|
|
|
|
def test_delete_status_with_reassignment(token, project_id):
|
|
"""Test 3: Delete status in use with reassignment"""
|
|
print("\n=== Test 3: Delete status in use with reassignment ===")
|
|
|
|
# Get the status we created in test 2 (should still exist)
|
|
statuses_response = requests.get(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
if statuses_response.status_code != 200:
|
|
print("Failed to get statuses")
|
|
return
|
|
|
|
all_statuses = statuses_response.json()
|
|
custom_statuses = all_statuses["statuses"]
|
|
|
|
# Find the "In Use Status"
|
|
status_to_delete = None
|
|
for status in custom_statuses:
|
|
if status["name"] == "In Use Status":
|
|
status_to_delete = status
|
|
break
|
|
|
|
if not status_to_delete:
|
|
print("Status 'In Use Status' not found")
|
|
return
|
|
|
|
status_id = status_to_delete["id"]
|
|
print(f"Found status to delete: {status_to_delete['name']} (ID: {status_id})")
|
|
|
|
# Delete with reassignment to system status "not_started"
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status_id}?reassign_to_status_id=not_started",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 200:
|
|
result = delete_response.json()
|
|
print(f"Message: {result['message']}")
|
|
print(f"Remaining custom statuses: {len(result['all_statuses']['statuses'])}")
|
|
else:
|
|
print(f"Error: {delete_response.text}")
|
|
|
|
def test_delete_default_status(token, project_id):
|
|
"""Test 4: Delete default status (should auto-assign new default)"""
|
|
print("\n=== Test 4: Delete default status ===")
|
|
|
|
# Create two custom statuses
|
|
status1_response = requests.post(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token),
|
|
json={"name": "Default Status Test", "color": "#0000FF"}
|
|
)
|
|
|
|
status2_response = requests.post(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token),
|
|
json={"name": "Non-Default Status", "color": "#FFFF00"}
|
|
)
|
|
|
|
if status1_response.status_code != 201 or status2_response.status_code != 201:
|
|
print("Failed to create statuses")
|
|
return
|
|
|
|
status1 = status1_response.json()["status"]
|
|
status1_id = status1["id"]
|
|
|
|
# Set status1 as default
|
|
update_response = requests.put(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status1_id}",
|
|
headers=get_headers(token),
|
|
json={"is_default": True}
|
|
)
|
|
|
|
if update_response.status_code != 200:
|
|
print("Failed to set default status")
|
|
return
|
|
|
|
print(f"Set '{status1['name']}' as default")
|
|
|
|
# Delete the default status
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status1_id}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 200:
|
|
result = delete_response.json()
|
|
print(f"Message: {result['message']}")
|
|
new_default = result['all_statuses']['default_status_id']
|
|
print(f"New default status ID: {new_default}")
|
|
|
|
# Verify a new default was assigned
|
|
if new_default != "not_started":
|
|
print("✓ New default status was auto-assigned")
|
|
else:
|
|
print("✗ Default reverted to system status")
|
|
else:
|
|
print(f"Error: {delete_response.text}")
|
|
|
|
def test_prevent_delete_last_status(token, project_id):
|
|
"""Test 5: Prevent deletion of last status"""
|
|
print("\n=== Test 5: Prevent deletion of last status ===")
|
|
|
|
# Get all custom statuses
|
|
statuses_response = requests.get(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
if statuses_response.status_code != 200:
|
|
print("Failed to get statuses")
|
|
return
|
|
|
|
all_statuses = statuses_response.json()
|
|
custom_statuses = all_statuses["statuses"]
|
|
|
|
print(f"Current custom statuses: {len(custom_statuses)}")
|
|
|
|
# Delete all but one
|
|
while len(custom_statuses) > 1:
|
|
status_to_delete = custom_statuses[0]
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{status_to_delete['id']}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
if delete_response.status_code == 200:
|
|
custom_statuses.pop(0)
|
|
print(f"Deleted status: {status_to_delete['name']}")
|
|
else:
|
|
print(f"Failed to delete: {delete_response.text}")
|
|
break
|
|
|
|
# Try to delete the last one
|
|
if len(custom_statuses) == 1:
|
|
last_status = custom_statuses[0]
|
|
print(f"\nAttempting to delete last status: {last_status['name']}")
|
|
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{last_status['id']}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 422:
|
|
print(f"✓ Expected error: {delete_response.json()['detail']}")
|
|
else:
|
|
print(f"✗ Unexpected response: {delete_response.text}")
|
|
|
|
def test_delete_nonexistent_status(token, project_id):
|
|
"""Test 6: Delete non-existent status (should fail)"""
|
|
print("\n=== Test 6: Delete non-existent status ===")
|
|
|
|
fake_status_id = "custom_nonexistent"
|
|
|
|
delete_response = requests.delete(
|
|
f"{BASE_URL}/projects/{project_id}/task-statuses/{fake_status_id}",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
print(f"Status: {delete_response.status_code}")
|
|
if delete_response.status_code == 404:
|
|
print(f"✓ Expected error: {delete_response.json()['detail']}")
|
|
else:
|
|
print(f"✗ Unexpected response: {delete_response.text}")
|
|
|
|
def main():
|
|
print("Testing DELETE custom task status endpoint")
|
|
print("=" * 50)
|
|
|
|
# Login
|
|
token = login_as_admin()
|
|
if not token:
|
|
print("Failed to login")
|
|
return
|
|
|
|
print("✓ Logged in successfully")
|
|
|
|
# Get first project
|
|
projects_response = requests.get(
|
|
f"{BASE_URL}/projects/",
|
|
headers=get_headers(token)
|
|
)
|
|
|
|
if projects_response.status_code != 200:
|
|
print("Failed to get projects")
|
|
return
|
|
|
|
projects = projects_response.json()
|
|
if not projects:
|
|
print("No projects found")
|
|
return
|
|
|
|
project_id = projects[0]["id"]
|
|
print(f"Using project ID: {project_id}")
|
|
|
|
# Run tests
|
|
test_delete_unused_status(token, project_id)
|
|
test_delete_status_in_use_without_reassignment(token, project_id)
|
|
test_delete_status_with_reassignment(token, project_id)
|
|
test_delete_default_status(token, project_id)
|
|
test_prevent_delete_last_status(token, project_id)
|
|
test_delete_nonexistent_status(token, project_id)
|
|
|
|
print("\n" + "=" * 50)
|
|
print("All tests completed!")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|