Create a plan for implementing projects and also create the backend API. (#19)
Some checks failed
Check / Backend (push) Successful in 6m55s
Check / Frontend (push) Successful in 2m2s
Docker Build / Build and Push Backend Image (push) Failing after 11m21s
Docker Build / Build and Push Frontend Image (push) Successful in 5m44s

Creates projects to organize tasks under. (Note the migration also contains the tables for creating folders for projects as well because adding foreign keys is a PITA in sqlite apparently).

Reviewed-on: #19
Co-authored-by: Drew Galbraith <drew@tiramisu.one>
Co-committed-by: Drew Galbraith <drew@tiramisu.one>
This commit is contained in:
Drew 2025-10-28 04:13:12 +00:00 committed by Drew
parent 69f4a6f1ca
commit 4552c347c6
17 changed files with 957 additions and 12 deletions

View file

@ -0,0 +1,387 @@
# 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}}"