test_maintenance_api.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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(
  53. "/api/v1/maintenance/types", json=create_data
  54. )
  55. assert create_response.status_code == 200
  56. type_id = create_response.json()["id"]
  57. # Update it
  58. update_data = {"description": "Updated description"}
  59. response = await async_client.patch(
  60. f"/api/v1/maintenance/types/{type_id}", json=update_data
  61. )
  62. assert response.status_code == 200
  63. assert response.json()["description"] == "Updated description"
  64. @pytest.mark.asyncio
  65. @pytest.mark.integration
  66. async def test_delete_custom_maintenance_type(self, async_client: AsyncClient):
  67. """Verify custom maintenance type can be deleted."""
  68. # Create a custom type
  69. create_data = {
  70. "name": "Delete Test",
  71. "description": "To be deleted",
  72. "default_interval_hours": 50.0,
  73. }
  74. create_response = await async_client.post(
  75. "/api/v1/maintenance/types", json=create_data
  76. )
  77. type_id = create_response.json()["id"]
  78. # Delete it
  79. response = await async_client.delete(f"/api/v1/maintenance/types/{type_id}")
  80. assert response.status_code == 200
  81. class TestPrinterMaintenanceAPI:
  82. """Integration tests for /api/v1/maintenance/printers endpoints."""
  83. @pytest.mark.asyncio
  84. @pytest.mark.integration
  85. async def test_get_printer_maintenance_not_found(self, async_client: AsyncClient):
  86. """Verify 404 for non-existent printer."""
  87. response = await async_client.get("/api/v1/maintenance/printers/9999")
  88. assert response.status_code == 404
  89. @pytest.mark.asyncio
  90. @pytest.mark.integration
  91. async def test_get_printer_maintenance(
  92. self, async_client: AsyncClient, printer_factory, db_session
  93. ):
  94. """Verify maintenance overview for a printer."""
  95. printer = await printer_factory(name="Maintenance Test Printer")
  96. response = await async_client.get(f"/api/v1/maintenance/printers/{printer.id}")
  97. assert response.status_code == 200
  98. data = response.json()
  99. assert data["printer_id"] == printer.id
  100. assert data["printer_name"] == "Maintenance Test Printer"
  101. assert "maintenance_items" in data
  102. assert "total_print_hours" in data
  103. @pytest.mark.asyncio
  104. @pytest.mark.integration
  105. async def test_get_all_maintenance_overview(
  106. self, async_client: AsyncClient, printer_factory, db_session
  107. ):
  108. """Verify overview endpoint returns all printers."""
  109. await printer_factory(name="Overview Printer 1")
  110. await printer_factory(name="Overview Printer 2")
  111. response = await async_client.get("/api/v1/maintenance/overview")
  112. assert response.status_code == 200
  113. data = response.json()
  114. assert isinstance(data, list)
  115. @pytest.mark.asyncio
  116. @pytest.mark.integration
  117. async def test_get_maintenance_summary(self, async_client: AsyncClient):
  118. """Verify summary endpoint returns counts."""
  119. response = await async_client.get("/api/v1/maintenance/summary")
  120. assert response.status_code == 200
  121. data = response.json()
  122. assert "total_due" in data
  123. assert "total_warning" in data
  124. assert "printers_with_issues" in data
  125. class TestMaintenanceItemsAPI:
  126. """Integration tests for /api/v1/maintenance/items endpoints."""
  127. @pytest.fixture
  128. async def maintenance_item(self, async_client: AsyncClient, printer_factory, db_session):
  129. """Create a maintenance item for testing."""
  130. printer = await printer_factory(name="Item Test Printer")
  131. # Get the printer's maintenance overview to create items
  132. response = await async_client.get(f"/api/v1/maintenance/printers/{printer.id}")
  133. assert response.status_code == 200
  134. data = response.json()
  135. # Return the first maintenance item
  136. if data["maintenance_items"]:
  137. return data["maintenance_items"][0]
  138. return None
  139. @pytest.mark.asyncio
  140. @pytest.mark.integration
  141. async def test_update_maintenance_item(
  142. self, async_client: AsyncClient, maintenance_item
  143. ):
  144. """Verify maintenance item can be updated."""
  145. if not maintenance_item:
  146. pytest.skip("No maintenance items available")
  147. item_id = maintenance_item["id"]
  148. response = await async_client.patch(
  149. f"/api/v1/maintenance/items/{item_id}",
  150. json={"custom_interval_hours": 150.0}
  151. )
  152. assert response.status_code == 200
  153. @pytest.mark.asyncio
  154. @pytest.mark.integration
  155. async def test_disable_maintenance_item(
  156. self, async_client: AsyncClient, maintenance_item
  157. ):
  158. """Verify maintenance item can be disabled."""
  159. if not maintenance_item:
  160. pytest.skip("No maintenance items available")
  161. item_id = maintenance_item["id"]
  162. response = await async_client.patch(
  163. f"/api/v1/maintenance/items/{item_id}",
  164. json={"enabled": False}
  165. )
  166. assert response.status_code == 200
  167. assert response.json()["enabled"] is False
  168. @pytest.mark.asyncio
  169. @pytest.mark.integration
  170. async def test_perform_maintenance(
  171. self, async_client: AsyncClient, maintenance_item
  172. ):
  173. """Verify maintenance can be marked as performed."""
  174. if not maintenance_item:
  175. pytest.skip("No maintenance items available")
  176. item_id = maintenance_item["id"]
  177. response = await async_client.post(
  178. f"/api/v1/maintenance/items/{item_id}/perform",
  179. json={"notes": "Test maintenance performed"}
  180. )
  181. assert response.status_code == 200
  182. data = response.json()
  183. assert data["last_performed_at"] is not None
  184. @pytest.mark.asyncio
  185. @pytest.mark.integration
  186. async def test_get_maintenance_history(
  187. self, async_client: AsyncClient, maintenance_item
  188. ):
  189. """Verify maintenance history can be retrieved."""
  190. if not maintenance_item:
  191. pytest.skip("No maintenance items available")
  192. item_id = maintenance_item["id"]
  193. # First perform maintenance to create history
  194. await async_client.post(
  195. f"/api/v1/maintenance/items/{item_id}/perform",
  196. json={"notes": "History test"}
  197. )
  198. response = await async_client.get(f"/api/v1/maintenance/items/{item_id}/history")
  199. assert response.status_code == 200
  200. history = response.json()
  201. assert isinstance(history, list)
  202. @pytest.mark.asyncio
  203. @pytest.mark.integration
  204. async def test_update_maintenance_item_not_found(self, async_client: AsyncClient):
  205. """Verify 404 for non-existent maintenance item."""
  206. response = await async_client.patch(
  207. "/api/v1/maintenance/items/9999",
  208. json={"enabled": False}
  209. )
  210. assert response.status_code == 404
  211. class TestPrinterHoursAPI:
  212. """Integration tests for /api/v1/maintenance/printers/{id}/hours endpoint."""
  213. @pytest.mark.asyncio
  214. @pytest.mark.integration
  215. async def test_set_printer_hours(
  216. self, async_client: AsyncClient, printer_factory, db_session
  217. ):
  218. """Verify printer hours can be set."""
  219. printer = await printer_factory(name="Hours Test Printer")
  220. response = await async_client.patch(
  221. f"/api/v1/maintenance/printers/{printer.id}/hours",
  222. params={"total_hours": 500.0}
  223. )
  224. assert response.status_code == 200
  225. data = response.json()
  226. assert data["total_hours"] == 500.0
  227. @pytest.mark.asyncio
  228. @pytest.mark.integration
  229. async def test_set_printer_hours_not_found(self, async_client: AsyncClient):
  230. """Verify 404 for non-existent printer."""
  231. response = await async_client.patch(
  232. "/api/v1/maintenance/printers/9999/hours",
  233. params={"total_hours": 100.0}
  234. )
  235. assert response.status_code == 404