Skip to content

Commit 930ce54

Browse files
committedDec 20, 2016
Fix failing tests
1 parent c4a0c47 commit 930ce54

17 files changed

+293
-205
lines changed
 

‎python/gui/editorwidgets/qgsvaluerelationsearchwidgetwrapper.sip

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ class QgsValueRelationSearchWidgetWrapper : QgsSearchWidgetWrapper
2828
QWidget* createWidget( QWidget* parent );
2929
void initWidget( QWidget* editor );
3030

31+
protected slots:
32+
void onValueChanged();
33+
34+
void setExpression( QString exp );
35+
3136
};

‎src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ADD_SUBDIRECTORY(gui)
55
ADD_SUBDIRECTORY(auth)
66
ADD_SUBDIRECTORY(providers)
77
ADD_SUBDIRECTORY(crssync)
8+
ADD_SUBDIRECTORY(test)
89

910
IF (WITH_DESKTOP)
1011
ADD_SUBDIRECTORY(app)

‎src/core/fieldkit/qgsvaluerelationfieldkit.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,47 +47,50 @@ QString QgsValueRelationFieldKit::representValue( QgsVectorLayer* layer, int fie
4747
Q_UNUSED( layer )
4848
Q_UNUSED( fieldIndex )
4949

50-
QHash<QString, QString> vrCache;
50+
QgsValueRelationFieldKit::ValueRelationCache vrCache;
5151

5252
if ( cache.isValid() )
5353
{
54-
vrCache = cache.value<QHash<QString, QString>>();
54+
vrCache = cache.value<QgsValueRelationFieldKit::ValueRelationCache>();
5555
}
5656
else
5757
{
58-
vrCache = createCache( layer, fieldIndex, config ).value<QHash<QString, QString>>();
58+
vrCache = QgsValueRelationFieldKit::createCache( config );
5959
}
6060

61-
if ( config.value( QStringLiteral( "AllowMulti" ) ).toBool() )
61+
if ( config.value( "AllowMulti" ).toBool() )
6262
{
6363
QStringList keyList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( ',' );
6464
QStringList valueList;
6565

66-
Q_FOREACH ( const QString& key, keyList )
66+
Q_FOREACH ( const QgsValueRelationFieldKit::ValueRelationItem& item, vrCache )
6767
{
68-
auto val = vrCache.constFind( key );
69-
if ( val != vrCache.constEnd() )
70-
valueList << val.value();
71-
else
72-
valueList << QStringLiteral( "(%1)" ).arg( key );
68+
if ( keyList.contains( item.key.toString() ) )
69+
{
70+
valueList << item.value;
71+
}
7372
}
7473

75-
return valueList.join( QStringLiteral( ", " ) ).prepend( '{' ).append( '}' );
74+
return valueList.join( ", " ).prepend( '{' ).append( '}' );
7675
}
7776
else
7877
{
7978
if ( value.isNull() )
8079
{
8180
QSettings settings;
82-
return settings.value( QStringLiteral( "qgis/nullValue" ), "NULL" ).toString();
81+
return settings.value( "qgis/nullValue", "NULL" ).toString();
8382
}
8483

85-
auto val = vrCache.constFind( value.toString() );
86-
if ( val != vrCache.constEnd() )
87-
return val.value();
84+
Q_FOREACH ( const QgsValueRelationFieldKit::ValueRelationItem& item, vrCache )
85+
{
86+
if ( item.key == value )
87+
{
88+
return item.value;
89+
}
90+
}
8891
}
8992

90-
return QStringLiteral( "(%1)" ).arg( value.toString() );
93+
return QString( "(%1)" ).arg( value.toString() );
9194
}
9295

9396
QVariant QgsValueRelationFieldKit::sortValue( QgsVectorLayer* layer, int fieldIndex, const QVariantMap& config, const QVariant& cache, const QVariant& value ) const

