Files
Plugin_SN_Basis/tests/test_basemap_anbindung.py
T
DanielandClaude Opus 5.5 f9241a11f9 Basemap-Bereich im Druck-Tab mit lokalen Stilvorlagen (#88)
Einklappbarer Bereich „Basemap“: Auswertebereich (Verfahrensgebiet/Druckbereich),
Basemap-Legende beim Erstellen an/aus, „Basemap-Legende aktualisieren“ für
bestehende Vorlagen und Stilvorlagen des Basemap-Layers. Stilvorlagen liegen lokal im
QGIS-Profil (QML plus Begleitdatei mit Legendenauswahl), mehrere Varianten, eine als
Standard markierbar; geladen wird nur auf Knopfdruck nach Rückfrage, fremde Varianten
(andere Style-Namen) erst nach zweiter Bestätigung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:57:10 +02:00

175 lines
9.0 KiB
Python

"""
Tests für die Anbindung der Basemap-Legende an Druckablauf, Dialog und Druck-Tab (Basis #88):
Mehrfachauswahl-Dialog, PrintLogic/PrintLayout und Basemap-Bereich im Druck-Tab.
"""
import json
import unittest
from unittest.mock import MagicMock, patch
from sn_basis.functions.dialog_wrapper import ask_mehrfachauswahl
from sn_basis.functions.variable_wrapper import get_variable, set_variable
from sn_basis.modules import basemap_legende as bl
from sn_basis.modules.print_layout import PrintLayout
from sn_basis.modules.print_logic import (
KARTENNAME_38,
KARTENNAME_41,
KARTENNAME_BAUFREIGABE,
LAYOUTS_MIT_BASEMAP_LEGENDE,
PrintLogic,
)
from sn_basis.ui.tabs.print_tab import PrintTab
from sn_basis.ui.widgets.basemap_bereich import BasemapBereich
class TestMehrfachauswahl(unittest.TestCase):
def test_mock_modus_liefert_vorauswahl_in_listenreihenfolge(self):
"""Prüft, dass der Mehrfachauswahl-Dialog im Mock-Modus die vorausgewählten Schlüssel in Listenreihenfolge liefert."""
eintraege = [{"schluessel": s, "text": s.upper()} for s in ("a", "b", "c")]
self.assertEqual(ask_mehrfachauswahl("T", "H", eintraege, {"c", "a"}), ["a", "c"])
class TestDruckanbindung(unittest.TestCase):
def tearDown(self):
set_variable(bl.LEGENDE_ERZEUGEN_VAR, "", scope="project")
def test_basemap_legende_nur_fuer_38_und_41_und_bei_eingeschaltetem_schalter(self):
"""Prüft, dass nur §-38- und §-41-Vorlagen eine Basemap-Legende bekommen und nur, wenn der Schalter im Druck-Tab an ist."""
logik = PrintLogic(pruefmanager=MagicMock())
self.assertEqual(LAYOUTS_MIT_BASEMAP_LEGENDE, {KARTENNAME_38, KARTENNAME_41})
self.assertTrue(logik._basemap_legende_erzeugen(KARTENNAME_41))
self.assertFalse(logik._basemap_legende_erzeugen(KARTENNAME_BAUFREIGABE))
bl.setze_legende_erzeugen(False)
self.assertFalse(logik._basemap_legende_erzeugen(KARTENNAME_38))
def test_layout_wird_markiert_und_legende_erzeugt(self):
"""Prüft, dass PrintLayout das Layout als Basemap-Nutzer kennzeichnet und die Basemap-Legende erzeugen lässt."""
layout = MagicMock()
with patch("sn_basis.modules.basemap_legende.BasemapLegende") as klasse:
klasse.return_value.aktualisiere.return_value = {"status": "ok"}
PrintLayout(project=MagicMock())._erzeuge_basemap_legende(layout)
layout.setCustomProperty.assert_any_call("sn_basemap_legende", 1)
klasse.return_value.aktualisiere.assert_called_once_with(layout)
def test_fehler_der_basemap_legende_verhindert_die_vorlage_nicht(self):
"""Prüft, dass ein Fehler beim Erzeugen der Basemap-Legende nur als Warnung gemeldet wird und keine Ausnahme durchreicht."""
with patch("sn_basis.modules.basemap_legende.BasemapLegende") as klasse, \
patch("sn_basis.functions.message_wrapper.warning") as warnung:
klasse.return_value.aktualisiere.side_effect = RuntimeError("Netz weg")
PrintLayout(project=MagicMock())._erzeuge_basemap_legende(MagicMock())
warnung.assert_called_once()
self.assertIn("Netz weg", warnung.call_args[0][1])
def test_druck_tab_aktualisiert_basemap_bereich_falls_vorhanden(self):
"""Prüft, dass der Druck-Tab den Basemap-Bereich neu einliest und ohne Bereich nichts tut."""
tab = PrintTab.__new__(PrintTab)
tab._basemap_bereich_aktualisieren() # ohne Bereich: keine Ausnahme
tab._basemap_bereich = MagicMock()
tab._basemap_bereich_aktualisieren()
tab._basemap_bereich.aktualisieren.assert_called_once()
def _bereich(stil_name="Ohne_Hausnummern", layer=None, layout_name="§41"):
bereich = BasemapBereich.__new__(BasemapBereich)
bereich._project = MagicMock()
bereich._stilvorlagen = MagicMock()
bereich._stil_combo = MagicMock()
bereich._stil_combo.currentData.return_value = stil_name
bereich._stil_combo.currentText.return_value = stil_name
bereich._layout_combo = MagicMock()
bereich._layout_combo.currentText.return_value = layout_name
bereich._bereich_combo = MagicMock()
bereich.basemap_layer = MagicMock(return_value=layer)
bereich.aktualisieren = MagicMock()
return bereich
class TestBasemapBereich(unittest.TestCase):
def tearDown(self):
for schluessel in (bl.AUSWAHL_VAR, bl.AUSWERTEBEREICH_VAR):
set_variable(schluessel, "", scope="project")
def test_auswertebereich_wird_gespeichert(self):
"""Prüft, dass die Wahl des Auswertebereichs in der Projektvariable landet."""
bereich = _bereich()
bereich._bereich_combo.currentData.return_value = bl.AUSWERTEBEREICH_DRUCKBEREICH
bereich._on_bereich_geaendert(1)
self.assertEqual(bl.lies_auswertebereich(), bl.AUSWERTEBEREICH_DRUCKBEREICH)
@patch("sn_basis.ui.widgets.basemap_bereich.warning")
def test_aktualisieren_ohne_vorlage_warnt(self, warnung):
"""Prüft, dass „Basemap-Legende aktualisieren“ ohne vorhandene Vorlage warnt und nichts auswertet."""
bereich = _bereich()
bereich._project.layoutManager.return_value.layoutByName.return_value = None
with patch("sn_basis.modules.basemap_legende.BasemapLegende") as klasse:
bereich._on_legende_aktualisieren()
klasse.assert_not_called()
warnung.assert_called_once()
@patch("sn_basis.ui.widgets.basemap_bereich.success")
def test_aktualisieren_wertet_gewaehlte_vorlage_aus(self, erfolg):
"""Prüft, dass „Basemap-Legende aktualisieren“ die gewählte Vorlage auswertet und den Erfolg meldet."""
bereich = _bereich()
layout = bereich._project.layoutManager.return_value.layoutByName.return_value
with patch("sn_basis.modules.basemap_legende.BasemapLegende") as klasse:
klasse.return_value.aktualisiere.return_value = {"status": "ok", "meldung": "3 Einträge"}
bereich._on_legende_aktualisieren()
klasse.return_value.aktualisiere.assert_called_once_with(layout)
erfolg.assert_called_once()
@patch("sn_basis.ui.widgets.basemap_bereich.ask_yes_no", return_value=True)
@patch("sn_basis.ui.widgets.basemap_bereich.success")
def test_stil_laden_uebernimmt_legendenauswahl(self, _erfolg, _frage):
"""Prüft, dass das Laden einer Stilvorlage den Layerstil ersetzt und ihre Legendenauswahl in das Projekt übernimmt."""
layer = MagicMock()
bereich = _bereich(layer=layer)
bereich._stilvorlagen.pruefe_passung.return_value = []
bereich._stilvorlagen.legendenauswahl.return_value = {"ausgeblendet": ["wald"], "eingeblendet": []}
bereich._on_stil_laden()
bereich._stilvorlagen.laden.assert_called_once_with(layer, "Ohne_Hausnummern")
self.assertEqual(json.loads(get_variable(bl.AUSWAHL_VAR, scope="project"))["ausgeblendet"], ["wald"])
@patch("sn_basis.ui.widgets.basemap_bereich.ask_yes_no", side_effect=[True, False])
def test_stil_laden_bricht_bei_fremder_vorlage_ab(self, _frage):
"""Prüft, dass eine Vorlage mit unbekannten Styles nur nach Bestätigung geladen wird."""
bereich = _bereich(layer=MagicMock())
bereich._stilvorlagen.pruefe_passung.return_value = ["Fremder_Style"]
bereich._on_stil_laden()
bereich._stilvorlagen.laden.assert_not_called()
@patch("sn_basis.ui.widgets.basemap_bereich.ask_text", return_value=("Ohne Hausnummern", True))
@patch("sn_basis.ui.widgets.basemap_bereich.ask_yes_no", return_value=False)
def test_vorhandene_vorlage_wird_nur_nach_rueckfrage_ersetzt(self, _frage, _text):
"""Prüft, dass eine gleichnamige Stilvorlage ohne Bestätigung nicht überschrieben wird."""
bereich = _bereich(layer=MagicMock())
bereich._stilvorlagen.vorhanden.return_value = True
bereich._on_stil_speichern()
bereich._stilvorlagen.speichern.assert_not_called()
@patch("sn_basis.ui.widgets.basemap_bereich.ask_text", return_value=("Neu", True))
@patch("sn_basis.ui.widgets.basemap_bereich.success")
def test_speichern_mit_aktueller_legendenauswahl(self, _erfolg, _text):
"""Prüft, dass eine neue Stilvorlage zusammen mit der aktuellen Legendenauswahl gespeichert wird."""
layer = MagicMock()
bereich = _bereich(layer=layer)
bereich._stilvorlagen.vorhanden.return_value = False
bl.merke_auswahl([bl.LegendenEintrag("wald", "Wald", "Vegetation", [])], [])
bereich._on_stil_speichern()
bereich._stilvorlagen.speichern.assert_called_once_with(
layer, "Neu", {"ausgeblendet": ["wald"], "eingeblendet": []})
bereich.aktualisieren.assert_called_once()
@patch("sn_basis.ui.widgets.basemap_bereich.warning")
def test_stil_speichern_ohne_basemap_layer_warnt(self, warnung):
"""Prüft, dass ohne Basemap-Layer keine Stilvorlage gespeichert, sondern gewarnt wird."""
bereich = _bereich(layer=None)
bereich._on_stil_speichern()
bereich._stilvorlagen.speichern.assert_not_called()
warnung.assert_called_once()
if __name__ == "__main__":
unittest.main()