test_project_api.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. """
  2. Unit tests for Project API endpoints.
  3. Tests CRUD operations for projects.
  4. """
  5. import pytest
  6. import os
  7. import sqlite3
  8. from fastapi.testclient import TestClient
  9. # Use a test database
  10. TEST_DB_PATH = "test_annotation_platform.db"
  11. @pytest.fixture(scope="function", autouse=True)
  12. def setup_test_db():
  13. """Setup test database before each test and cleanup after."""
  14. # Set test database path
  15. original_db_path = os.environ.get("DATABASE_PATH")
  16. os.environ["DATABASE_PATH"] = TEST_DB_PATH
  17. # Remove existing test database
  18. if os.path.exists(TEST_DB_PATH):
  19. os.remove(TEST_DB_PATH)
  20. # Import after setting env var
  21. from database import init_database
  22. init_database()
  23. yield
  24. # Cleanup
  25. if os.path.exists(TEST_DB_PATH):
  26. os.remove(TEST_DB_PATH)
  27. # Restore original path
  28. if original_db_path:
  29. os.environ["DATABASE_PATH"] = original_db_path
  30. elif "DATABASE_PATH" in os.environ:
  31. del os.environ["DATABASE_PATH"]
  32. @pytest.fixture(scope="function")
  33. def test_client():
  34. """Create a test client."""
  35. from main import app
  36. return TestClient(app)
  37. def test_list_projects_empty(test_client):
  38. """Test listing projects when database is empty."""
  39. response = test_client.get("/api/projects")
  40. assert response.status_code == 200
  41. assert response.json() == []
  42. def test_create_project(test_client):
  43. """Test creating a new project."""
  44. project_data = {
  45. "name": "Test Project",
  46. "description": "Test Description",
  47. "config": "<View><Image name='img' value='$image'/></View>"
  48. }
  49. response = test_client.post("/api/projects", json=project_data)
  50. assert response.status_code == 201
  51. data = response.json()
  52. assert data["name"] == project_data["name"]
  53. assert data["description"] == project_data["description"]
  54. assert data["config"] == project_data["config"]
  55. assert "id" in data
  56. assert data["id"].startswith("proj_")
  57. assert data["task_count"] == 0
  58. assert "created_at" in data
  59. def test_create_project_empty_name(test_client):
  60. """Test creating a project with empty name fails validation."""
  61. project_data = {
  62. "name": "",
  63. "description": "Test Description",
  64. "config": "<View></View>"
  65. }
  66. response = test_client.post("/api/projects", json=project_data)
  67. assert response.status_code == 422 # Validation error
  68. def test_get_project(test_client):
  69. """Test getting a project by ID."""
  70. # Create a project first
  71. project_data = {
  72. "name": "Test Project",
  73. "description": "Test Description",
  74. "config": "<View></View>"
  75. }
  76. create_response = test_client.post("/api/projects", json=project_data)
  77. project_id = create_response.json()["id"]
  78. # Get the project
  79. response = test_client.get(f"/api/projects/{project_id}")
  80. assert response.status_code == 200
  81. data = response.json()
  82. assert data["id"] == project_id
  83. assert data["name"] == project_data["name"]
  84. def test_get_project_not_found(test_client):
  85. """Test getting a non-existent project returns 404."""
  86. response = test_client.get("/api/projects/nonexistent_id")
  87. assert response.status_code == 404
  88. assert "not found" in response.json()["detail"].lower()
  89. def test_update_project(test_client):
  90. """Test updating a project."""
  91. # Create a project first
  92. project_data = {
  93. "name": "Original Name",
  94. "description": "Original Description",
  95. "config": "<View></View>"
  96. }
  97. create_response = test_client.post("/api/projects", json=project_data)
  98. project_id = create_response.json()["id"]
  99. # Update the project
  100. update_data = {
  101. "name": "Updated Name",
  102. "description": "Updated Description"
  103. }
  104. response = test_client.put(f"/api/projects/{project_id}", json=update_data)
  105. assert response.status_code == 200
  106. data = response.json()
  107. assert data["name"] == update_data["name"]
  108. assert data["description"] == update_data["description"]
  109. assert data["config"] == project_data["config"] # Config unchanged
  110. def test_update_project_not_found(test_client):
  111. """Test updating a non-existent project returns 404."""
  112. update_data = {"name": "Updated Name"}
  113. response = test_client.put("/api/projects/nonexistent_id", json=update_data)
  114. assert response.status_code == 404
  115. def test_delete_project(test_client):
  116. """Test deleting a project."""
  117. # Create a project first
  118. project_data = {
  119. "name": "Test Project",
  120. "description": "Test Description",
  121. "config": "<View></View>"
  122. }
  123. create_response = test_client.post("/api/projects", json=project_data)
  124. project_id = create_response.json()["id"]
  125. # Delete the project
  126. response = test_client.delete(f"/api/projects/{project_id}")
  127. assert response.status_code == 204
  128. # Verify project is deleted
  129. get_response = test_client.get(f"/api/projects/{project_id}")
  130. assert get_response.status_code == 404
  131. def test_delete_project_not_found(test_client):
  132. """Test deleting a non-existent project returns 404."""
  133. response = test_client.delete("/api/projects/nonexistent_id")
  134. assert response.status_code == 404
  135. def test_list_projects_after_creation(test_client):
  136. """Test listing projects after creating some."""
  137. # Create multiple projects
  138. for i in range(3):
  139. project_data = {
  140. "name": f"Project {i}",
  141. "description": f"Description {i}",
  142. "config": "<View></View>"
  143. }
  144. test_client.post("/api/projects", json=project_data)
  145. # List projects
  146. response = test_client.get("/api/projects")
  147. assert response.status_code == 200
  148. data = response.json()
  149. assert len(data) == 3
  150. assert all("id" in project for project in data)
  151. assert all("task_count" in project for project in data)