From 7737cf6b6bb8e6b7c4abccb6c30c570717658585 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Thu, 6 Jun 2019 11:59:59 +0200 Subject: [PATCH] Add test for double widgets in a form --- tests/src/python/CMakeLists.txt | 1 + tests/src/python/test_qgsattributeform.py | 120 ++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tests/src/python/test_qgsattributeform.py diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 96d9afd19c2..2c8f9799703 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -17,6 +17,7 @@ ADD_PYTHON_TEST(PyQgsAggregateCalculator test_qgsaggregatecalculator.py) ADD_PYTHON_TEST(PyQgsAnnotation test_qgsannotation.py) ADD_PYTHON_TEST(PyQgsApplication test_qgsapplication.py) ADD_PYTHON_TEST(PyQgsAttributeFormEditorWidget test_qgsattributeformeditorwidget.py) +ADD_PYTHON_TEST(PyQgsAttributeForm test_qgsattributeform.py) ADD_PYTHON_TEST(PyQgsAttributeTableConfig test_qgsattributetableconfig.py) ADD_PYTHON_TEST(PyQgsAttributeTableModel test_qgsattributetablemodel.py) ADD_PYTHON_TEST(PyQgsAuthenticationSystem test_qgsauthsystem.py) diff --git a/tests/src/python/test_qgsattributeform.py b/tests/src/python/test_qgsattributeform.py new file mode 100644 index 00000000000..3fc2476dc5f --- /dev/null +++ b/tests/src/python/test_qgsattributeform.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for the attribute form + + +Run with ctest -V -R PyQgsAttributeForm + +.. note:: This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +""" +__author__ = 'Alessandro Pasotti' +__date__ = '2019-06-06' +__copyright__ = 'Copyright 2019, The QGIS Project' + + +from qgis.testing import start_app, unittest +from qgis.core import ( + QgsFields, + QgsVectorLayer, + QgsFeature, + QgsEditorWidgetSetup, + QgsEditFormConfig, + QgsAttributeEditorElement, +) +from qgis.gui import ( + QgsAttributeForm, + QgsGui, + QgsEditorWidgetWrapper, +) + + +QGISAPP = start_app() + + +class TestQgsAttributeForm(unittest.TestCase): + + @classmethod + def setUpClass(cls): + QgsGui.editorWidgetRegistry().initEditors() + + @classmethod + def createLayerWithOnePoint(cls, field_type): + layer = QgsVectorLayer("Point?field=fld:%s" % field_type, + "vl", "memory") + pr = layer.dataProvider() + f = QgsFeature() + assert pr.addFeatures([f]) + assert layer.featureCount() == 1 + return layer + + @classmethod + def createFormWithDuplicateWidget(cls, vl, field_type, widget_type): + """Creates a form with two identical widgets for the same field""" + + config = vl.editFormConfig() + config.setLayout(QgsEditFormConfig.TabLayout) + element = config.tabs()[0] + element2 = element.clone(element) + config.addTab(element2) + vl.setEditFormConfig(config) + vl.setEditorWidgetSetup(0, QgsEditorWidgetSetup(widget_type, {})) + form = QgsAttributeForm(vl, next(vl.getFeatures())) + assert (form.editable()) + return form + + @classmethod + def get_widgets_for_field(cls, vl): + """Get compatible widget names""" + + return [k for k, v in QgsGui.editorWidgetRegistry().factories().items() if v.supportsField(vl, 0)] + + @classmethod + def checkForm(cls, field_type, value): + """Creates a vector layer and an associated form with two identical widgets for the same field and test it with NULL and after setting a value + """ + + vl = cls.createLayerWithOnePoint(field_type) + assert (vl.startEditing()) + for widget_type in cls.get_widgets_for_field(vl): + form = cls.createFormWithDuplicateWidget(vl, field_type, widget_type) + vl.changeAttributeValue(1, 0, value) + form.setFeature(next(vl.getFeatures())) + + def test_duplicated_widgets(self): + """ + Note: this crashed two times for datetime (see GH #29937): + + - first crash with inital NULL values, because widget's clear() triggered changed() + - second crash when setting a value, because setDateTime() triggered changed() + + There are no assertions in this test because we are looking for a crash. + """ + + field_types = { + 'integer': 123, + 'double': 123.45, + 'string': 'lorem ipsum', + 'date': '2019-01-01', + 'time': '12:12:12', + 'datetime': '2019-01-01', + 'int2': 123, + 'int4': 123, + 'int8': 123, + 'numeric': 123.45, + 'decimal': 123.45, + 'real': 123.45, + 'double precision': 123.45, + 'text': 'lorem ipsum', + 'bool': True, + #'binary' + } + + for field_type, value in field_types.items(): + self.checkForm(field_type, value) + + +if __name__ == '__main__': + unittest.main()