‎src/core/qgsconfigurationmap.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,13 @@ QVariant QgsConfigurationMap::fromXmlHelper( const QDomElement& element ) const
116116
else if ( type == QLatin1String( "Map" ) )
117117
{
118118
QVariantMap map;
119-
QDomNodeList options = element.elementsByTagName( QStringLiteral( "Option" ) );
119+
QDomNodeList options = element.childNodes();
120120

121121
for ( int i = 0; i < options.count(); ++i )
122122
{
123123
QDomElement elem = options.at( i ).toElement();
124-
map.insert( elem.attribute( QStringLiteral( "name" ) ), fromXmlHelper( elem ) );
124+
if ( elem.tagName() == QLatin1String( "Option" ) )
125+
map.insert( elem.attribute( QStringLiteral( "name" ) ), fromXmlHelper( elem ) );
125126
}
126127
return map;
127128
}

‎src/core/qgsfieldkit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class QgsVectorLayer;
3333
*
3434
* This is an abstract base class and will always need to be subclassed.
3535
*
36-
* @Note added in QGIS 3.0
36+
* @note added in QGIS 3.0
3737
*/
3838
class CORE_EXPORT QgsFieldKit
3939
{

‎src/gui/editorwidgets/qgsvaluerelationsearchwidgetwrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class GUI_EXPORT QgsValueRelationSearchWidgetWrapper : public QgsSearchWidgetWra
5252
QWidget* createWidget( QWidget* parent ) override;
5353
void initWidget( QWidget* editor ) override;
5454

55-
private slots:
55+
protected slots:
5656
//! Called when current value of search widget changes
5757
void onValueChanged();
5858

‎src/test/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# for installing headers
2+
3+
SET(QGIS_TEST_HDRS
4+
qgstest.h
5+
)
6+
7+
INSTALL(FILES ${QGIS_TEST_HDRS} DESTINATION ${QGIS_INCLUDE_DIR})

‎src/test/qgstest.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/***************************************************************************
2+
qgstest - %{Cpp:License:ClassName}
3+
4+
---------------------
5+
begin : 5.12.2016
6+
copyright : (C) 2016 by Matthias Kuhn
7+
email : matthias@opengis.ch
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSTEST_H
17+
#define QGSTEST_H
18+
19+
#define QGSTEST_MAIN(TestObject) \
20+
QT_BEGIN_NAMESPACE \
21+
QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
22+
QT_END_NAMESPACE \
23+
int main(int argc, char *argv[]) \
24+
{ \
25+
QgsApplication app(argc, argv, false); \
26+
app.setAttribute(Qt::AA_Use96Dpi, true); \
27+
QTEST_DISABLE_KEYPAD_NAVIGATION \
28+
QTEST_ADD_GPU_BLACKLIST_SUPPORT \
29+
TestObject tc; \
30+
QTEST_SET_MAIN_SOURCE_PATH \
31+
return QTest::qExec(&tc, argc, argv); \
32+
}
33+
34+
35+
#endif // QGSTEST_H

‎tests/src/app/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
1010
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/raster
1111
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/symbology-ng
1212
${CMAKE_CURRENT_BINARY_DIR}/../../../src/ui
13+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/ui
1314
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui
1415
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/editorwidgets
1516
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/gui/editorwidgets/core
@@ -19,7 +20,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
1920
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/python
2021
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/app
2122
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/app/pluginmanager
22-
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/ui
23+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/test
2324
)
2425
INCLUDE_DIRECTORIES(SYSTEM
2526
${QT_INCLUDE_DIR}

‎tests/src/app/testqgsattributetable.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "qgsmapcanvas.h"
2626
#include "qgsunittypes.h"
2727

28+
#include "qgstest.h"
29+
2830
/** \ingroup UnitTests
2931
* This is a unit test for the attribute table dialog
3032
*/
@@ -167,5 +169,5 @@ void TestQgsAttributeTable::testFieldCalculationArea()
167169
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
168170
}
169171

170-
QTEST_MAIN( TestQgsAttributeTable )
172+
QGSTEST_MAIN( TestQgsAttributeTable )
171173
#include "testqgsattributetable.moc"

