odoo_mqtt/iot_bridge/tests/integration/test_config_push_integration.py
matthias.lotz f5ad4ad7bf Phase 4.2: Add integration tests for reconnect, config push, and event delivery
- Add tests/integration/test_mqtt_reconnect.py with in-memory broker/client fakes
- Add tests/integration/test_config_push_integration.py for POST /config flow and reconnect trigger
- Add tests/integration/test_event_delivery.py for retry queue delivery behavior
- Add httpx dependency required by FastAPI/Starlette TestClient
- Update OPTIMIZATION_PLAN.md to mark 4.2 tasks complete

Validation:
- pytest tests/integration/test_mqtt_reconnect.py tests/integration/test_config_push_integration.py tests/integration/test_event_delivery.py
- mypy tests/integration/test_mqtt_reconnect.py tests/integration/test_config_push_integration.py tests/integration/test_event_delivery.py
2026-02-19 19:17:23 +01:00

86 lines
2.7 KiB
Python

"""Integration tests for config push flow via FastAPI config server."""
from __future__ import annotations
from typing import Any
from fastapi.testclient import TestClient
from api.models import BridgeConfig
from api.server import ConfigServer
def _config_payload(broker: str, port: int = 1883) -> dict[str, Any]:
return {
"mqtt": {
"broker": broker,
"port": port,
"username": "",
"password": "",
"client_id": "iot_bridge",
"keepalive": 60,
"use_tls": False,
},
"devices": [
{
"device_id": "dev-1",
"machine_name": "Machine 1",
"mqtt_topic": "dev-1/status/pm1:0",
"parser_type": "shelly_pm",
"device_status_timeout_s": 90,
"session_config": {
"standby_threshold_w": 20,
"working_threshold_w": 100,
"start_debounce_s": 3,
"stop_debounce_s": 15,
"message_timeout_s": 90,
"heartbeat_interval_s": 300,
},
}
],
"timestamp": "2026-02-19T18:00:00Z",
"version": "1.0",
}
def test_config_push_applies_and_returns_request_id(monkeypatch) -> None:
received: list[BridgeConfig] = []
async def on_config(config: BridgeConfig) -> None:
received.append(config)
server = ConfigServer(config_callback=on_config)
monkeypatch.setattr(server, "_persist_config", lambda _cfg: None)
client = TestClient(server.app)
response = client.post("/config", json=_config_payload("broker-a"))
assert response.status_code == 200
assert response.json()["status"] == "success"
assert "X-Request-ID" in response.headers
assert len(received) == 1
assert received[0].mqtt is not None
assert received[0].mqtt.broker == "broker-a"
def test_config_push_triggers_mqtt_reconnect_on_broker_change(monkeypatch) -> None:
reconnect_calls: list[str] = []
async def on_config(_config: BridgeConfig) -> None:
return None
async def on_reconnect(mqtt_config) -> None:
reconnect_calls.append(f"{mqtt_config.broker}:{mqtt_config.port}")
server = ConfigServer(config_callback=on_config, mqtt_reconnect_callback=on_reconnect)
monkeypatch.setattr(server, "_persist_config", lambda _cfg: None)
client = TestClient(server.app)
first = client.post("/config", json=_config_payload("broker-a"))
assert first.status_code == 200
second = client.post("/config", json=_config_payload("broker-b"))
assert second.status_code == 200
assert reconnect_calls == ["broker-b:1883"]