244 lines
9.6 KiB
Python
244 lines
9.6 KiB
Python
import sys
|
|
import types
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
if "qgis" not in sys.modules:
|
|
qgis_mod = types.ModuleType("qgis")
|
|
qgis_utils = types.ModuleType("qgis.utils")
|
|
qgis_utils.iface = types.SimpleNamespace()
|
|
qgis_utils.plugins = {}
|
|
qgis_mod.utils = qgis_utils
|
|
sys.modules["qgis"] = qgis_mod
|
|
sys.modules["qgis.utils"] = qgis_utils
|
|
|
|
from sn_verfahrensgebiet.functions import verfahrensgebiet_alkis as vg
|
|
|
|
|
|
class _DummyMessageBox:
|
|
class StandardButton:
|
|
Yes = 1
|
|
No = 2
|
|
|
|
last_critical = None
|
|
next_reply = StandardButton.No
|
|
|
|
@staticmethod
|
|
def question(_parent, _title, _message, _buttons, _default):
|
|
return _DummyMessageBox.next_reply
|
|
|
|
@staticmethod
|
|
def critical(parent, title, message):
|
|
_DummyMessageBox.last_critical = (parent, title, message)
|
|
|
|
|
|
class _DummyProject:
|
|
def __init__(self, layers=None):
|
|
self._layers = layers or []
|
|
self.removed = []
|
|
|
|
def mapLayersByName(self, _name):
|
|
return self._layers
|
|
|
|
def removeMapLayer(self, layer_id):
|
|
self.removed.append(layer_id)
|
|
|
|
|
|
class _DummyExistingLayer:
|
|
def __init__(self, layer_id="existing"):
|
|
self._id = layer_id
|
|
|
|
def id(self):
|
|
return self._id
|
|
|
|
|
|
class _DummyGeom:
|
|
def __init__(self, empty=False):
|
|
self._empty = empty
|
|
|
|
def isEmpty(self):
|
|
return self._empty
|
|
|
|
|
|
class _DummyFeature:
|
|
def __init__(self, geom=None, attrs=None):
|
|
self._geom = geom or _DummyGeom()
|
|
self._attrs = attrs or {}
|
|
|
|
def geometry(self):
|
|
return self._geom
|
|
|
|
def attribute(self, name):
|
|
return self._attrs.get(name)
|
|
|
|
|
|
class _DummyTempLayer:
|
|
def __init__(self, valid=True, features=None):
|
|
self._valid = valid
|
|
self._features = features or []
|
|
|
|
def isValid(self):
|
|
return self._valid
|
|
|
|
def getFeatures(self):
|
|
return self._features
|
|
|
|
def crs(self):
|
|
class _Crs:
|
|
@staticmethod
|
|
def authid():
|
|
return "EPSG:25833"
|
|
|
|
return _Crs()
|
|
|
|
|
|
class _DummyProvider:
|
|
def addAttributes(self, _attrs):
|
|
return True
|
|
|
|
def addFeatures(self, _features):
|
|
return True
|
|
|
|
|
|
class _DummyMemoryLayer:
|
|
def __init__(self):
|
|
self._provider = _DummyProvider()
|
|
|
|
def dataProvider(self):
|
|
return self._provider
|
|
|
|
def updateFields(self):
|
|
return None
|
|
|
|
def updateExtents(self):
|
|
return None
|
|
|
|
|
|
class TestVerfahrensgebietAlkis(unittest.TestCase):
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsProject.instance")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
def test_check_existing_layer_first_load(self, mock_project_instance):
|
|
mock_project_instance.return_value = _DummyProject(layers=[])
|
|
|
|
layer, status = vg._check_existing_layer(tab_widget=None)
|
|
|
|
self.assertIsNone(layer)
|
|
self.assertEqual(status, vg.LoadStatus.FIRST)
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsProject.instance")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
def test_check_existing_layer_keep_existing(self, mock_project_instance):
|
|
existing = _DummyExistingLayer("L1")
|
|
mock_project_instance.return_value = _DummyProject(layers=[existing])
|
|
_DummyMessageBox.next_reply = _DummyMessageBox.StandardButton.No
|
|
|
|
layer, status = vg._check_existing_layer(tab_widget=None)
|
|
|
|
self.assertIs(layer, existing)
|
|
self.assertEqual(status, vg.LoadStatus.KEEP)
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="")
|
|
def test_verfahrensgebiet_alkis_fails_when_verfahrensnummer_missing(self, _mock_get_var):
|
|
_DummyMessageBox.last_critical = None
|
|
|
|
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
|
|
|
|
self.assertIsNone(layer)
|
|
self.assertEqual(status, vg.LoadStatus.NONE)
|
|
self.assertIsNotNone(_DummyMessageBox.last_critical)
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
|
|
def test_verfahrensgebiet_alkis_fails_on_invalid_wfs_layer(self, mock_qgsvectorlayer, _mock_get_var, _mock_check):
|
|
_DummyMessageBox.last_critical = None
|
|
mock_qgsvectorlayer.return_value = _DummyTempLayer(valid=False)
|
|
|
|
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
|
|
|
|
self.assertIsNone(layer)
|
|
self.assertEqual(status, vg.LoadStatus.NONE)
|
|
self.assertIsNotNone(_DummyMessageBox.last_critical)
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsFeature")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsGeometry.unaryUnion", return_value=_DummyGeom(empty=False))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
def test_verfahrensgebiet_alkis_success_single_kombination(self, mock_qgsvectorlayer, _mock_get_var, _mock_check, _mock_union, mock_feature_cls):
|
|
"""Einzelne (adv_name, bezeichnung)-Kombination → kein Dialog, Memory-Layer zurück."""
|
|
feat = _DummyFeature(attrs={"adv_name": "Bodensanierung", "bezeichnung": "VKZ12/001"})
|
|
temp_layer = _DummyTempLayer(valid=True, features=[feat])
|
|
memory_layer = _DummyMemoryLayer()
|
|
mock_qgsvectorlayer.side_effect = [temp_layer, memory_layer]
|
|
|
|
mock_feature = mock_feature_cls.return_value
|
|
mock_feature.setGeometry.return_value = None
|
|
mock_feature.setAttributes.return_value = None
|
|
|
|
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
|
|
|
|
self.assertIs(layer, memory_layer)
|
|
self.assertEqual(status, vg.LoadStatus.FIRST)
|
|
self.assertEqual(len(feats), 1)
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.ask_bror_kombination")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsFeature")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsGeometry.unaryUnion", return_value=_DummyGeom(empty=False))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
def test_verfahrensgebiet_alkis_multi_kombination_dialog_auswahl(
|
|
self, mock_qgsvectorlayer, _mock_get_var, _mock_check, _mock_union, mock_feature_cls, mock_dialog
|
|
):
|
|
"""Zwei verschiedene Kombinationen → Dialog wird gezeigt, gewählte Features genutzt."""
|
|
feat1 = _DummyFeature(attrs={"adv_name": "ADV-A", "bezeichnung": "VKZ12/001"})
|
|
feat2 = _DummyFeature(attrs={"adv_name": "ADV-B", "bezeichnung": "VKZ12/002"})
|
|
temp_layer = _DummyTempLayer(valid=True, features=[feat1, feat2])
|
|
memory_layer = _DummyMemoryLayer()
|
|
mock_qgsvectorlayer.side_effect = [temp_layer, memory_layer]
|
|
mock_dialog.return_value = ("ADV-A", "VKZ12/001")
|
|
|
|
mock_feature = mock_feature_cls.return_value
|
|
mock_feature.setGeometry.return_value = None
|
|
mock_feature.setAttributes.return_value = None
|
|
|
|
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
|
|
|
|
mock_dialog.assert_called_once()
|
|
self.assertIs(layer, memory_layer)
|
|
self.assertEqual(status, vg.LoadStatus.FIRST)
|
|
# Nur feat1 gehört zur gewählten Kombination
|
|
self.assertEqual(feats, [feat1])
|
|
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.ask_bror_kombination")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis._check_existing_layer", return_value=(None, vg.LoadStatus.FIRST))
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.get_variable", return_value="VKZ123")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QgsVectorLayer")
|
|
@patch("sn_verfahrensgebiet.functions.verfahrensgebiet_alkis.QMessageBox", new=_DummyMessageBox)
|
|
def test_verfahrensgebiet_alkis_multi_kombination_dialog_abbruch(
|
|
self, mock_qgsvectorlayer, _mock_get_var, _mock_check, mock_dialog
|
|
):
|
|
"""Zwei verschiedene Kombinationen → Nutzer bricht Dialog ab → NONE."""
|
|
feat1 = _DummyFeature(attrs={"adv_name": "ADV-A", "bezeichnung": "VKZ12/001"})
|
|
feat2 = _DummyFeature(attrs={"adv_name": "ADV-B", "bezeichnung": "VKZ12/002"})
|
|
temp_layer = _DummyTempLayer(valid=True, features=[feat1, feat2])
|
|
mock_qgsvectorlayer.return_value = temp_layer
|
|
mock_dialog.return_value = None # Nutzer bricht ab
|
|
|
|
layer, status, feats = vg.verfahrensgebiet_alkis(tab_widget=None)
|
|
|
|
mock_dialog.assert_called_once()
|
|
self.assertIsNone(layer)
|
|
self.assertEqual(status, vg.LoadStatus.NONE)
|
|
self.assertEqual(feats, [])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|