‎tests/src/gui/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
1919
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/geometry
2020
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/raster
2121
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core/symbology-ng
22+
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/test
2223
)
2324
INCLUDE_DIRECTORIES(SYSTEM
2425
${QT_INCLUDE_DIR}

‎tests/src/gui/testqgsdualview.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <qgsmapcanvas.h>
2828
#include <qgsfeature.h>
2929

30+
#include "qgstest.h"
31+
3032
class TestQgsDualView : public QObject
3133
{
3234
Q_OBJECT
@@ -67,6 +69,7 @@ void TestQgsDualView::initTestCase()
6769
QgsApplication::init();
6870
QgsApplication::initQgis();
6971
QgsApplication::showSettings();
72+
7073
QgsEditorWidgetRegistry::initEditors();
7174

7275
// Setup a map canvas with a vector layer loaded...
@@ -267,9 +270,5 @@ void TestQgsDualView::testAttributeFormSharedValueScanning()
267270
QVERIFY( mixedValueFields.isEmpty() );
268271
}
269272

270-
QTEST_MAIN( TestQgsDualView )
273+
QGSTEST_MAIN( TestQgsDualView )
271274
#include "testqgsdualview.moc"
272-
273-
274-
275-

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ ADD_PYTHON_TEST(PyQgsEditWidgets test_qgseditwidgets.py)
4545
ADD_PYTHON_TEST(PyQgsExpression test_qgsexpression.py)
4646
ADD_PYTHON_TEST(PyQgsExpressionLineEdit test_qgsexpressionlineedit.py)
4747
ADD_PYTHON_TEST(PyQgsFeature test_qgsfeature.py)
48+
ADD_PYTHON_TEST(PyQgsFieldKitsTest test_qgsfieldkits.py)
4849
ADD_PYTHON_TEST(PyQgsProject test_qgsproject.py)
4950
ADD_PYTHON_TEST(PyQgsFeatureIterator test_qgsfeatureiterator.py)
5051
ADD_PYTHON_TEST(PyQgsField test_qgsfield.py)

‎tests/src/python/test_qgsconfigurationmap.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_integer(self):
5252
prop2 = QgsConfigurationMap()
5353

5454
prop2.fromXml(element)
55-
self.assertEquals(prop2.get(), my_properties)
55+
self.assertEquals(my_properties, prop2.get())
5656

5757
def test_string(self):
5858
"""
@@ -69,7 +69,7 @@ def test_string(self):
6969
prop2 = QgsConfigurationMap()
7070

7171
prop2.fromXml(element)
72-
self.assertEquals(prop2.get(), my_properties)
72+
self.assertEquals(my_properties, prop2.get())
7373

7474
def test_double(self):
7575
"""
@@ -86,7 +86,7 @@ def test_double(self):
8686
prop2 = QgsConfigurationMap()
8787

8888
prop2.fromXml(element)
89-
self.assertEquals(prop2.get(), my_properties)
89+
self.assertEquals(my_properties, prop2.get())
9090

9191
def test_boolean(self):
9292
"""
@@ -105,7 +105,7 @@ def test_boolean(self):
105105
prop2 = QgsConfigurationMap()
106106

107107
prop2.fromXml(element)
108-
self.assertEquals(prop2.get(), my_properties)
108+
self.assertEquals(my_properties, prop2.get())
109109

110110
def test_complex(self):
111111
"""
@@ -124,7 +124,7 @@ def test_complex(self):
124124
prop2 = QgsConfigurationMap()
125125

126126
prop2.fromXml(element)
127-
self.assertEquals(prop2.get(), my_properties)
127+
self.assertEquals(my_properties, prop2.get())
128128

129129

130130
if __name__ == '__main__':

‎tests/src/python/test_qgseditwidgets.py

Lines changed: 2 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -95,190 +95,20 @@ def testStringWithMaxLen(self):
9595

9696
QgsProject.instance().removeAllMapLayers()
9797

98-
def test_ValueMap_representValue(self):
99-
layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string",
100-
"layer", "memory")
101-
assert layer.isValid()
102-
QgsProject.instance().addMapLayer(layer)
103-
f = QgsFeature()
104-
f.setAttributes([2, 2.5, 'NULL', None, None, None])
105-
assert layer.dataProvider().addFeatures([f])
106-
reg = QgsEditorWidgetRegistry.instance()
107-
factory = reg.factory("ValueMap")
108-
self.assertIsNotNone(factory)
109-
110-
# Tests with different value types occurring in the value map
111-
config = {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL',
112-
'nothing': self.VALUEMAP_NULL_TEXT}
113-
self.assertEqual(factory.representValue(layer, 0, config, None, 2), 'two')
114-
self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), 'twoandhalf')
115-
self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), 'NULL text')
116-
# Tests with null values of different types, if value map contains null
117-
self.assertEqual(factory.representValue(layer, 3, config, None, None), 'nothing')
118-
self.assertEqual(factory.representValue(layer, 4, config, None, None), 'nothing')
119-
self.assertEqual(factory.representValue(layer, 5, config, None, None), 'nothing')
120-
# Tests with fallback display for different value types
121-
config = {}
122-
self.assertEqual(factory.representValue(layer, 0, config, None, 2), '(2)')
123-
self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), '(2.50000)')
124-
self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), '(NULL)')
125-
# Tests with fallback display for null in different types of fields
126-
self.assertEqual(factory.representValue(layer, 3, config, None, None), '(NULL)')
127-
self.assertEqual(factory.representValue(layer, 4, config, None, None), '(NULL)')
128-
self.assertEqual(factory.representValue(layer, 5, config, None, None), '(NULL)')
129-
130-
QgsProject.instance().removeAllMapLayers()
131-
13298
def test_ValueMap_set_get(self):
13399
layer = QgsVectorLayer("none?field=number:integer", "layer", "memory")
134100
assert layer.isValid()
135101
QgsProject.instance().addMapLayer(layer)
136102
reg = QgsEditorWidgetRegistry.instance()
137103
configWdg = reg.createConfigWidget('ValueMap', layer, 0, None)
138104

