# Project API Tests # Test: Create a new project with all fields (POST /api/projects) POST {{host}}/api/projects Content-Type: application/json { "title": "Test Project Alpha", "color": "#1976d2" } HTTP 201 [Captures] project_id: jsonpath "$.id" [Asserts] jsonpath "$.title" == "Test Project Alpha" jsonpath "$.color" == "#1976d2" jsonpath "$.status" == "active" jsonpath "$.folder_id" == null jsonpath "$.sort_order" == 0 jsonpath "$.id" exists jsonpath "$.created_at" exists jsonpath "$.updated_at" exists # Test: Create another new project POST {{host}}/api/projects Content-Type: application/json { "title": "Test Project Beta", "color": "#ffffff" } HTTP 201 [Captures] project_id_beta: jsonpath "$.id" [Asserts] jsonpath "$.title" == "Test Project Beta" jsonpath "$.color" == "#ffffff" jsonpath "$.status" == "active" jsonpath "$.folder_id" == null jsonpath "$.sort_order" == 1000 jsonpath "$.id" exists jsonpath "$.created_at" exists jsonpath "$.updated_at" exists POST {{host}}/api/projects Content-Type: application/json { "title": "Missing Color" } HTTP 422 [Asserts] jsonpath "$.error" exists # Test: Create project with invalid data (missing title) POST {{host}}/api/projects Content-Type: application/json { "color": "#ffffff" } HTTP 422 [Asserts] jsonpath "$.error" exists # Test: Create project with invalid data (invalid color) POST {{host}}/api/projects Content-Type: application/json { "title": "Invalid Color", "color": "#ffffffasdf" } HTTP 422 [Asserts] jsonpath "$.error" exists # Test: Get a specific project by ID (GET /api/projects/{id}) GET {{host}}/api/projects/{{project_id}} HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.title" == "Test Project Alpha" jsonpath "$.color" == "#1976d2" jsonpath "$.status" == "active" jsonpath "$.folder_id" == null jsonpath "$.created_at" exists jsonpath "$.updated_at" exists # Test: Get a minimal project by ID GET {{host}}/api/projects/{{project_id_beta}} HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id_beta}}" jsonpath "$.title" == "Test Project Beta" jsonpath "$.color" == "#ffffff" jsonpath "$.status" == "active" # Test: Get non-existent project GET {{host}}/api/projects/00000000-0000-0000-0000-000000000000 HTTP 404 [Asserts] jsonpath "$.error" exists # Test: Get project with invalid UUID format GET {{host}}/api/projects/invalid-uuid HTTP 400 [Asserts] jsonpath "$.error" exists # Test: List all projects (GET /api/projects) GET {{host}}/api/projects HTTP 200 [Captures] initial_count: jsonpath "$" count [Asserts] jsonpath "$" isCollection jsonpath "$[*].id" contains "{{project_id}}" jsonpath "$[*].id" contains "{{project_id_beta}}" jsonpath "$[*].title" contains "Test Project Alpha" jsonpath "$[*].title" contains "Test Project Beta" # Test: Verify all projects have required fields GET {{host}}/api/projects HTTP 200 [Asserts] jsonpath "$[?(@.id=='{{project_id}}')].title" exists jsonpath "$[?(@.id=='{{project_id}}')].status" exists jsonpath "$[?(@.id=='{{project_id}}')].created_at" exists jsonpath "$[?(@.id=='{{project_id}}')].updated_at" exists jsonpath "$[?(@.id=='{{project_id}}')].sort_order" exists # Test: Update project title only (PUT /api/projects/{id}) PUT {{host}}/api/projects/{{project_id}} Content-Type: application/json { "title": "Updated Project Alpha" } HTTP 200 [Captures] first_updated_at: jsonpath "$.updated_at" [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.title" == "Updated Project Alpha" jsonpath "$.color" == "#1976d2" jsonpath "$.status" == "active" # Test: Update status to done PUT {{host}}/api/projects/{{project_id}} Content-Type: application/json { "status": "done" } HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.status" == "done" # Test: Update status to backlog PUT {{host}}/api/projects/{{project_id}} Content-Type: application/json { "status": "backlog" } HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.status" == "backlog" # Test: Update color PUT {{host}}/api/projects/{{project_id}} Content-Type: application/json { "color": "#388e3c" } HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.color" == "#388e3c" # Test: Update multiple fields together PUT {{host}}/api/projects/{{project_id}} Content-Type: application/json { "title": "Completely Updated Project", "color": "#d32f2f", "status": "active" } HTTP 200 [Asserts] jsonpath "$.id" == "{{project_id}}" jsonpath "$.title" == "Completely Updated Project" jsonpath "$.color" == "#d32f2f" jsonpath "$.status" == "active" # Test: Update non-existent project PUT {{host}}/api/projects/00000000-0000-0000-0000-000000000000 Content-Type: application/json { "title": "This should fail" } HTTP 404 [Asserts] jsonpath "$.error" exists # Test: Update with invalid UUID format PUT {{host}}/api/projects/invalid-uuid-format Content-Type: application/json { "title": "This should also fail" } HTTP 400 [Asserts] jsonpath "$.error" exists # Test: Update with empty title PUT {{host}}/api/projects/{{project_id_beta}} Content-Type: application/json { "title": "" } HTTP 422 [Asserts] jsonpath "$.error" exists # Test: Update with invalid status PUT {{host}}/api/projects/{{project_id_beta}} Content-Type: application/json { "status": "invalid_status" } HTTP 422 [Asserts] jsonpath "$.error" exists # Test: Update with invalid color format PUT {{host}}/api/projects/{{project_id_beta}} Content-Type: application/json { "color": "invalid-color" } HTTP 422 [Asserts] jsonpath "$.error" exists # Setup: Create a project to delete POST {{host}}/api/projects Content-Type: application/json { "title": "Project to Delete", "color": "#222222" } HTTP 201 [Captures] delete_project_id: jsonpath "$.id" # Test: Delete project successfully (DELETE /api/projects/{id}) DELETE {{host}}/api/projects/{{delete_project_id}} HTTP 204 # Test: Verify project is deleted (should return 404) GET {{host}}/api/projects/{{delete_project_id}} HTTP 404 [Asserts] jsonpath "$.error" exists # Setup: Create another project for additional delete tests POST {{host}}/api/projects Content-Type: application/json { "title": "Another Project to Delete", "color": "#333333" } HTTP 201 [Captures] another_delete_project_id: jsonpath "$.id" # Test: Verify project exists before deletion GET {{host}}/api/projects/{{another_delete_project_id}} HTTP 200 [Asserts] jsonpath "$.title" == "Another Project to Delete" # Test: Delete the project DELETE {{host}}/api/projects/{{another_delete_project_id}} HTTP 204 # Test: Confirm project no longer exists GET {{host}}/api/projects/{{another_delete_project_id}} HTTP 404 [Asserts] jsonpath "$.error" exists # Test: Delete non-existent project DELETE {{host}}/api/projects/00000000-0000-0000-0000-000000000000 HTTP 404 [Asserts] jsonpath "$.error" exists # Test: Delete with invalid UUID format DELETE {{host}}/api/projects/invalid-uuid-format HTTP 400 [Asserts] jsonpath "$.error" exists # Test: Multiple deletions of same project (idempotency test) POST {{host}}/api/projects Content-Type: application/json { "title": "Project for Idempotency Test", "color": "#234567" } HTTP 201 [Captures] idempotent_project_id: jsonpath "$.id" # First deletion should succeed DELETE {{host}}/api/projects/{{idempotent_project_id}} HTTP 204 # Second deletion should return 404 (project already gone) DELETE {{host}}/api/projects/{{idempotent_project_id}} HTTP 404 [Asserts] jsonpath "$.error" exists # Test: List shows remaining projects after deletions GET {{host}}/api/projects HTTP 200 [Asserts] jsonpath "$[*].id" contains "{{project_id}}" jsonpath "$[*].id" contains "{{project_id_beta}}" jsonpath "$[*].id" not contains "{{delete_project_id}}" jsonpath "$[*].id" not contains "{{another_delete_project_id}}" jsonpath "$[*].id" not contains "{{idempotent_project_id}}" # Cleanup: Delete remaining test projects DELETE {{host}}/api/projects/{{project_id}} HTTP 204 DELETE {{host}}/api/projects/{{project_id_beta}} HTTP 204 # Test: Verify all test projects are cleaned up GET {{host}}/api/projects HTTP 200 [Asserts] jsonpath "$[*].id" not contains "{{project_id}}" jsonpath "$[*].id" not contains "{{project_id_beta}}"