test_ams_history_api.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. """Integration tests for AMS History API endpoints."""
  2. from datetime import datetime, timedelta
  3. import pytest
  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(self, async_client: AsyncClient, printer_factory, db_session):
  33. """Verify empty history returns empty data array."""
  34. printer = await printer_factory()
  35. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  36. assert response.status_code == 200
  37. data = response.json()
  38. assert data["printer_id"] == printer.id
  39. assert data["ams_id"] == 0
  40. assert data["data"] == []
  41. @pytest.mark.asyncio
  42. @pytest.mark.integration
  43. async def test_get_ams_history_with_data(self, async_client: AsyncClient, ams_history_factory, db_session):
  44. """Verify history returns recorded data."""
  45. # Create history records
  46. history = await ams_history_factory()
  47. printer_id = history.printer_id
  48. response = await async_client.get(f"/api/v1/ams-history/{printer_id}/0")
  49. assert response.status_code == 200
  50. data = response.json()
  51. assert len(data["data"]) >= 1
  52. @pytest.mark.asyncio
  53. @pytest.mark.integration
  54. async def test_get_ams_history_with_stats(
  55. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  56. ):
  57. """Verify history includes statistics."""
  58. printer = await printer_factory()
  59. # Create multiple records with different values
  60. await ams_history_factory(printer_id=printer.id, humidity=40.0, temperature=24.0)
  61. await ams_history_factory(printer_id=printer.id, humidity=50.0, temperature=26.0)
  62. await ams_history_factory(printer_id=printer.id, humidity=45.0, temperature=25.0)
  63. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  64. assert response.status_code == 200
  65. data = response.json()
  66. # Check statistics
  67. assert data["min_humidity"] == 40.0
  68. assert data["max_humidity"] == 50.0
  69. assert data["min_temperature"] == 24.0
  70. assert data["max_temperature"] == 26.0
  71. @pytest.mark.asyncio
  72. @pytest.mark.integration
  73. async def test_get_ams_history_with_hours_filter(
  74. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  75. ):
  76. """Verify hours parameter filters data."""
  77. printer = await printer_factory()
  78. # Create a recent record
  79. await ams_history_factory(printer_id=printer.id, recorded_at=datetime.now())
  80. # Create an old record (outside default 24h)
  81. await ams_history_factory(printer_id=printer.id, recorded_at=datetime.now() - timedelta(hours=48))
  82. # Request only last 24 hours (default)
  83. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  84. assert response.status_code == 200
  85. data = response.json()
  86. # Should only get the recent record
  87. assert len(data["data"]) == 1
  88. @pytest.mark.asyncio
  89. @pytest.mark.integration
  90. async def test_get_ams_history_custom_hours(self, async_client: AsyncClient, printer_factory, db_session):
  91. """Verify custom hours parameter works."""
  92. printer = await printer_factory()
  93. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0", params={"hours": 48})
  94. assert response.status_code == 200
  95. data = response.json()
  96. assert data["printer_id"] == printer.id
  97. @pytest.mark.asyncio
  98. @pytest.mark.integration
  99. async def test_get_ams_history_different_ams_units(
  100. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  101. ):
  102. """Verify filtering by AMS unit ID."""
  103. printer = await printer_factory()
  104. await ams_history_factory(printer_id=printer.id, ams_id=0, humidity=40.0)
  105. await ams_history_factory(printer_id=printer.id, ams_id=1, humidity=50.0)
  106. # Get AMS unit 0
  107. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/0")
  108. assert response.status_code == 200
  109. data0 = response.json()
  110. assert len(data0["data"]) == 1
  111. assert data0["data"][0]["humidity"] == 40.0
  112. # Get AMS unit 1
  113. response = await async_client.get(f"/api/v1/ams-history/{printer.id}/1")
  114. assert response.status_code == 200
  115. data1 = response.json()
  116. assert len(data1["data"]) == 1
  117. assert data1["data"][0]["humidity"] == 50.0
  118. @pytest.mark.asyncio
  119. @pytest.mark.integration
  120. async def test_delete_old_history(
  121. self, async_client: AsyncClient, ams_history_factory, printer_factory, db_session
  122. ):
  123. """Verify old history can be deleted."""
  124. printer = await printer_factory()
  125. # Create an old record
  126. await ams_history_factory(printer_id=printer.id, recorded_at=datetime.now() - timedelta(days=60))
  127. # Delete records older than 30 days
  128. response = await async_client.delete(f"/api/v1/ams-history/{printer.id}", params={"days": 30})
  129. assert response.status_code == 200
  130. data = response.json()
  131. assert data["deleted"] >= 1
  132. @pytest.mark.asyncio
  133. @pytest.mark.integration
  134. async def test_delete_old_history_no_records(self, async_client: AsyncClient, printer_factory, db_session):
  135. """Verify delete with no old records returns 0."""
  136. printer = await printer_factory()
  137. response = await async_client.delete(f"/api/v1/ams-history/{printer.id}", params={"days": 30})
  138. assert response.status_code == 200
  139. data = response.json()
  140. assert data["deleted"] == 0