test_ams_history_api.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. """Integration tests for AMS History API endpoints."""
  2. import pytest
  3. from datetime import datetime, timedelta
  4. from httpx import AsyncClient
  5. class TestAMSHistoryAPI:
  6. """Integration tests for /api/v1/ams-history endpoints."""
  7. @pytest.fixture
  8. async def ams_history_factory(self, db_session, printer_factory):
  9. """Factory to create test AMS history records."""
  10. async def _create_history(printer_id=None, ams_id=0, **kwargs):
  11. from backend.app.models.ams_history import AMSSensorHistory
  12. if printer_id is None:
  13. printer = await printer_factory()
  14. printer_id = printer.id
  15. defaults = {
  16. "printer_id": printer_id,
  17. "ams_id": ams_id,
  18. "humidity": 45.0,
  19. "humidity_raw": 4500,
  20. "temperature": 25.0,
  21. "recorded_at": datetime.now(),
  22. }
  23. defaults.update(kwargs)
  24. history = AMSSensorHistory(**defaults)
  25. db_session.add(history)
  26. await db_session.commit()
  27. await db_session.refresh(history)
  28. return history
  29. return _create_history
  30. @pytest.mark.asyncio
  31. @pytest.mark.integration
  32. async def test_get_ams_history_empty(
  33. self, async_client: AsyncClient, printer_factory, db_session
  34. ):
  35. """Verify empty history returns empty data array."""
  36. printer = await printer_factory()
  37. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  38. assert response.status_code == 200
  39. data = response.json()
  40. assert data["printer_id"] == printer.id
  41. assert data["ams_id"] == 0
  42. assert data["data"] == []
  43. @pytest.mark.asyncio
  44. @pytest.mark.integration
  45. async def test_get_ams_history_with_data(
  46. self, async_client: AsyncClient, ams_history_factory, db_session
  47. ):
  48. """Verify history returns recorded data."""
  49. # Create history records
  50. history = await ams_history_factory()
  51. printer_id = history.printer_id
  52. response = await async_client.get(f"/api/v1/ams-history/{printer_id}/0")
  53. assert response.status_code == 200
  54. data = response.json()
  55. assert len(data["data"]) >= 1
  56. @pytest.mark.asyncio
  57. @pytest.mark.integration
  58. async def test_get_ams_history_with_stats(
  59. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  60. ):
  61. """Verify history includes statistics."""
  62. printer = await printer_factory()
  63. # Create multiple records with different values
  64. await ams_history_factory(printer_id=printer.id, humidity=40.0, temperature=24.0)
  65. await ams_history_factory(printer_id=printer.id, humidity=50.0, temperature=26.0)
  66. await ams_history_factory(printer_id=printer.id, humidity=45.0, temperature=25.0)
  67. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  68. assert response.status_code == 200
  69. data = response.json()
  70. # Check statistics
  71. assert data["min_humidity"] == 40.0
  72. assert data["max_humidity"] == 50.0
  73. assert data["min_temperature"] == 24.0
  74. assert data["max_temperature"] == 26.0
  75. @pytest.mark.asyncio
  76. @pytest.mark.integration
  77. async def test_get_ams_history_with_hours_filter(
  78. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  79. ):
  80. """Verify hours parameter filters data."""
  81. printer = await printer_factory()
  82. # Create a recent record
  83. await ams_history_factory(
  84. printer_id=printer.id,
  85. recorded_at=datetime.now()
  86. )
  87. # Create an old record (outside default 24h)
  88. await ams_history_factory(
  89. printer_id=printer.id,
  90. recorded_at=datetime.now() - timedelta(hours=48)
  91. )
  92. # Request only last 24 hours (default)
  93. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  94. assert response.status_code == 200
  95. data = response.json()
  96. # Should only get the recent record
  97. assert len(data["data"]) == 1
  98. @pytest.mark.asyncio
  99. @pytest.mark.integration
  100. async def test_get_ams_history_custom_hours(
  101. self, async_client: AsyncClient, printer_factory, db_session
  102. ):
  103. """Verify custom hours parameter works."""
  104. printer = await printer_factory()
  105. response = await async_client.get(
  106. f"/api/v1/ams-history/{printer.id}/0",
  107. params={"hours": 48}
  108. )
  109. assert response.status_code == 200
  110. data = response.json()
  111. assert data["printer_id"] == printer.id
  112. @pytest.mark.asyncio
  113. @pytest.mark.integration
  114. async def test_get_ams_history_different_ams_units(
  115. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  116. ):
  117. """Verify filtering by AMS unit ID."""
  118. printer = await printer_factory()
  119. await ams_history_factory(printer_id=printer.id, ams_id=0, humidity=40.0)
  120. await ams_history_factory(printer_id=printer.id, ams_id=1, humidity=50.0)
  121. # Get AMS unit 0
  122. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  123. assert response.status_code == 200
  124. data0 = response.json()
  125. assert len(data0["data"]) == 1
  126. assert data0["data"][0]["humidity"] == 40.0
  127. # Get AMS unit 1
  128. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/1")
  129. assert response.status_code == 200
  130. data1 = response.json()
  131. assert len(data1["data"]) == 1
  132. assert data1["data"][0]["humidity"] == 50.0
  133. @pytest.mark.asyncio
  134. @pytest.mark.integration
  135. async def test_delete_old_history(
  136. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  137. ):
  138. """Verify old history can be deleted."""
  139. printer = await printer_factory()
  140. # Create an old record
  141. await ams_history_factory(
  142. printer_id=printer.id,
  143. recorded_at=datetime.now() - timedelta(days=60)
  144. )
  145. # Delete records older than 30 days
  146. response = await async_client.delete(
  147. f"/api/v1/ams-history/{printer.id}",
  148. params={"days": 30}
  149. )
  150. assert response.status_code == 200
  151. data = response.json()
  152. assert data["deleted"] >= 1
  153. @pytest.mark.asyncio
  154. @pytest.mark.integration
  155. async def test_delete_old_history_no_records(
  156. self, async_client: AsyncClient, printer_factory, db_session
  157. ):
  158. """Verify delete with no old records returns 0."""
  159. printer = await printer_factory()
  160. response = await async_client.delete(
  161. f"/api/v1/ams-history/{printer.id}",
  162. params={"days": 30}
  163. )
  164. assert response.status_code == 200
  165. data = response.json()
  166. assert data["deleted"] == 0