test_printers_api.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. """Integration tests for Printers API endpoints.
  2. Tests the full request/response cycle for /api/v1/printers/ endpoints.
  3. """
  4. import pytest
  5. from httpx import AsyncClient
  6. from unittest.mock import patch, MagicMock, AsyncMock
  7. class TestPrintersAPI:
  8. """Integration tests for /api/v1/printers/ endpoints."""
  9. # ========================================================================
  10. # List endpoints
  11. # ========================================================================
  12. @pytest.mark.asyncio
  13. @pytest.mark.integration
  14. async def test_list_printers_empty(self, async_client: AsyncClient):
  15. """Verify empty list is returned when no printers exist."""
  16. response = await async_client.get("/api/v1/printers/")
  17. assert response.status_code == 200
  18. assert response.json() == []
  19. @pytest.mark.asyncio
  20. @pytest.mark.integration
  21. async def test_list_printers_with_data(
  22. self, async_client: AsyncClient, printer_factory, db_session
  23. ):
  24. """Verify list returns existing printers."""
  25. printer = await printer_factory(name="Test Printer")
  26. response = await async_client.get("/api/v1/printers/")
  27. assert response.status_code == 200
  28. data = response.json()
  29. assert len(data) >= 1
  30. assert any(p["name"] == "Test Printer" for p in data)
  31. # ========================================================================
  32. # Create endpoints
  33. # ========================================================================
  34. @pytest.mark.asyncio
  35. @pytest.mark.integration
  36. async def test_create_printer(self, async_client: AsyncClient):
  37. """Verify printer can be created."""
  38. data = {
  39. "name": "New Printer",
  40. "serial_number": "00M09A111111111",
  41. "ip_address": "192.168.1.100",
  42. "access_code": "12345678",
  43. "is_active": True,
  44. "model": "X1C",
  45. }
  46. response = await async_client.post("/api/v1/printers/", json=data)
  47. assert response.status_code == 200
  48. result = response.json()
  49. assert result["name"] == "New Printer"
  50. assert result["serial_number"] == "00M09A111111111"
  51. assert result["model"] == "X1C"
  52. @pytest.mark.asyncio
  53. @pytest.mark.integration
  54. async def test_create_printer_duplicate_serial(
  55. self, async_client: AsyncClient, printer_factory, db_session
  56. ):
  57. """Verify duplicate serial number is rejected."""
  58. await printer_factory(serial_number="00M09A222222222")
  59. data = {
  60. "name": "Duplicate Printer",
  61. "serial_number": "00M09A222222222",
  62. "ip_address": "192.168.1.101",
  63. "access_code": "12345678",
  64. }
  65. response = await async_client.post("/api/v1/printers/", json=data)
  66. # Should fail due to duplicate serial
  67. assert response.status_code in [400, 409, 422, 500]
  68. # ========================================================================
  69. # Get single endpoint
  70. # ========================================================================
  71. @pytest.mark.asyncio
  72. @pytest.mark.integration
  73. async def test_get_printer(
  74. self, async_client: AsyncClient, printer_factory, db_session
  75. ):
  76. """Verify single printer can be retrieved."""
  77. printer = await printer_factory(name="Get Test Printer")
  78. response = await async_client.get(f"/api/v1/printers/{printer.id}")
  79. assert response.status_code == 200
  80. result = response.json()
  81. assert result["id"] == printer.id
  82. assert result["name"] == "Get Test Printer"
  83. @pytest.mark.asyncio
  84. @pytest.mark.integration
  85. async def test_get_printer_not_found(self, async_client: AsyncClient):
  86. """Verify 404 for non-existent printer."""
  87. response = await async_client.get("/api/v1/printers/9999")
  88. assert response.status_code == 404
  89. # ========================================================================
  90. # Update endpoints
  91. # ========================================================================
  92. @pytest.mark.asyncio
  93. @pytest.mark.integration
  94. async def test_update_printer_name(
  95. self, async_client: AsyncClient, printer_factory, db_session
  96. ):
  97. """Verify printer name can be updated."""
  98. printer = await printer_factory(name="Original Name")
  99. response = await async_client.patch(
  100. f"/api/v1/printers/{printer.id}",
  101. json={"name": "Updated Name"}
  102. )
  103. assert response.status_code == 200
  104. assert response.json()["name"] == "Updated Name"
  105. @pytest.mark.asyncio
  106. @pytest.mark.integration
  107. async def test_update_printer_active_status(
  108. self, async_client: AsyncClient, printer_factory, db_session
  109. ):
  110. """Verify printer active status can be updated."""
  111. printer = await printer_factory(is_active=True)
  112. response = await async_client.patch(
  113. f"/api/v1/printers/{printer.id}",
  114. json={"is_active": False}
  115. )
  116. assert response.status_code == 200
  117. assert response.json()["is_active"] is False
  118. @pytest.mark.asyncio
  119. @pytest.mark.integration
  120. async def test_update_printer_auto_archive(
  121. self, async_client: AsyncClient, printer_factory, db_session
  122. ):
  123. """Verify auto_archive setting can be updated."""
  124. printer = await printer_factory(auto_archive=True)
  125. response = await async_client.patch(
  126. f"/api/v1/printers/{printer.id}",
  127. json={"auto_archive": False}
  128. )
  129. assert response.status_code == 200
  130. assert response.json()["auto_archive"] is False
  131. @pytest.mark.asyncio
  132. @pytest.mark.integration
  133. async def test_update_nonexistent_printer(self, async_client: AsyncClient):
  134. """Verify updating non-existent printer returns 404."""
  135. response = await async_client.patch(
  136. "/api/v1/printers/9999",
  137. json={"name": "New Name"}
  138. )
  139. assert response.status_code == 404
  140. # ========================================================================
  141. # Delete endpoints
  142. # ========================================================================
  143. @pytest.mark.asyncio
  144. @pytest.mark.integration
  145. async def test_delete_printer(
  146. self, async_client: AsyncClient, printer_factory, db_session
  147. ):
  148. """Verify printer can be deleted."""
  149. printer = await printer_factory()
  150. printer_id = printer.id
  151. response = await async_client.delete(f"/api/v1/printers/{printer_id}")
  152. assert response.status_code == 200
  153. # Verify deleted
  154. response = await async_client.get(f"/api/v1/printers/{printer_id}")
  155. assert response.status_code == 404
  156. @pytest.mark.asyncio
  157. @pytest.mark.integration
  158. async def test_delete_nonexistent_printer(self, async_client: AsyncClient):
  159. """Verify deleting non-existent printer returns 404."""
  160. response = await async_client.delete("/api/v1/printers/9999")
  161. assert response.status_code == 404
  162. # ========================================================================
  163. # Status endpoint
  164. # ========================================================================
  165. @pytest.mark.asyncio
  166. @pytest.mark.integration
  167. async def test_get_printer_status(
  168. self, async_client: AsyncClient, printer_factory, mock_printer_manager, db_session
  169. ):
  170. """Verify printer status can be retrieved."""
  171. printer = await printer_factory()
  172. response = await async_client.get(f"/api/v1/printers/{printer.id}/status")
  173. assert response.status_code == 200
  174. result = response.json()
  175. assert "connected" in result
  176. assert "state" in result
  177. @pytest.mark.asyncio
  178. @pytest.mark.integration
  179. async def test_get_printer_status_not_found(self, async_client: AsyncClient):
  180. """Verify 404 for status of non-existent printer."""
  181. response = await async_client.get("/api/v1/printers/9999/status")
  182. assert response.status_code == 404
  183. # ========================================================================
  184. # Test connection endpoint
  185. # ========================================================================
  186. class TestPrinterDataIntegrity:
  187. """Tests for printer data integrity."""
  188. @pytest.mark.asyncio
  189. @pytest.mark.integration
  190. async def test_printer_stores_all_fields(
  191. self, async_client: AsyncClient, printer_factory, db_session
  192. ):
  193. """Verify printer stores all fields correctly."""
  194. printer = await printer_factory(
  195. name="Full Test Printer",
  196. serial_number="00M09A444444444",
  197. ip_address="192.168.1.150",
  198. model="P1S",
  199. is_active=True,
  200. auto_archive=False,
  201. )
  202. response = await async_client.get(f"/api/v1/printers/{printer.id}")
  203. assert response.status_code == 200
  204. result = response.json()
  205. assert result["name"] == "Full Test Printer"
  206. assert result["serial_number"] == "00M09A444444444"
  207. assert result["ip_address"] == "192.168.1.150"
  208. assert result["model"] == "P1S"
  209. assert result["is_active"] is True
  210. assert result["auto_archive"] is False
  211. @pytest.mark.asyncio
  212. @pytest.mark.integration
  213. async def test_printer_update_persists(
  214. self, async_client: AsyncClient, printer_factory, db_session
  215. ):
  216. """CRITICAL: Verify printer updates persist."""
  217. printer = await printer_factory(name="Original", is_active=True)
  218. # Update
  219. await async_client.patch(
  220. f"/api/v1/printers/{printer.id}",
  221. json={"name": "Updated", "is_active": False}
  222. )
  223. # Verify persistence
  224. response = await async_client.get(f"/api/v1/printers/{printer.id}")
  225. result = response.json()
  226. assert result["name"] == "Updated"
  227. assert result["is_active"] is False