Selbst-Update-Sicherung, Service-Prognose ohne Servicebuch und Sicherheit neu gestaltet
- aktualisierung.py: Backup-Ordner verliert sein manifest.json beim Sichern, sonst laedt HA ihn nach einem Neustart als zweite audi_dashboard-Integration (Ursache des raetselhaften "gleicher Pfad"-Umbenennungs-Fehlers). - service.ts/audi-dashboard-app.js: Uebersicht faellt jetzt wie Service schon auf die Fahrzeugmeldung zurueck, wenn kein Servicebucheintrag existiert; eigenes (kuerzeres) Oelwechsel-Intervall wird jetzt auch ohne Servicebuch- eintrag naeherungsweise aus der Herstellermeldung hochgerechnet, statt weiterhin unveraendert die Herstellervorgabe zu zeigen. - Sicherheit neu gestaltet: vier Sammelzeilen (Fahrzeug verriegelt / Tueren und Klappen geschlossen / Fenster und Dach geschlossen / Kein Licht) statt einer flachen Liste, mit neuen Tuerschloss-, Dach- und Standlicht-Sensor- rollen, Kreis-Haekchen-Symbolen und einer Detailseite je Tuer/Motorhaube/ Kofferraum in beiden Frontends. Details, Verifikation und Sensor-Rollen in AGENTS.md (Abschnitte J/M/N). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import zipfile
|
||||
from unittest import mock
|
||||
|
||||
_HIER = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(
|
||||
@@ -81,13 +82,42 @@ class ErfolgreicherTausch(unittest.TestCase):
|
||||
self.assertFalse(os.path.exists(os.path.join(self.integration, "alte_datei.py")))
|
||||
|
||||
# Alte Fassung bleibt vollständig und unverändert im Backup-Ordner.
|
||||
with open(os.path.join(self.backup, "manifest.json"), "rb") as f:
|
||||
with open(os.path.join(self.backup, "manifest.json.bak"), "rb") as f:
|
||||
self.assertIn(b'"2026.1.1.1"', f.read())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.backup, "alte_datei.py")))
|
||||
|
||||
# manifest.json selbst existiert im Backup-Ordner NICHT mehr - sonst
|
||||
# würde HA ihn beim nächsten Neustart als zweite Integration mit
|
||||
# derselben Domain laden (siehe Moduldocstring in aktualisierung.py).
|
||||
self.assertFalse(os.path.exists(os.path.join(self.backup, "manifest.json")))
|
||||
|
||||
# Kein Staging-Rest übrig.
|
||||
self.assertFalse(os.path.exists(self.staging))
|
||||
|
||||
def test_rollback_stellt_manifest_der_alten_fassung_wieder_her(self):
|
||||
"""Schlägt der zweite Rename fehl, muss der Backup-Ordner nicht nur
|
||||
zurückbenannt werden, sondern auch sein manifest.json - sonst stünde
|
||||
die wiederhergestellte alte Fassung ohne gültiges Manifest da."""
|
||||
zip_bytes = _zip_bauen({
|
||||
"manifest.json": _GUELTIGES_MANIFEST,
|
||||
"neue_datei.py": b"# neue Fassung\n",
|
||||
})
|
||||
echter_rename = os.rename
|
||||
|
||||
def zweiten_rename_kaputt_machen(src, dst):
|
||||
if src == self.staging and dst == self.integration:
|
||||
raise OSError("simulierter Fehler")
|
||||
echter_rename(src, dst)
|
||||
|
||||
with mock.patch("aktualisierung.os.rename", side_effect=zweiten_rename_kaputt_machen):
|
||||
with self.assertRaises(a.AktualisierungsFehler):
|
||||
a.entpacken_pruefen_tauschen(zip_bytes, self.integration, self.staging, self.backup)
|
||||
|
||||
with open(os.path.join(self.integration, "manifest.json"), "rb") as f:
|
||||
self.assertIn(b'"2026.1.1.1"', f.read())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.integration, "alte_datei.py")))
|
||||
self.assertFalse(os.path.exists(self.backup))
|
||||
|
||||
def test_entfernt_pycache_aus_dem_staging_ordner(self):
|
||||
zip_bytes = _zip_bauen({
|
||||
"manifest.json": _GUELTIGES_MANIFEST,
|
||||
|
||||
Reference in New Issue
Block a user