139-
config = {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL',
140-
'nothing': self.VALUEMAP_NULL_TEXT}
105+
config = {'map': {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL',
106+
'nothing': self.VALUEMAP_NULL_TEXT}}
141107

142108
# Set a configuration containing values and NULL and check if it
143109
# is returned intact.
144110
configWdg.setConfig(config)
145111
self.assertEqual(configWdg.config(), config)
146112

147113
QgsProject.instance().removeAllMapLayers()
148-
149-
def test_ValueRelation_representValue(self):
150-
151-
first_layer = QgsVectorLayer("none?field=foreign_key:integer",
152-
"first_layer", "memory")
153-
assert first_layer.isValid()
154-
second_layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string",
155-
"second_layer", "memory")
156-
assert second_layer.isValid()
157-
QgsProject.instance().addMapLayer(second_layer)
158-
f = QgsFeature()
159-
f.setAttributes([123])
160-
assert first_layer.dataProvider().addFeatures([f])
161-
f = QgsFeature()
162-
f.setAttributes([123, 'decoded_val'])
163-
assert second_layer.dataProvider().addFeatures([f])
164-
165-
reg = QgsEditorWidgetRegistry.instance()
166-
factory = reg.factory("ValueRelation")
167-
self.assertIsNotNone(factory)
168-
169-
# Everything valid
170-
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'decoded'}
171-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), 'decoded_val')
172-
173-
# Code not find match in foreign layer
174-
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'decoded'}
175-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '(456)')
176-
177-
# Missing Layer
178-
config = {'Key': 'pkid', 'Value': 'decoded'}
179-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '(456)')
180-
181-
# Invalid Layer
182-
config = {'Layer': 'invalid', 'Key': 'pkid', 'Value': 'decoded'}
183-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '(456)')
184-
185-
# Invalid Key
186-
config = {'Layer': second_layer.id(), 'Key': 'invalid', 'Value': 'decoded'}
187-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '(456)')
188-
189-
# Invalid Value
190-
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'invalid'}
191-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '(456)')
192-
193-
QgsProject.instance().removeMapLayer(second_layer.id())
194-
195-
def test_RelationReference_representValue(self):
196-
197-
first_layer = QgsVectorLayer("none?field=foreign_key:integer",
198-
"first_layer", "memory")
199-
assert first_layer.isValid()
200-
second_layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string",
201-
"second_layer", "memory")
202-
assert second_layer.isValid()
203-
QgsProject.instance().addMapLayers([first_layer, second_layer])
204-
f = QgsFeature()
205-
f.setAttributes([123])
206-
assert first_layer.dataProvider().addFeatures([f])
207-
f = QgsFeature()
208-
f.setAttributes([123, 'decoded_val'])
209-
assert second_layer.dataProvider().addFeatures([f])
210-
211-
relMgr = QgsProject.instance().relationManager()
212-
213-
reg = QgsEditorWidgetRegistry.instance()
214-
factory = reg.factory("RelationReference")
215-
self.assertIsNotNone(factory)
216-
217-
rel = QgsRelation()
218-
rel.setRelationId('rel1')
219-
rel.setRelationName('Relation Number One')
220-
rel.setReferencingLayer(first_layer.id())
221-
rel.setReferencedLayer(second_layer.id())
222-
rel.addFieldPair('foreign_key', 'pkid')
223-
assert(rel.isValid())
224-
225-
relMgr.addRelation(rel)
226-
227-
# Everything valid
228-
config = {'Relation': rel.id()}
229-
second_layer.setDisplayExpression('decoded')
230-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), 'decoded_val')
231-
232-
# Code not find match in foreign layer
233-
config = {'Relation': rel.id()}
234-
second_layer.setDisplayExpression('decoded')
235-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '456'), '456')
236-
237-
# Invalid relation id
238-
config = {'Relation': 'invalid'}
239-
second_layer.setDisplayExpression('decoded')
240-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), '123')
241-
242-
# No display expression
243-
config = {'Relation': rel.id()}
244-
second_layer.setDisplayExpression(None)
245-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), '123')
246-
247-
# Invalid display expression
248-
config = {'Relation': rel.id()}
249-
second_layer.setDisplayExpression('invalid +')
250-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), '123')
251-
252-
# Missing relation
253-
config = {}
254-
second_layer.setDisplayExpression('decoded')
255-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), '123')
256-
257-
# Inconsistent layer provided to representValue()
258-
config = {'Relation': rel.id()}
259-
second_layer.setDisplayExpression('decoded')
260-
self.assertEqual(factory.representValue(second_layer, 0, config, None, '123'), '123')
261-
262-
# Inconsistent idx provided to representValue()
263-
config = {'Relation': rel.id()}
264-
second_layer.setDisplayExpression('decoded')
265-
self.assertEqual(factory.representValue(first_layer, 1, config, None, '123'), '123')
266-
267-
# Invalid relation
268-
rel = QgsRelation()
269-
rel.setRelationId('rel2')
270-
rel.setRelationName('Relation Number Two')
271-
rel.setReferencingLayer(first_layer.id())
272-
rel.addFieldPair('foreign_key', 'pkid')
273-
self.assertFalse(rel.isValid())
274-
275-
relMgr.addRelation(rel)
276-
277-
config = {'Relation': rel.id()}
278-
second_layer.setDisplayExpression('decoded')
279-
self.assertEqual(factory.representValue(first_layer, 0, config, None, '123'), '123')
280-
281-
QgsProject.instance().removeAllMapLayers()
282-
283-
if __name__ == '__main__':
284114
unittest.main()

