"""Lucys Freiheiten je Aktionsart (Ausbauplan Welle 3, Punkt 14, 25.09.2026). User-Entscheid „Mehr Freiheit“: Sie startet Dienste selbst neu, spielt Sicherheitsupdates ein und geht bei Rot auf den Snapshot zurück — mit Meldung danach; andere Updates, Aufräumen, Modell-Tests und den Host-Neustart gibt es nur nach dem Ja des Commanders.""" import json import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from kern import einstellungen as einstellungen_mod from services import lucy_autonomie, rueckfragen @pytest.fixture def daten(tmp_path, monkeypatch): monkeypatch.setenv("MC_DATEN_DIR", str(tmp_path)) einstellungen_mod.einstellungen.cache_clear() yield tmp_path einstellungen_mod.einstellungen.cache_clear() def test_start_ist_mehr_freiheit(daten): stufen = lucy_autonomie.stufen() assert {a for a, s in stufen.items() if s == "selbst"} == {"ermitteln", "neustart", "sicherheit", "rueckweg", "suchen"} assert {a for a, s in stufen.items() if s == "fragen"} == {"updates", "aufraeumen", "radar", "host_neustart"} assert lucy_autonomie.stufe("gibt-es-nicht") == "fragen" # im Zweifel nie ungefragt def test_umstellen_und_merken(daten): ergebnis = lucy_autonomie.setzen({"stufen": {"host_neustart": "lesen", "updates": "selbst"}}) assert ergebnis == {"ok": True, "text": "Gespeichert — Proxmox-Host neu starten: nur lesen; Andere Updates " "einspielen: selbst handeln."} assert lucy_autonomie.stufe("host_neustart") == "lesen" and lucy_autonomie.stufe("updates") == "selbst" assert json.loads((daten / "lucy-autonomie.json").read_text(encoding="utf-8")) == { "stufen": {"host_neustart": "lesen", "updates": "selbst"}} stand = lucy_autonomie.stand() assert stand["arten"][0]["id"] == "ermitteln" and set(stand["stufen"]) == {"lesen", "fragen", "selbst"} host = next(a for a in stand["arten"] if a["id"] == "host_neustart") assert host["stufe"] == "lesen" and host["standard"] == "fragen" @pytest.mark.parametrize("eingabe, fehler", [ ({}, "Es fehlt"), ({"stufen": {}}, "Es fehlt"), ("quatsch", "Es fehlt"), ({"stufen": {"loeschen": "selbst"}}, "gibt es nicht"), ({"stufen": {"updates": "immer"}}, "keine Stufe"), ]) def test_nur_bekanntes(daten, eingabe, fehler): ergebnis = lucy_autonomie.setzen(eingabe) assert not ergebnis["ok"] and fehler in ergebnis["detail"] assert not (daten / "lucy-autonomie.json").exists() def test_kaputte_datei_gilt_als_standard(daten): (daten / "lucy-autonomie.json").write_text('{"stufen": {"updates": "immer", "neustart": "lesen"}}', encoding="utf-8") assert lucy_autonomie.stufe("updates") == "fragen" and lucy_autonomie.stufe("neustart") == "lesen" (daten / "lucy-autonomie.json").write_text("kein json", encoding="utf-8") assert lucy_autonomie.stufe("neustart") == "selbst" def test_meldung_danach(daten, monkeypatch): gemeldet = [] monkeypatch.setattr(rueckfragen, "melden", lambda betreff, text, knoepfe=None, dringend=False: gemeldet.append((betreff, text))) ergebnis = lucy_autonomie.gehandelt({"was": "Hermes-Gateway neu gestartet.", "grund": "hing seit zehn Minuten", "ergebnis": "hermes-gateway wird neu gestartet."}) assert ergebnis["ok"] assert gemeldet == [("[Lucy selbst]", ("Hermes-Gateway neu gestartet. Warum: hing seit zehn Minuten\n" "hermes-gateway wird neu gestartet."))] assert not lucy_autonomie.gehandelt({"grund": "ohne was"})["ok"] def test_schnittstelle(daten): from routers import lucy app = FastAPI() app.include_router(lucy.router) c = TestClient(app) assert c.get("/api/lucy/autonomie").json()["arten"][1]["id"] == "neustart" assert c.post("/api/lucy/autonomie", json={"stufen": {"radar": "selbst"}}).status_code == 200 assert lucy_autonomie.stufe("radar") == "selbst" r = c.post("/api/lucy/autonomie", json={"stufen": {"radar": "nie"}}) assert r.status_code == 409 and "keine Stufe" in r.json()["detail"]