Spaces:
Sleeping
Sleeping
| """Tests for Task API endpoints.""" | |
| import pytest | |
| from fastapi.testclient import TestClient | |
| from sqlmodel import Session | |
| from src.models.user import User | |
| from src.models.task import Task | |
| class TestTaskEndpoints: | |
| """Test suite for task CRUD operations.""" | |
| def test_create_task(self, client: TestClient, test_user: User): | |
| """Test creating a new task.""" | |
| response = client.post( | |
| "/api/tasks", | |
| json={"title": "New Task", "description": "New Description"} | |
| ) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["title"] == "New Task" | |
| assert data["description"] == "New Description" | |
| assert data["completed"] is False | |
| assert data["user_id"] == test_user.id | |
| assert "id" in data | |
| assert "created_at" in data | |
| assert "updated_at" in data | |
| def test_create_task_without_description(self, client: TestClient, test_user: User): | |
| """Test creating a task without description.""" | |
| response = client.post( | |
| "/api/tasks", | |
| json={"title": "Task Without Description"} | |
| ) | |
| assert response.status_code == 201 | |
| data = response.json() | |
| assert data["title"] == "Task Without Description" | |
| assert data["description"] is None | |
| def test_create_task_invalid_data(self, client: TestClient): | |
| """Test creating a task with invalid data.""" | |
| response = client.post( | |
| "/api/tasks", | |
| json={"description": "Missing title"} | |
| ) | |
| assert response.status_code == 422 | |
| def test_get_tasks(self, client: TestClient, test_task: Task): | |
| """Test getting all tasks.""" | |
| response = client.get("/api/tasks") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "tasks" in data | |
| assert "total" in data | |
| assert data["total"] >= 1 | |
| assert len(data["tasks"]) >= 1 | |
| def test_get_tasks_empty(self, client: TestClient, test_user: User): | |
| """Test getting tasks when none exist.""" | |
| response = client.get("/api/tasks") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["tasks"] == [] | |
| assert data["total"] == 0 | |
| def test_get_tasks_filter_completed(self, client: TestClient, session: Session, test_user: User): | |
| """Test filtering tasks by completion status.""" | |
| # Create completed and active tasks | |
| completed_task = Task( | |
| user_id=test_user.id, | |
| title="Completed Task", | |
| completed=True | |
| ) | |
| active_task = Task( | |
| user_id=test_user.id, | |
| title="Active Task", | |
| completed=False | |
| ) | |
| session.add(completed_task) | |
| session.add(active_task) | |
| session.commit() | |
| # Test filter for completed tasks | |
| response = client.get("/api/tasks?completed=true") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert all(task["completed"] for task in data["tasks"]) | |
| # Test filter for active tasks | |
| response = client.get("/api/tasks?completed=false") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert all(not task["completed"] for task in data["tasks"]) | |
| def test_get_tasks_sort_order(self, client: TestClient, session: Session, test_user: User): | |
| """Test sorting tasks.""" | |
| # Create multiple tasks | |
| for i in range(3): | |
| task = Task( | |
| user_id=test_user.id, | |
| title=f"Task {i}", | |
| completed=False | |
| ) | |
| session.add(task) | |
| session.commit() | |
| # Test descending order (newest first) | |
| response = client.get("/api/tasks?sort=created_at&order=desc") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| tasks = data["tasks"] | |
| assert len(tasks) >= 3 | |
| # Verify descending order | |
| for i in range(len(tasks) - 1): | |
| assert tasks[i]["created_at"] >= tasks[i + 1]["created_at"] | |
| # Test ascending order (oldest first) | |
| response = client.get("/api/tasks?sort=created_at&order=asc") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| tasks = data["tasks"] | |
| # Verify ascending order | |
| for i in range(len(tasks) - 1): | |
| assert tasks[i]["created_at"] <= tasks[i + 1]["created_at"] | |
| def test_get_single_task(self, client: TestClient, test_task: Task): | |
| """Test getting a single task by ID.""" | |
| response = client.get(f"/api/tasks/{test_task.id}") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["id"] == test_task.id | |
| assert data["title"] == test_task.title | |
| def test_get_nonexistent_task(self, client: TestClient): | |
| """Test getting a task that doesn't exist.""" | |
| response = client.get("/api/tasks/99999") | |
| assert response.status_code == 404 | |
| def test_update_task(self, client: TestClient, test_task: Task): | |
| """Test updating a task with PUT.""" | |
| response = client.put( | |
| f"/api/tasks/{test_task.id}", | |
| json={ | |
| "title": "Updated Title", | |
| "description": "Updated Description", | |
| "completed": True | |
| } | |
| ) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["title"] == "Updated Title" | |
| assert data["description"] == "Updated Description" | |
| assert data["completed"] is True | |
| def test_update_nonexistent_task(self, client: TestClient): | |
| """Test updating a task that doesn't exist.""" | |
| response = client.put( | |
| "/api/tasks/99999", | |
| json={ | |
| "title": "Updated", | |
| "description": "Updated", | |
| "completed": True | |
| } | |
| ) | |
| assert response.status_code == 404 | |
| def test_patch_task_title(self, client: TestClient, test_task: Task): | |
| """Test partially updating task title.""" | |
| original_description = test_task.description | |
| response = client.patch( | |
| f"/api/tasks/{test_task.id}", | |
| json={"title": "Patched Title"} | |
| ) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["title"] == "Patched Title" | |
| assert data["description"] == original_description | |
| assert data["completed"] == test_task.completed | |
| def test_patch_task_completion(self, client: TestClient, test_task: Task): | |
| """Test toggling task completion status.""" | |
| response = client.patch( | |
| f"/api/tasks/{test_task.id}", | |
| json={"completed": True} | |
| ) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["completed"] is True | |
| assert data["title"] == test_task.title | |
| def test_patch_nonexistent_task(self, client: TestClient): | |
| """Test patching a task that doesn't exist.""" | |
| response = client.patch( | |
| "/api/tasks/99999", | |
| json={"completed": True} | |
| ) | |
| assert response.status_code == 404 | |
| def test_delete_task(self, client: TestClient, test_task: Task): | |
| """Test deleting a task.""" | |
| task_id = test_task.id | |
| response = client.delete(f"/api/tasks/{task_id}") | |
| assert response.status_code == 204 | |
| # Verify task is deleted | |
| response = client.get(f"/api/tasks/{task_id}") | |
| assert response.status_code == 404 | |
| def test_delete_nonexistent_task(self, client: TestClient): | |
| """Test deleting a task that doesn't exist.""" | |
| response = client.delete("/api/tasks/99999") | |
| assert response.status_code == 404 | |
| def test_pagination(self, client: TestClient, session: Session, test_user: User): | |
| """Test pagination with limit and offset.""" | |
| # Create 10 tasks | |
| for i in range(10): | |
| task = Task( | |
| user_id=test_user.id, | |
| title=f"Task {i}", | |
| completed=False | |
| ) | |
| session.add(task) | |
| session.commit() | |
| # Test limit | |
| response = client.get("/api/tasks?limit=5") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert len(data["tasks"]) == 5 | |
| # Test offset | |
| response = client.get("/api/tasks?limit=5&offset=5") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert len(data["tasks"]) == 5 | |
| def test_task_timestamps(self, client: TestClient, test_task: Task): | |
| """Test that timestamps are properly set and updated.""" | |
| # Get initial timestamps | |
| response = client.get(f"/api/tasks/{test_task.id}") | |
| initial_data = response.json() | |
| initial_updated_at = initial_data["updated_at"] | |
| # Update task | |
| response = client.patch( | |
| f"/api/tasks/{test_task.id}", | |
| json={"title": "Updated Title"} | |
| ) | |
| assert response.status_code == 200 | |
| updated_data = response.json() | |
| # Verify updated_at changed | |
| assert updated_data["updated_at"] >= initial_updated_at | |
| assert updated_data["created_at"] == initial_data["created_at"] | |