test_discovery_api.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. """Integration tests for Discovery API endpoints.
  2. Tests the full request/response cycle for /api/v1/discovery/ endpoints.
  3. """
  4. from unittest.mock import AsyncMock, patch
  5. import pytest
  6. from httpx import AsyncClient
  7. class TestDiscoveryAPI:
  8. """Integration tests for /api/v1/discovery/ endpoints."""
  9. # ========================================================================
  10. # Info endpoint
  11. # ========================================================================
  12. @pytest.mark.asyncio
  13. @pytest.mark.integration
  14. async def test_get_discovery_info(self, async_client: AsyncClient):
  15. """Verify discovery info endpoint returns expected fields."""
  16. response = await async_client.get("/api/v1/discovery/info")
  17. assert response.status_code == 200
  18. data = response.json()
  19. assert "is_docker" in data
  20. assert "ssdp_running" in data
  21. assert "scan_running" in data
  22. assert isinstance(data["is_docker"], bool)
  23. assert isinstance(data["ssdp_running"], bool)
  24. assert isinstance(data["scan_running"], bool)
  25. # ========================================================================
  26. # SSDP Discovery endpoints
  27. # ========================================================================
  28. @pytest.mark.asyncio
  29. @pytest.mark.integration
  30. async def test_get_discovery_status(self, async_client: AsyncClient):
  31. """Verify SSDP discovery status endpoint works."""
  32. response = await async_client.get("/api/v1/discovery/status")
  33. assert response.status_code == 200
  34. data = response.json()
  35. assert "running" in data
  36. assert isinstance(data["running"], bool)
  37. @pytest.mark.asyncio
  38. @pytest.mark.integration
  39. async def test_start_discovery(self, async_client: AsyncClient):
  40. """Verify SSDP discovery can be started."""
  41. response = await async_client.post("/api/v1/discovery/start?duration=1.0")
  42. assert response.status_code == 200
  43. data = response.json()
  44. assert "running" in data
  45. @pytest.mark.asyncio
  46. @pytest.mark.integration
  47. async def test_stop_discovery(self, async_client: AsyncClient):
  48. """Verify SSDP discovery can be stopped."""
  49. response = await async_client.post("/api/v1/discovery/stop")
  50. assert response.status_code == 200
  51. data = response.json()
  52. assert "running" in data
  53. assert data["running"] is False
  54. @pytest.mark.asyncio
  55. @pytest.mark.integration
  56. async def test_get_discovered_printers_empty(self, async_client: AsyncClient):
  57. """Verify empty list when no printers discovered."""
  58. response = await async_client.get("/api/v1/discovery/printers")
  59. assert response.status_code == 200
  60. data = response.json()
  61. assert isinstance(data, list)
  62. # ========================================================================
  63. # Subnet scanning endpoints
  64. # ========================================================================
  65. @pytest.mark.asyncio
  66. @pytest.mark.integration
  67. async def test_start_subnet_scan(self, async_client: AsyncClient):
  68. """Verify subnet scan can be started."""
  69. response = await async_client.post(
  70. "/api/v1/discovery/scan",
  71. json={"subnet": "192.168.1.0/30", "timeout": 0.1}, # Small subnet for testing
  72. )
  73. assert response.status_code == 200
  74. data = response.json()
  75. assert "running" in data
  76. assert "scanned" in data
  77. assert "total" in data
  78. @pytest.mark.asyncio
  79. @pytest.mark.integration
  80. async def test_get_scan_status(self, async_client: AsyncClient):
  81. """Verify subnet scan status endpoint works."""
  82. response = await async_client.get("/api/v1/discovery/scan/status")
  83. assert response.status_code == 200
  84. data = response.json()
  85. assert "running" in data
  86. assert "scanned" in data
  87. assert "total" in data
  88. @pytest.mark.asyncio
  89. @pytest.mark.integration
  90. async def test_stop_subnet_scan(self, async_client: AsyncClient):
  91. """Verify subnet scan can be stopped."""
  92. response = await async_client.post("/api/v1/discovery/scan/stop")
  93. assert response.status_code == 200
  94. data = response.json()
  95. assert "running" in data
  96. @pytest.mark.asyncio
  97. @pytest.mark.integration
  98. async def test_subnet_scan_invalid_subnet(self, async_client: AsyncClient):
  99. """Verify invalid subnet format is rejected."""
  100. response = await async_client.post("/api/v1/discovery/scan", json={"subnet": "invalid-subnet", "timeout": 1.0})
  101. # Should return 422 validation error or 200 with empty results
  102. assert response.status_code in [200, 422]
  103. class TestDiscoveryService:
  104. """Unit tests for discovery service functionality."""
  105. @pytest.mark.asyncio
  106. @pytest.mark.integration
  107. async def test_docker_detection_fields(self, async_client: AsyncClient):
  108. """Verify Docker detection returns consistent response."""
  109. # Call multiple times to ensure consistency
  110. response1 = await async_client.get("/api/v1/discovery/info")
  111. response2 = await async_client.get("/api/v1/discovery/info")
  112. assert response1.status_code == 200
  113. assert response2.status_code == 200
  114. assert response1.json()["is_docker"] == response2.json()["is_docker"]