test_maintenance_api.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. """Integration tests for Maintenance API endpoints."""
  2. import pytest
  3. from httpx import AsyncClient
  4. class TestMaintenanceTypesAPI:
  5. """Integration tests for /api/v1/maintenance/types endpoints."""
  6. @pytest.mark.asyncio
  7. @pytest.mark.integration
  8. async def test_list_maintenance_types(self, async_client: AsyncClient):
  9. """Verify maintenance types list returns data with defaults."""
  10. response = await async_client.get("/api/v1/maintenance/types")
  11. assert response.status_code == 200
  12. data = response.json()
  13. assert isinstance(data, list)
  14. # Should have default system types
  15. assert len(data) >= 1
  16. @pytest.mark.asyncio
  17. @pytest.mark.integration
  18. async def test_list_includes_system_types(self, async_client: AsyncClient):
  19. """Verify default system types are created."""
  20. response = await async_client.get("/api/v1/maintenance/types")
  21. assert response.status_code == 200
  22. data = response.json()
  23. names = [t["name"] for t in data]
  24. # Check for some default types
  25. assert "Lubricate Linear Rails" in names or len(data) > 0
  26. @pytest.mark.asyncio
  27. @pytest.mark.integration
  28. async def test_create_custom_maintenance_type(self, async_client: AsyncClient):
  29. """Verify custom maintenance type can be created."""
  30. data = {
  31. "name": "Custom Test Task",
  32. "description": "Test description",
  33. "default_interval_hours": 200.0,
  34. "interval_type": "hours",
  35. "icon": "Wrench",
  36. }
  37. response = await async_client.post("/api/v1/maintenance/types", json=data)
  38. assert response.status_code == 200
  39. result = response.json()
  40. assert result["name"] == "Custom Test Task"
  41. assert result["is_system"] is False
  42. @pytest.mark.asyncio
  43. @pytest.mark.integration
  44. async def test_update_maintenance_type(self, async_client: AsyncClient):
  45. """Verify maintenance type can be updated."""
  46. # First create a custom type
  47. create_data = {
  48. "name": "Update Test",
  49. "description": "Original",
  50. "default_interval_hours": 100.0,
  51. }
  52. create_response = await async_client.post("/api/v1/maintenance/types", json=create_data)
  53. assert create_response.status_code == 200
  54. type_id = create_response.json()["id"]
  55. # Update it
  56. update_data = {"description": "Updated description"}
  57. response = await async_client.patch(f"/api/v1/maintenance/types/{type_id}", json=update_data)
  58. assert response.status_code == 200
  59. assert response.json()["description"] == "Updated description"
  60. @pytest.mark.asyncio
  61. @pytest.mark.integration
  62. async def test_delete_custom_maintenance_type(self, async_client: AsyncClient):
  63. """Verify custom maintenance type can be deleted."""
  64. # Create a custom type
  65. create_data = {
  66. "name": "Delete Test",
  67. "description": "To be deleted",
  68. "default_interval_hours": 50.0,
  69. }
  70. create_response = await async_client.post("/api/v1/maintenance/types", json=create_data)
  71. type_id = create_response.json()["id"]
  72. # Delete it
  73. response = await async_client.delete(f"/api/v1/maintenance/types/{type_id}")
  74. assert response.status_code == 200
  75. class TestPrinterMaintenanceAPI:
  76. """Integration tests for /api/v1/maintenance/printers endpoints."""
  77. @pytest.mark.asyncio
  78. @pytest.mark.integration
  79. async def test_get_printer_maintenance_not_found(self, async_client: AsyncClient):
  80. """Verify 404 for non-existent printer."""
  81. response = await async_client.get("/api/v1/maintenance/printers/9999")
  82. assert response.status_code == 404
  83. @pytest.mark.asyncio
  84. @pytest.mark.integration
  85. async def test_get_printer_maintenance(self, async_client: AsyncClient, printer_factory, db_session):
  86. """Verify maintenance overview for a printer."""
  87. printer = await printer_factory(name="Maintenance Test Printer")
  88. response = await async_client.get(f"/api/v1/maintenance/printers/{printer.id}")
  89. assert response.status_code == 200
  90. data = response.json()
  91. assert data["printer_id"] == printer.id
  92. assert data["printer_name"] == "Maintenance Test Printer"
  93. assert "maintenance_items" in data
  94. assert "total_print_hours" in data
  95. @pytest.mark.asyncio
  96. @pytest.mark.integration
  97. async def test_get_all_maintenance_overview(self, async_client: AsyncClient, printer_factory, db_session):
  98. """Verify overview endpoint returns all printers."""
  99. await printer_factory(name="Overview Printer 1")
  100. await printer_factory(name="Overview Printer 2")
  101. response = await async_client.get("/api/v1/maintenance/overview")
  102. assert response.status_code == 200
  103. data = response.json()
  104. assert isinstance(data, list)
  105. @pytest.mark.asyncio
  106. @pytest.mark.integration
  107. async def test_get_maintenance_summary(self, async_client: AsyncClient):
  108. """Verify summary endpoint returns counts."""
  109. response = await async_client.get("/api/v1/maintenance/summary")
  110. assert response.status_code == 200
  111. data = response.json()
  112. assert "total_due" in data
  113. assert "total_warning" in data
  114. assert "printers_with_issues" in data
  115. class TestMaintenanceItemsAPI:
  116. """Integration tests for /api/v1/maintenance/items endpoints."""
  117. @pytest.fixture
  118. async def maintenance_item(self, async_client: AsyncClient, printer_factory, db_session):
  119. """Create a maintenance item for testing."""
  120. printer = await printer_factory(name="Item Test Printer")
  121. # Get the printer's maintenance overview to create items
  122. response = await async_client.get(f"/api/v1/maintenance/printers/{printer.id}")
  123. assert response.status_code == 200
  124. data = response.json()
  125. # Return the first maintenance item
  126. if data["maintenance_items"]:
  127. return data["maintenance_items"][0]
  128. return None
  129. @pytest.mark.asyncio
  130. @pytest.mark.integration
  131. async def test_update_maintenance_item(self, async_client: AsyncClient, maintenance_item):
  132. """Verify maintenance item can be updated."""
  133. if not maintenance_item:
  134. pytest.skip("No maintenance items available")
  135. item_id = maintenance_item["id"]
  136. response = await async_client.patch(
  137. f"/api/v1/maintenance/items/{item_id}", json={"custom_interval_hours": 150.0}
  138. )
  139. assert response.status_code == 200
  140. @pytest.mark.asyncio
  141. @pytest.mark.integration
  142. async def test_disable_maintenance_item(self, async_client: AsyncClient, maintenance_item):
  143. """Verify maintenance item can be disabled."""
  144. if not maintenance_item:
  145. pytest.skip("No maintenance items available")
  146. item_id = maintenance_item["id"]
  147. response = await async_client.patch(f"/api/v1/maintenance/items/{item_id}", json={"enabled": False})
  148. assert response.status_code == 200
  149. assert response.json()["enabled"] is False
  150. @pytest.mark.asyncio
  151. @pytest.mark.integration
  152. async def test_perform_maintenance(self, async_client: AsyncClient, maintenance_item):
  153. """Verify maintenance can be marked as performed."""
  154. if not maintenance_item:
  155. pytest.skip("No maintenance items available")
  156. item_id = maintenance_item["id"]
  157. response = await async_client.post(
  158. f"/api/v1/maintenance/items/{item_id}/perform", json={"notes": "Test maintenance performed"}
  159. )
  160. assert response.status_code == 200
  161. data = response.json()
  162. assert data["last_performed_at"] is not None
  163. @pytest.mark.asyncio
  164. @pytest.mark.integration
  165. async def test_get_maintenance_history(self, async_client: AsyncClient, maintenance_item):
  166. """Verify maintenance history can be retrieved."""
  167. if not maintenance_item:
  168. pytest.skip("No maintenance items available")
  169. item_id = maintenance_item["id"]
  170. # First perform maintenance to create history
  171. await async_client.post(f"/api/v1/maintenance/items/{item_id}/perform", json={"notes": "History test"})
  172. response = await async_client.get(f"/api/v1/maintenance/items/{item_id}/history")
  173. assert response.status_code == 200
  174. history = response.json()
  175. assert isinstance(history, list)
  176. @pytest.mark.asyncio
  177. @pytest.mark.integration
  178. async def test_update_maintenance_item_not_found(self, async_client: AsyncClient):
  179. """Verify 404 for non-existent maintenance item."""
  180. response = await async_client.patch("/api/v1/maintenance/items/9999", json={"enabled": False})
  181. assert response.status_code == 404
  182. class TestPrinterHoursAPI:
  183. """Integration tests for /api/v1/maintenance/printers/{id}/hours endpoint."""
  184. @pytest.mark.asyncio
  185. @pytest.mark.integration
  186. async def test_set_printer_hours(self, async_client: AsyncClient, printer_factory, db_session):
  187. """Verify printer hours can be set."""
  188. printer = await printer_factory(name="Hours Test Printer")
  189. response = await async_client.patch(
  190. f"/api/v1/maintenance/printers/{printer.id}/hours", params={"total_hours": 500.0}
  191. )
  192. assert response.status_code == 200
  193. data = response.json()
  194. assert data["total_hours"] == 500.0
  195. @pytest.mark.asyncio
  196. @pytest.mark.integration
  197. async def test_set_printer_hours_not_found(self, async_client: AsyncClient):
  198. """Verify 404 for non-existent printer."""
  199. response = await async_client.patch("/api/v1/maintenance/printers/9999/hours", params={"total_hours": 100.0})
  200. assert response.status_code == 404