""" Test script for updating custom task statuses Tests Requirements: 2.1, 2.2, 2.3, 5.2 """ import requests import json BASE_URL = "http://localhost:8000" def login_as_admin(): """Login as admin user""" 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_all_task_statuses(token, project_id): """Get all task statuses for a project""" response = requests.get( f"{BASE_URL}/projects/{project_id}/task-statuses", headers={"Authorization": f"Bearer {token}"} ) if response.status_code == 200: return response.json() else: print(f"Failed to get task statuses: {response.status_code}") print(response.text) return None def create_custom_status(token, project_id, name, color=None): """Create a custom task status""" data = {"name": name} if color: data["color"] = color response = requests.post( f"{BASE_URL}/projects/{project_id}/task-statuses", headers={"Authorization": f"Bearer {token}"}, json=data ) if response.status_code == 201: return response.json() else: print(f"Failed to create status: {response.status_code}") print(response.text) return None def update_custom_status(token, project_id, status_id, name=None, color=None, is_default=None): """Update a custom task status""" data = {} if name is not None: data["name"] = name if color is not None: data["color"] = color if is_default is not None: data["is_default"] = is_default response = requests.put( f"{BASE_URL}/projects/{project_id}/task-statuses/{status_id}", headers={"Authorization": f"Bearer {token}"}, json=data ) if response.status_code == 200: return response.json() else: print(f"Failed to update status: {response.status_code}") print(response.text) return None def main(): print("=" * 80) print("Testing Custom Task Status Update Endpoint") print("=" * 80) # Login print("\n1. Logging in as admin...") token = login_as_admin() if not token: print("❌ Failed to login") return print("✅ Login successful") # Use project ID 1 (should exist from setup) project_id = 1 # Get initial statuses print(f"\n2. Getting initial task statuses for project {project_id}...") initial_statuses = get_all_task_statuses(token, project_id) if not initial_statuses: print("❌ Failed to get initial statuses") return print(f"✅ Found {len(initial_statuses['statuses'])} custom statuses") print(f" System statuses: {len(initial_statuses['system_statuses'])}") # Create a test status print("\n3. Creating a test custom status...") create_result = create_custom_status(token, project_id, "Test Status", "#FF5733") if not create_result: print("❌ Failed to create test status") return created_status = create_result['status'] status_id = created_status['id'] print(f"✅ Created status: {created_status['name']} (ID: {status_id})") print(f" Color: {created_status['color']}") print(f" Order: {created_status['order']}") print(f" Is Default: {created_status['is_default']}") # Test 1: Update status name (Requirement 2.1) print("\n4. Test 1: Updating status name...") update_result = update_custom_status(token, project_id, status_id, name="Updated Test Status") if not update_result: print("❌ Failed to update status name") return updated_status = update_result['status'] if updated_status['name'] == "Updated Test Status": print(f"✅ Status name updated successfully: {updated_status['name']}") else: print(f"❌ Status name not updated correctly: {updated_status['name']}") return # Test 2: Update status color (Requirement 2.2) print("\n5. Test 2: Updating status color...") update_result = update_custom_status(token, project_id, status_id, color="#00FF00") if not update_result: print("❌ Failed to update status color") return updated_status = update_result['status'] if updated_status['color'] == "#00FF00": print(f"✅ Status color updated successfully: {updated_status['color']}") else: print(f"❌ Status color not updated correctly: {updated_status['color']}") return # Test 3: Update both name and color (Requirement 2.1, 2.2) print("\n6. Test 3: Updating both name and color...") update_result = update_custom_status( token, project_id, status_id, name="Final Test Status", color="#0000FF" ) if not update_result: print("❌ Failed to update status name and color") return updated_status = update_result['status'] if updated_status['name'] == "Final Test Status" and updated_status['color'] == "#0000FF": print(f"✅ Status name and color updated successfully") print(f" Name: {updated_status['name']}") print(f" Color: {updated_status['color']}") else: print(f"❌ Status not updated correctly") return # Test 4: Validate name uniqueness (Requirement 2.4) print("\n7. Test 4: Testing name uniqueness validation...") # Create another status create_result2 = create_custom_status(token, project_id, "Another Status", "#FFFF00") if not create_result2: print("❌ Failed to create second test status") return status_id2 = create_result2['status']['id'] print(f"✅ Created second status: {create_result2['status']['name']}") # Try to update first status with the name of the second status print(" Attempting to update with duplicate name...") update_result = update_custom_status(token, project_id, status_id, name="Another Status") if update_result is None: print("✅ Duplicate name correctly rejected") else: print("❌ Duplicate name was not rejected") return # Test 5: Try to use system status name (Requirement 2.4) print("\n8. Test 5: Testing system status name conflict...") update_result = update_custom_status(token, project_id, status_id, name="In Progress") if update_result is None: print("✅ System status name correctly rejected") else: print("❌ System status name was not rejected") return # Test 6: Set as default status (Requirement 2.3, 5.2) print("\n9. Test 6: Setting status as default...") update_result = update_custom_status(token, project_id, status_id, is_default=True) if not update_result: print("❌ Failed to set status as default") return updated_status = update_result['status'] all_statuses = update_result['all_statuses'] if updated_status['is_default']: print(f"✅ Status set as default successfully") print(f" Default status ID: {all_statuses['default_status_id']}") # Verify only one default status exists default_count = sum(1 for s in all_statuses['statuses'] if s['is_default']) if default_count == 1: print(f"✅ Only one default status exists") else: print(f"❌ Multiple default statuses found: {default_count}") return else: print(f"❌ Status not set as default") return # Test 7: Set another status as default (should unset previous default) print("\n10. Test 7: Setting another status as default (should unset previous)...") update_result = update_custom_status(token, project_id, status_id2, is_default=True) if not update_result: print("❌ Failed to set second status as default") return all_statuses = update_result['all_statuses'] # Verify only one default status exists default_count = sum(1 for s in all_statuses['statuses'] if s['is_default']) if default_count == 1: print(f"✅ Only one default status exists after changing default") print(f" New default status ID: {all_statuses['default_status_id']}") # Verify the first status is no longer default first_status = next((s for s in all_statuses['statuses'] if s['id'] == status_id), None) if first_status and not first_status['is_default']: print(f"✅ Previous default status correctly unset") else: print(f"❌ Previous default status not unset") return else: print(f"❌ Multiple default statuses found: {default_count}") return # Test 8: Unset default status print("\n11. Test 8: Unsetting default status...") update_result = update_custom_status(token, project_id, status_id2, is_default=False) if not update_result: print("❌ Failed to unset default status") return updated_status = update_result['status'] if not updated_status['is_default']: print(f"✅ Default status unset successfully") else: print(f"❌ Default status not unset") return # Test 9: Update non-existent status print("\n12. Test 9: Testing update of non-existent status...") update_result = update_custom_status(token, project_id, "nonexistent_id", name="Test") if update_result is None: print("✅ Non-existent status correctly rejected") else: print("❌ Non-existent status was not rejected") return # Test 10: Verify flag_modified works (JSON column update) print("\n13. Test 10: Verifying JSON column updates persist...") # Get statuses again to verify changes persisted final_statuses = get_all_task_statuses(token, project_id) if not final_statuses: print("❌ Failed to get final statuses") return # Find our updated status final_status = next((s for s in final_statuses['statuses'] if s['id'] == status_id), None) if final_status: if final_status['name'] == "Final Test Status" and final_status['color'] == "#0000FF": print(f"✅ Changes persisted correctly in database") print(f" Name: {final_status['name']}") print(f" Color: {final_status['color']}") else: print(f"❌ Changes did not persist correctly") return else: print(f"❌ Updated status not found in final list") return print("\n" + "=" * 80) print("✅ ALL TESTS PASSED!") print("=" * 80) print("\nSummary:") print(" ✅ Status name update works (Requirement 2.1)") print(" ✅ Status color update works (Requirement 2.2)") print(" ✅ Default status management works (Requirement 2.3, 5.2)") print(" ✅ Name uniqueness validation works (Requirement 2.4)") print(" ✅ System status name conflict detection works") print(" ✅ Only one default status at a time (Requirement 5.2)") print(" ✅ flag_modified ensures JSON column updates persist") print(" ✅ Non-existent status handling works") if __name__ == "__main__": main()