M5: use DB-merged runtime settings for MQTT/discovery; add MQTT test button; move Expose panel into config accordion
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
@@ -656,3 +656,90 @@ def test_put_config_bool_field_roundtrip_true_false(
|
||||
finally:
|
||||
conn.close()
|
||||
assert rows.get("MQTT_ENABLED") == "false"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# M5-fix2: DB-config → runtime settings (Issue 2 regression assertions)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_put_config_mqtt_reconnect_uses_db_merged_settings(
|
||||
client: TestClient, test_database_urls
|
||||
) -> None:
|
||||
"""PUT /api/config with MQTT keys must reconnect with DB-merged settings,
|
||||
not bootstrap-only settings. Asserts that mqtt_manager.reconnect receives
|
||||
settings where mqtt_enabled=True and mqtt_broker_host matches the submitted value.
|
||||
"""
|
||||
_login(client)
|
||||
|
||||
target_host = "mqtt.example.com"
|
||||
payload = _full_config_payload({
|
||||
"MQTT_ENABLED": "true",
|
||||
"MQTT_BROKER_HOST": target_host,
|
||||
})
|
||||
|
||||
mock_mgr = MagicMock()
|
||||
mock_mgr.is_configured.return_value = True
|
||||
|
||||
with patch("app.api.routes.api.config.mqtt_manager", mock_mgr):
|
||||
resp = client.put(
|
||||
"/api/config",
|
||||
json={"updates": payload},
|
||||
headers={"X-CSRF-Token": "token"},
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
|
||||
# reconnect must have been called once
|
||||
assert mock_mgr.reconnect.call_count == 1, (
|
||||
f"Expected mqtt_manager.reconnect called once, got {mock_mgr.reconnect.call_count}"
|
||||
)
|
||||
reconnect_settings = mock_mgr.reconnect.call_args[0][0]
|
||||
assert reconnect_settings.mqtt_enabled is True, (
|
||||
f"reconnect settings.mqtt_enabled must be True, got {reconnect_settings.mqtt_enabled!r}"
|
||||
)
|
||||
assert reconnect_settings.mqtt_broker_host == target_host, (
|
||||
f"reconnect settings.mqtt_broker_host must be {target_host!r}, "
|
||||
f"got {reconnect_settings.mqtt_broker_host!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_post_mqtt_test_uses_db_broker_host(
|
||||
client: TestClient, test_database_urls
|
||||
) -> None:
|
||||
"""POST /api/config/mqtt/test must use the DB-stored broker host, not env/bootstrap."""
|
||||
_login(client)
|
||||
|
||||
db_host = "broker.db-configured.local"
|
||||
|
||||
# First write the MQTT config to DB via PUT /api/config
|
||||
payload_save = _full_config_payload({
|
||||
"MQTT_ENABLED": "true",
|
||||
"MQTT_BROKER_HOST": db_host,
|
||||
})
|
||||
with patch("app.api.routes.api.config.mqtt_manager"):
|
||||
save_resp = client.put(
|
||||
"/api/config",
|
||||
json={"updates": payload_save},
|
||||
headers={"X-CSRF-Token": "token"},
|
||||
)
|
||||
assert save_resp.status_code == 200
|
||||
|
||||
# Now POST /api/config/mqtt/test — capture the host that _run_mqtt_test uses.
|
||||
captured_host: list[str] = []
|
||||
|
||||
def _fake_run_mqtt_test(settings):
|
||||
captured_host.append(settings.mqtt_broker_host)
|
||||
# simulate success by just returning
|
||||
return
|
||||
|
||||
with patch("app.api.routes.api.config._run_mqtt_test", side_effect=_fake_run_mqtt_test):
|
||||
resp = client.post(
|
||||
"/api/config/mqtt/test",
|
||||
headers={"X-CSRF-Token": "token"},
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert len(captured_host) == 1, "Expected _run_mqtt_test to be called once"
|
||||
assert captured_host[0] == db_host, (
|
||||
f"Expected mqtt test to use DB host {db_host!r}, got {captured_host[0]!r}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user