test_homeassistant_settings.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. """Unit tests for Home Assistant settings with environment variable support.
  2. Tests the get_homeassistant_settings() function in isolation.
  3. """
  4. import os
  5. from unittest.mock import AsyncMock, patch
  6. import pytest
  7. from sqlalchemy.ext.asyncio import AsyncSession
  8. @pytest.mark.asyncio
  9. @pytest.mark.unit
  10. async def test_get_homeassistant_settings_no_env_vars():
  11. """Test get_homeassistant_settings with no environment variables."""
  12. from backend.app.api.routes.settings import get_homeassistant_settings
  13. # Mock database session
  14. db = AsyncMock(spec=AsyncSession)
  15. # Mock get_setting to return database values
  16. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  17. mock_get_setting.side_effect = lambda db, key: {
  18. "ha_url": "http://db-url:8123",
  19. "ha_token": "db-token",
  20. "ha_enabled": "true",
  21. }.get(key, "")
  22. # Ensure no env vars
  23. with patch.dict(os.environ, {}, clear=False):
  24. os.environ.pop("HA_URL", None)
  25. os.environ.pop("HA_TOKEN", None)
  26. result = await get_homeassistant_settings(db)
  27. # Should use database values
  28. assert result["ha_url"] == "http://db-url:8123"
  29. assert result["ha_token"] == "db-token"
  30. assert result["ha_enabled"] is True
  31. assert result["ha_url_from_env"] is False
  32. assert result["ha_token_from_env"] is False
  33. assert result["ha_env_managed"] is False
  34. @pytest.mark.asyncio
  35. @pytest.mark.unit
  36. async def test_get_homeassistant_settings_with_env_vars():
  37. """Test get_homeassistant_settings with environment variables set."""
  38. from backend.app.api.routes.settings import get_homeassistant_settings
  39. db = AsyncMock(spec=AsyncSession)
  40. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  41. mock_get_setting.side_effect = lambda db, key: {
  42. "ha_url": "http://db-url:8123",
  43. "ha_token": "db-token",
  44. "ha_enabled": "false",
  45. }.get(key, "")
  46. # Set environment variables
  47. with patch.dict(os.environ, {"HA_URL": "http://supervisor/core", "HA_TOKEN": "env-token"}, clear=False):
  48. result = await get_homeassistant_settings(db)
  49. # Should use environment values
  50. assert result["ha_url"] == "http://supervisor/core"
  51. assert result["ha_token"] == "env-token"
  52. assert result["ha_enabled"] is True # Auto-enabled
  53. assert result["ha_url_from_env"] is True
  54. assert result["ha_token_from_env"] is True
  55. assert result["ha_env_managed"] is True
  56. @pytest.mark.asyncio
  57. @pytest.mark.unit
  58. async def test_get_homeassistant_settings_partial_env_url_only():
  59. """Test get_homeassistant_settings with only HA_URL set."""
  60. from backend.app.api.routes.settings import get_homeassistant_settings
  61. db = AsyncMock(spec=AsyncSession)
  62. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  63. mock_get_setting.side_effect = lambda db, key: {
  64. "ha_url": "http://db-url:8123",
  65. "ha_token": "db-token",
  66. "ha_enabled": "false",
  67. }.get(key, "")
  68. # Set only URL env var
  69. with patch.dict(os.environ, {"HA_URL": "http://supervisor/core"}, clear=False):
  70. os.environ.pop("HA_TOKEN", None)
  71. result = await get_homeassistant_settings(db)
  72. # URL from env, token from database
  73. assert result["ha_url"] == "http://supervisor/core"
  74. assert result["ha_token"] == "db-token"
  75. assert result["ha_enabled"] is False # Not auto-enabled
  76. assert result["ha_url_from_env"] is True
  77. assert result["ha_token_from_env"] is False
  78. assert result["ha_env_managed"] is False
  79. @pytest.mark.asyncio
  80. @pytest.mark.unit
  81. async def test_get_homeassistant_settings_partial_env_token_only():
  82. """Test get_homeassistant_settings with only HA_TOKEN set."""
  83. from backend.app.api.routes.settings import get_homeassistant_settings
  84. db = AsyncMock(spec=AsyncSession)
  85. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  86. mock_get_setting.side_effect = lambda db, key: {
  87. "ha_url": "http://db-url:8123",
  88. "ha_token": "db-token",
  89. "ha_enabled": "false",
  90. }.get(key, "")
  91. # Set only token env var
  92. with patch.dict(os.environ, {"HA_TOKEN": "env-token"}, clear=False):
  93. os.environ.pop("HA_URL", None)
  94. result = await get_homeassistant_settings(db)
  95. # URL from database, token from env
  96. assert result["ha_url"] == "http://db-url:8123"
  97. assert result["ha_token"] == "env-token"
  98. assert result["ha_enabled"] is False # Not auto-enabled
  99. assert result["ha_url_from_env"] is False
  100. assert result["ha_token_from_env"] is True
  101. assert result["ha_env_managed"] is False
  102. @pytest.mark.asyncio
  103. @pytest.mark.unit
  104. async def test_get_homeassistant_settings_empty_env_vars():
  105. """Test get_homeassistant_settings with empty environment variables."""
  106. from backend.app.api.routes.settings import get_homeassistant_settings
  107. db = AsyncMock(spec=AsyncSession)
  108. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  109. mock_get_setting.side_effect = lambda db, key: {
  110. "ha_url": "http://db-url:8123",
  111. "ha_token": "db-token",
  112. "ha_enabled": "false",
  113. }.get(key, "")
  114. # Set empty env vars
  115. with patch.dict(os.environ, {"HA_URL": "", "HA_TOKEN": ""}, clear=False):
  116. result = await get_homeassistant_settings(db)
  117. # Empty env vars treated as not set, should use database values
  118. assert result["ha_url"] == "http://db-url:8123"
  119. assert result["ha_token"] == "db-token"
  120. assert result["ha_enabled"] is False
  121. assert result["ha_url_from_env"] is False
  122. assert result["ha_token_from_env"] is False
  123. assert result["ha_env_managed"] is False
  124. @pytest.mark.asyncio
  125. @pytest.mark.unit
  126. async def test_get_homeassistant_settings_auto_enable_logic():
  127. """Test auto-enable behavior with various configurations."""
  128. from backend.app.api.routes.settings import get_homeassistant_settings
  129. db = AsyncMock(spec=AsyncSession)
  130. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  131. # Database has ha_enabled=false
  132. mock_get_setting.side_effect = lambda db, key: {
  133. "ha_url": "",
  134. "ha_token": "",
  135. "ha_enabled": "false",
  136. }.get(key, "")
  137. # Test 1: No env vars - use database enabled state
  138. with patch.dict(os.environ, {}, clear=False):
  139. os.environ.pop("HA_URL", None)
  140. os.environ.pop("HA_TOKEN", None)
  141. result = await get_homeassistant_settings(db)
  142. assert result["ha_enabled"] is False
  143. # Test 2: Both env vars set - auto-enable
  144. with patch.dict(os.environ, {"HA_URL": "http://test", "HA_TOKEN": "token"}, clear=False):
  145. result = await get_homeassistant_settings(db)
  146. assert result["ha_enabled"] is True
  147. # Test 3: Only URL - use database enabled state
  148. with patch.dict(os.environ, {"HA_URL": "http://test"}, clear=False):
  149. os.environ.pop("HA_TOKEN", None)
  150. result = await get_homeassistant_settings(db)
  151. assert result["ha_enabled"] is False
  152. # Test 4: Only token - use database enabled state
  153. with patch.dict(os.environ, {"HA_TOKEN": "token"}, clear=False):
  154. os.environ.pop("HA_URL", None)
  155. result = await get_homeassistant_settings(db)
  156. assert result["ha_enabled"] is False
  157. @pytest.mark.asyncio
  158. @pytest.mark.unit
  159. async def test_get_homeassistant_settings_env_vars_override_enabled_true():
  160. """Test that env vars auto-enable even when database has ha_enabled=true."""
  161. from backend.app.api.routes.settings import get_homeassistant_settings
  162. db = AsyncMock(spec=AsyncSession)
  163. with patch("backend.app.api.routes.settings.get_setting") as mock_get_setting:
  164. # Database has ha_enabled=true
  165. mock_get_setting.side_effect = lambda db, key: {
  166. "ha_url": "http://db-url:8123",
  167. "ha_token": "db-token",
  168. "ha_enabled": "true",
  169. }.get(key, "")
  170. # Both env vars set - should still be enabled
  171. with patch.dict(os.environ, {"HA_URL": "http://supervisor/core", "HA_TOKEN": "env-token"}, clear=False):
  172. result = await get_homeassistant_settings(db)
  173. assert result["ha_enabled"] is True # Auto-enabled by env vars
  174. assert result["ha_url"] == "http://supervisor/core"
  175. assert result["ha_token"] == "env-token"
  176. assert result["ha_env_managed"] is True