‎tests/src/python/test_qgsfieldkits.py

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for field kits.
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Matthias Kuhn'
10+
__date__ = '05/12/2016'
11+
__copyright__ = 'Copyright 2016, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
from qgis.core import (QgsMapLayerRegistry, QgsFeature, QgsGeometry, QgsPoint,
18+
QgsProject, QgsRelation, QgsVectorLayer, NULL, QgsField,
19+
QgsValueMapFieldKit, QgsValueRelationFieldKit,
20+
QgsRelationReferenceFieldKit)
21+
22+
from qgis.testing import start_app, unittest
23+
from qgis.PyQt.QtCore import QVariant
24+
from qgis.PyQt.QtWidgets import QTextEdit
25+
26+
start_app()
27+
28+
29+
class TestQgsValueMapFieldKit(unittest.TestCase):
30+
31+
VALUEMAP_NULL_TEXT = "{2839923C-8B7D-419E-B84B-CA2FE9B80EC7}"
32+
33+
def test_representValue(self):
34+
layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string",
35+
"layer", "memory")
36+
self.assertTrue(layer.isValid())
37+
QgsMapLayerRegistry.instance().addMapLayer(layer)
38+
f = QgsFeature()
39+
f.setAttributes([2, 2.5, 'NULL', None, None, None])
40+
layer.dataProvider().addFeatures([f])
41+
fieldKit = QgsValueMapFieldKit()
42+
43+
# Tests with different value types occurring in the value map
44+
config = {'map': {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL',
45+
'nothing': self.VALUEMAP_NULL_TEXT}}
46+
self.assertEqual(fieldKit.representValue(layer, 0, config, None, 2), 'two')
47+
self.assertEqual(fieldKit.representValue(layer, 1, config, None, 2.5), 'twoandhalf')
48+
self.assertEqual(fieldKit.representValue(layer, 2, config, None, 'NULL'), 'NULL text')
49+
# Tests with null values of different types, if value map contains null
50+
self.assertEqual(fieldKit.representValue(layer, 3, config, None, None), 'nothing')
51+
self.assertEqual(fieldKit.representValue(layer, 4, config, None, None), 'nothing')
52+
self.assertEqual(fieldKit.representValue(layer, 5, config, None, None), 'nothing')
53+
# Tests with fallback display for different value types
54+
config = {}
55+
self.assertEqual(fieldKit.representValue(layer, 0, config, None, 2), '(2)')
56+
self.assertEqual(fieldKit.representValue(layer, 1, config, None, 2.5), '(2.50000)')
57+
self.assertEqual(fieldKit.representValue(layer, 2, config, None, 'NULL'), '(NULL)')
58+
# Tests with fallback display for null in different types of fields
59+
self.assertEqual(fieldKit.representValue(layer, 3, config, None, None), '(NULL)')
60+
self.assertEqual(fieldKit.representValue(layer, 4, config, None, None), '(NULL)')
61+
self.assertEqual(fieldKit.representValue(layer, 5, config, None, None), '(NULL)')
62+
63+
QgsMapLayerRegistry.instance().removeAllMapLayers()
64+
65+
66+
class TestQgsValueRelationFieldKit(unittest.TestCase):
67+
68+
def test_representValue(self):
69+
70+
first_layer = QgsVectorLayer("none?field=foreign_key:integer",
71+
"first_layer", "memory")
72+
self.assertTrue(first_layer.isValid())
73+
second_layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string",
74+
"second_layer", "memory")
75+
self.assertTrue(second_layer.isValid())
76+
QgsMapLayerRegistry.instance().addMapLayer(second_layer)
77+
f = QgsFeature()
78+
f.setAttributes([123])
79+
first_layer.dataProvider().addFeatures([f])
80+
f = QgsFeature()
81+
f.setAttributes([123, 'decoded_val'])
82+
second_layer.dataProvider().addFeatures([f])
83+
84+
fieldKit = QgsValueRelationFieldKit()
85+
86+
# Everything valid
87+
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'decoded'}
88+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), 'decoded_val')
89+
90+
# Code not find match in foreign layer
91+
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'decoded'}
92+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '(456)')
93+
94+
# Missing Layer
95+
config = {'Key': 'pkid', 'Value': 'decoded'}
96+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '(456)')
97+
98+
# Invalid Layer
99+
config = {'Layer': 'invalid', 'Key': 'pkid', 'Value': 'decoded'}
100+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '(456)')
101+
102+
# Invalid Key
103+
config = {'Layer': second_layer.id(), 'Key': 'invalid', 'Value': 'decoded'}
104+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '(456)')
105+
106+
# Invalid Value
107+
config = {'Layer': second_layer.id(), 'Key': 'pkid', 'Value': 'invalid'}
108+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '(456)')
109+
110+
QgsMapLayerRegistry.instance().removeMapLayer(second_layer.id())
111+
112+
113+
class TestQgsRelationReferenceFieldKit(unittest.TestCase):
114+
115+
def test_representValue(self):
116+
117+
first_layer = QgsVectorLayer("none?field=foreign_key:integer",
118+
"first_layer", "memory")
119+
self.assertTrue(first_layer.isValid())
120+
second_layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string",
121+
"second_layer", "memory")
122+
self.assertTrue(second_layer.isValid())
123+
QgsMapLayerRegistry.instance().addMapLayers([first_layer, second_layer])
124+
f = QgsFeature()
125+
f.setAttributes([123])
126+
first_layer.dataProvider().addFeatures([f])
127+
f = QgsFeature()
128+
f.setAttributes([123, 'decoded_val'])
129+
second_layer.dataProvider().addFeatures([f])
130+
131+
relMgr = QgsProject.instance().relationManager()
132+
133+
fieldKit = QgsRelationReferenceFieldKit()
134+
135+
rel = QgsRelation()
136+
rel.setRelationId('rel1')
137+
rel.setRelationName('Relation Number One')
138+
rel.setReferencingLayer(first_layer.id())
139+
rel.setReferencedLayer(second_layer.id())
140+
rel.addFieldPair('foreign_key', 'pkid')
141+
self.assertTrue(rel.isValid())
142+
143+
relMgr.addRelation(rel)
144+
145+
# Everything valid
146+
config = {'Relation': rel.id()}
147+
second_layer.setDisplayExpression('decoded')
148+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), 'decoded_val')
149+
150+
# Code not find match in foreign layer
151+
config = {'Relation': rel.id()}
152+
second_layer.setDisplayExpression('decoded')
153+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '456'), '456')
154+
155+
# Invalid relation id
156+
config = {'Relation': 'invalid'}
157+
second_layer.setDisplayExpression('decoded')
158+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), '123')
159+
160+
# No display expression
161+
config = {'Relation': rel.id()}
162+
second_layer.setDisplayExpression(None)
163+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), '123')
164+
165+
# Invalid display expression
166+
config = {'Relation': rel.id()}
167+
second_layer.setDisplayExpression('invalid +')
168+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), '123')
169+
170+
# Missing relation
171+
config = {}
172+
second_layer.setDisplayExpression('decoded')
173+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), '123')
174+
175+
# Inconsistent layer provided to representValue()
176+
config = {'Relation': rel.id()}
177+
second_layer.setDisplayExpression('decoded')
178+
self.assertEqual(fieldKit.representValue(second_layer, 0, config, None, '123'), '123')
179+
180+
# Inconsistent idx provided to representValue()
181+
config = {'Relation': rel.id()}
182+
second_layer.setDisplayExpression('decoded')
183+
self.assertEqual(fieldKit.representValue(first_layer, 1, config, None, '123'), '123')
184+
185+
# Invalid relation
186+
rel = QgsRelation()
187+
rel.setRelationId('rel2')
188+
rel.setRelationName('Relation Number Two')
189+
rel.setReferencingLayer(first_layer.id())
190+
rel.addFieldPair('foreign_key', 'pkid')
191+
self.assertFalse(rel.isValid())
192+
193+
relMgr.addRelation(rel)
194+
195+
config = {'Relation': rel.id()}
196+
second_layer.setDisplayExpression('decoded')
197+
self.assertEqual(fieldKit.representValue(first_layer, 0, config, None, '123'), '123')
198+
199+
QgsMapLayerRegistry.instance().removeAllMapLayers()
200+
201+
if __name__ == '__main__':
202+
unittest.main()

‎tests/testdata/provider/testdata_pg.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ CREATE TABLE qgis_test.widget_styles(
457457
);
458458

459459
INSERT INTO qgis_editor_widget_styles VALUES
460-
('qgis_test', 'widget_styles', 'fld1', 'FooEdit', '<config><option key="param1" value="value1"/><option key="param2" value="2"/></config>');
460+
('qgis_test', 'widget_styles', 'fld1', 'FooEdit', '<config type="Map"><Option name="param1" value="value1" type="String"/><Option name="param2" value="2" type="String"/></config>');
461461

462462

463463
-----------------------------

0 commit comments

Comments
 (0)
Please sign in to comment.