"""Tests for the Task Queue API endpoints. Verifies task CRUD operations and the dashboard page rendering. """ import sqlite3 from unittest.mock import patch # --------------------------------------------------------------------------- # DB error handling tests # --------------------------------------------------------------------------- _DB_ERROR = sqlite3.OperationalError("database is locked") def test_tasks_page_degrades_on_db_error(client): """GET /tasks renders empty columns when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/tasks") assert response.status_code == 200 assert "TASK QUEUE" in response.text def test_pending_partial_degrades_on_db_error(client): """GET /tasks/pending returns fallback HTML when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/tasks/pending") assert response.status_code == 200 assert "Database unavailable" in response.text def test_active_partial_degrades_on_db_error(client): """GET /tasks/active returns fallback HTML when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/tasks/active") assert response.status_code == 200 assert "Database unavailable" in response.text def test_completed_partial_degrades_on_db_error(client): """GET /tasks/completed returns fallback HTML when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/tasks/completed") assert response.status_code == 200 assert "Database unavailable" in response.text def test_api_create_task_503_on_db_error(client): """POST /api/tasks returns 503 when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.post("/api/tasks", json={"title": "Test"}) assert response.status_code == 503 def test_api_list_tasks_empty_on_db_error(client): """GET /api/tasks returns empty list when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/api/tasks") assert response.status_code == 200 assert response.json() == [] def test_queue_status_degrades_on_db_error(client): """GET /api/queue/status returns idle status when DB is unavailable.""" with patch( "dashboard.routes.tasks._get_db", side_effect=_DB_ERROR, ): response = client.get("/api/queue/status") assert response.status_code == 200 data = response.json() assert data["is_working"] is False assert data["current_task"] is None # --------------------------------------------------------------------------- # Existing tests # --------------------------------------------------------------------------- def test_tasks_page_returns_200(client): response = client.get("/tasks") assert response.status_code == 200 assert "TASK QUEUE" in response.text def test_create_task(client): """POST /api/tasks returns 201 with task JSON.""" response = client.post( "/api/tasks", json={ "title": "Fix the memory bug", "priority": "high", }, ) assert response.status_code == 201 data = response.json() assert data["title"] == "Fix the memory bug" assert data["priority"] == "high" assert data["status"] == "pending_approval" assert "id" in data def test_list_tasks(client): """GET /api/tasks returns JSON array.""" response = client.get("/api/tasks") assert response.status_code == 200 assert isinstance(response.json(), list) def test_create_and_list_roundtrip(client): """Creating a task makes it appear in the list.""" client.post("/api/tasks", json={"title": "Roundtrip test"}) response = client.get("/api/tasks") tasks = response.json() assert any(t["title"] == "Roundtrip test" for t in tasks) def test_update_task_status(client): """PATCH /api/tasks/{id}/status updates the task.""" create = client.post("/api/tasks", json={"title": "To approve"}) task_id = create.json()["id"] response = client.patch( f"/api/tasks/{task_id}/status", json={"status": "approved"}, ) assert response.status_code == 200 assert response.json()["status"] == "approved" def test_delete_task(client): """DELETE /api/tasks/{id} removes the task.""" create = client.post("/api/tasks", json={"title": "To delete"}) task_id = create.json()["id"] response = client.delete(f"/api/tasks/{task_id}") assert response.status_code == 200 # Verify it's gone tasks = client.get("/api/tasks").json() assert not any(t["id"] == task_id for t in tasks) def test_create_task_missing_title_422(client): """POST /api/tasks without title returns 422.""" response = client.post("/api/tasks", json={"priority": "high"}) assert response.status_code == 422 def test_create_task_via_form(client): """POST /tasks/create via form creates and returns task card HTML.""" response = client.post( "/tasks/create", data={ "title": "Form task", "description": "Created via form", "priority": "normal", "assigned_to": "", }, ) assert response.status_code == 200 assert "Form task" in response.text def test_pending_partial(client): """GET /tasks/pending returns HTML partial.""" client.post("/api/tasks", json={"title": "Pending task"}) response = client.get("/tasks/pending") assert response.status_code == 200 assert "Pending task" in response.text