""" POST /nodes/request-update-all — the fleet-wide "Update Node": flags every approved node (HTTPS) and nudges it over MQTT; pending/rejected nodes are skipped. """ from unittest.mock import AsyncMock, MagicMock, patch from fastapi.testclient import TestClient from app.main import app from app.internal.auth import require_admin_token, require_service_or_firebase_token from app.routers import nodes client = TestClient(app) def setup_function(): app.dependency_overrides[require_admin_token] = lambda: {"admin": True} app.dependency_overrides[require_service_or_firebase_token] = lambda: {"admin": True} def teardown_function(): app.dependency_overrides.pop(require_admin_token, None) app.dependency_overrides.pop(require_service_or_firebase_token, None) def test_update_all_flags_only_approved_nodes(): fleet = [ {"node_id": "a", "approval_status": "approved"}, {"node_id": "b", "approval_status": "approved"}, {"node_id": "p", "approval_status": "pending"}, {"node_id": "r", "approval_status": "rejected"}, ] doc_update = AsyncMock() send = MagicMock(side_effect=lambda nid, cmd: nid == "a") with patch.object(nodes.fstore, "collection_list", AsyncMock(return_value=fleet)), \ patch.object(nodes.fstore, "doc_update", doc_update), \ patch.object(nodes.mqtt_handler, "send_command", send): r = client.post("/nodes/request-update-all") assert r.status_code == 200 body = r.json() assert body["requested"] == ["a", "b"] assert body["mqtt_sent"] == ["a"] assert sorted(body["skipped"]) == ["p", "r"] flagged = {c.args[1] for c in doc_update.await_args_list} assert flagged == {"a", "b"} for c in doc_update.await_args_list: assert c.args[2] == {"update_requested_at": body["update_requested_at"]} assert {c.args[0] for c in send.call_args_list} == {"a", "b"} assert all(c.args[1] == {"action": "node_update"} for c in send.call_args_list) def test_update_all_requires_admin(): app.dependency_overrides.pop(require_admin_token, None) r = client.post("/nodes/request-update-all") assert r.status_code in (401, 403)