1 /***************************************************************************
2 test_template.cpp
3 --------------------------------------
4 Date : Sun Sep 16 12:22:23 AKDT 2007
5 Copyright : (C) 2007 by Gary E. Sherman
6 Email : sherman at mrcc dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgstest.h"
17 #include <QObject>
18 #include <QString>
19 #include <QStringList>
20 #include <QApplication>
21 #include <QFileInfo>
22 #include <QDir>
23 #include <QDesktopServices>
24
25 //qgis includes...
26 #include <qgsgeometry.h>
27 #include <qgsmaplayer.h>
28 #include <qgsvectordataprovider.h>
29 #include <qgsvectorlayer.h>
30 #include <qgsvectorlayerutils.h>
31 #include "qgsfeatureiterator.h"
32 #include <qgsapplication.h>
33 #include <qgsproviderregistry.h>
34 #include <qgsproject.h>
35 #include <qgssymbol.h>
36 #include <qgssinglesymbolrenderer.h>
37 //qgis test includes
38 #include "qgsrenderchecker.h"
39
40 class TestSignalReceiver : public QObject
41 {
42 Q_OBJECT
43
44 public:
TestSignalReceiver()45 TestSignalReceiver()
46 : QObject( nullptr )
47 , featureBlendMode( QPainter::CompositionMode( 0 ) )
48 {}
49 bool rendererChanged = false ;
50 QPainter::CompositionMode featureBlendMode;
51 double opacity = 1.0 ;
52 public slots:
onRendererChanged()53 void onRendererChanged()
54 {
55 rendererChanged = true;
56 }
onFeatureBlendModeChanged(const QPainter::CompositionMode blendMode)57 void onFeatureBlendModeChanged( const QPainter::CompositionMode blendMode )
58 {
59 featureBlendMode = blendMode;
60 }
onLayerOpacityChanged(double layerOpacity)61 void onLayerOpacityChanged( double layerOpacity )
62 {
63 opacity = layerOpacity;
64 }
65 };
66
67 /**
68 * \ingroup UnitTests
69 * This is a unit test for the vector layer class.
70 */
71 class TestQgsVectorLayer : public QObject
72 {
73 Q_OBJECT
74 public:
75 TestQgsVectorLayer() = default;
76
77 private:
78 bool mTestHasError = false ;
79 QgsMapLayer *mpPointsLayer = nullptr;
80 QgsMapLayer *mpLinesLayer = nullptr;
81 QgsMapLayer *mpPolysLayer = nullptr;
82 QgsVectorLayer *mpNonSpatialLayer = nullptr;
83 QString mTestDataDir;
84 QString mReport;
85
86
87 private slots:
88
89 void initTestCase(); // will be called before the first testfunction is executed.
90 void cleanupTestCase(); // will be called after the last testfunction was executed.
init()91 void init() {} // will be called before each testfunction is executed.
cleanup()92 void cleanup() {} // will be called after every testfunction.
93
94 void QgsVectorLayerNonSpatialIterator();
95 void QgsVectorLayerGetValues();
96 void QgsVectorLayersetRenderer();
97 void QgsVectorLayersetFeatureBlendMode();
98 void QgsVectorLayersetLayerTransparency();
99 void uniqueValues();
100 void minimumValue();
101 void maximumValue();
102 void isSpatial();
103 void testAddTopologicalPoints();
104 void testCopyPasteFieldConfiguration();
105 void testCopyPasteFieldConfiguration_data();
106 };
107
initTestCase()108 void TestQgsVectorLayer::initTestCase()
109 {
110 mTestHasError = false;
111 QgsApplication::init();
112 QgsApplication::initQgis();
113 QgsApplication::showSettings();
114
115 //create some objects that will be used in all tests...
116
117 //
118 //create a non spatial layer that will be used in all tests...
119 //
120 QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
121 mTestDataDir = myDataDir + '/';
122 QString myDbfFileName = mTestDataDir + "nonspatial.dbf";
123 QFileInfo myDbfFileInfo( myDbfFileName );
124 mpNonSpatialLayer = new QgsVectorLayer( myDbfFileInfo.filePath(),
125 myDbfFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
126 // Register the layer with the registry
127 QgsProject::instance()->addMapLayers(
128 QList<QgsMapLayer *>() << mpNonSpatialLayer );
129 //
130 //create a point layer that will be used in all tests...
131 //
132 QString myPointsFileName = mTestDataDir + "points.shp";
133 QFileInfo myPointFileInfo( myPointsFileName );
134 mpPointsLayer = new QgsVectorLayer( myPointFileInfo.filePath(),
135 myPointFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
136 // Register the layer with the registry
137 QgsProject::instance()->addMapLayers(
138 QList<QgsMapLayer *>() << mpPointsLayer );
139
140 //
141 //create a poly layer that will be used in all tests...
142 //
143 QString myPolysFileName = mTestDataDir + "polys.shp";
144 QFileInfo myPolyFileInfo( myPolysFileName );
145 mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
146 myPolyFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
147 // Register the layer with the registry
148 QgsProject::instance()->addMapLayers(
149 QList<QgsMapLayer *>() << mpPolysLayer );
150
151
152 //
153 // Create a line layer that will be used in all tests...
154 //
155 QString myLinesFileName = mTestDataDir + "lines.shp";
156 QFileInfo myLineFileInfo( myLinesFileName );
157 mpLinesLayer = new QgsVectorLayer( myLineFileInfo.filePath(),
158 myLineFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
159 // Register the layer with the registry
160 QgsProject::instance()->addMapLayers(
161 QList<QgsMapLayer *>() << mpLinesLayer );
162
163 mReport += QLatin1String( "<h1>Vector Renderer Tests</h1>\n" );
164 }
165
cleanupTestCase()166 void TestQgsVectorLayer::cleanupTestCase()
167 {
168 QString myReportFile = QDir::tempPath() + "/qgistest.html";
169 QFile myFile( myReportFile );
170 if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
171 {
172 QTextStream myQTextStream( &myFile );
173 myQTextStream << mReport;
174 myFile.close();
175 //QDesktopServices::openUrl( "file:///" + myReportFile );
176 }
177 QgsApplication::exitQgis();
178 }
179
QgsVectorLayerNonSpatialIterator()180 void TestQgsVectorLayer::QgsVectorLayerNonSpatialIterator()
181 {
182 QgsFeature f;
183 QgsAttributeList myList;
184 myList << 0 << 1 << 2 << 3;
185 int myCount = 0;
186 QgsFeatureIterator fit = mpNonSpatialLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myList ) );
187 while ( fit.nextFeature( f ) )
188 {
189 qDebug( "Getting non-spatial feature from layer" );
190 myCount++;
191 }
192 QVERIFY( myCount == 3 );
193 }
194
QgsVectorLayerGetValues()195 void TestQgsVectorLayer::QgsVectorLayerGetValues()
196 {
197 QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:real" ), QStringLiteral( "layer" ), QStringLiteral( "memory" ) );
198 QVERIFY( layer->isValid() );
199 QgsFeature f1( layer->dataProvider()->fields(), 1 );
200 f1.setAttribute( QStringLiteral( "col1" ), 1 );
201 QgsFeature f2( layer->dataProvider()->fields(), 2 );
202 f2.setAttribute( QStringLiteral( "col1" ), 2 );
203 QgsFeature f3( layer->dataProvider()->fields(), 3 );
204 f3.setAttribute( QStringLiteral( "col1" ), 3 );
205 QgsFeature f4( layer->dataProvider()->fields(), 4 );
206 f4.setAttribute( QStringLiteral( "col1" ), QVariant() );
207 layer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 << f3 << f4 );
208
209 //make a selection
210 QgsFeatureIds ids;
211 ids << f2.id() << f3.id();
212 layer->selectByIds( ids );
213
214 bool ok;
215 QList<QVariant> varList = QgsVectorLayerUtils::getValues( layer, QStringLiteral( "col1" ), ok );
216 QVERIFY( ok );
217 QCOMPARE( varList.length(), 4 );
218 std::sort( varList.begin(), varList.end() );
219 QCOMPARE( varList.at( 0 ), QVariant() );
220 QCOMPARE( varList.at( 1 ), QVariant( 1 ) );
221 QCOMPARE( varList.at( 2 ), QVariant( 2 ) );
222 QCOMPARE( varList.at( 3 ), QVariant( 3 ) );
223
224 //check with selected features
225 varList = QgsVectorLayerUtils::getValues( layer, QStringLiteral( "col1" ), ok, true );
226 QVERIFY( ok );
227 QCOMPARE( varList.length(), 2 );
228 std::sort( varList.begin(), varList.end() );
229 QCOMPARE( varList.at( 0 ), QVariant( 2 ) );
230 QCOMPARE( varList.at( 1 ), QVariant( 3 ) );
231
232 int nulls = 0;
233 QList<double> doubleList = QgsVectorLayerUtils::getDoubleValues( layer, QStringLiteral( "col1" ), ok, false, &nulls );
234 QVERIFY( ok );
235 QCOMPARE( doubleList.length(), 3 );
236 std::sort( doubleList.begin(), doubleList.end() );
237 QCOMPARE( doubleList.at( 0 ), 1.0 );
238 QCOMPARE( doubleList.at( 1 ), 2.0 );
239 QCOMPARE( doubleList.at( 2 ), 3.0 );
240 QCOMPARE( nulls, 1 );
241
242 //check with selected features
243 doubleList = QgsVectorLayerUtils::getDoubleValues( layer, QStringLiteral( "col1" ), ok, true, &nulls );
244 QVERIFY( ok );
245 std::sort( doubleList.begin(), doubleList.end() );
246 QCOMPARE( doubleList.length(), 2 );
247 QCOMPARE( doubleList.at( 0 ), 2.0 );
248 QCOMPARE( doubleList.at( 1 ), 3.0 );
249 QCOMPARE( nulls, 0 );
250
251 QList<QVariant> expVarList = QgsVectorLayerUtils::getValues( layer, QStringLiteral( "tostring(col1) || ' '" ), ok );
252 QVERIFY( ok );
253 QCOMPARE( expVarList.length(), 4 );
254 std::sort( expVarList.begin(), expVarList.end() );
255 QCOMPARE( expVarList.at( 0 ), QVariant() );
256 QCOMPARE( expVarList.at( 1 ).toString(), QString( "1 " ) );
257 QCOMPARE( expVarList.at( 2 ).toString(), QString( "2 " ) );
258 QCOMPARE( expVarList.at( 3 ).toString(), QString( "3 " ) );
259
260 QList<double> expDoubleList = QgsVectorLayerUtils::getDoubleValues( layer, QStringLiteral( "col1 * 2" ), ok, false, &nulls );
261 QVERIFY( ok );
262 std::sort( expDoubleList.begin(), expDoubleList.end() );
263 QCOMPARE( expDoubleList.length(), 3 );
264 QCOMPARE( expDoubleList.at( 0 ), 2.0 );
265 QCOMPARE( expDoubleList.at( 1 ), 4.0 );
266 QCOMPARE( expDoubleList.at( 2 ), 6.0 );
267 QCOMPARE( nulls, 1 );
268
269 delete layer;
270 }
271
QgsVectorLayersetRenderer()272 void TestQgsVectorLayer::QgsVectorLayersetRenderer()
273 {
274 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
275 TestSignalReceiver receiver;
276 QObject::connect( vLayer, SIGNAL( rendererChanged() ),
277 &receiver, SLOT( onRendererChanged() ) );
278 QgsSingleSymbolRenderer *symbolRenderer = new QgsSingleSymbolRenderer( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
279
280 QCOMPARE( receiver.rendererChanged, false );
281 vLayer->setRenderer( symbolRenderer );
282 QCOMPARE( receiver.rendererChanged, true );
283 QCOMPARE( vLayer->renderer(), symbolRenderer );
284 }
285
QgsVectorLayersetFeatureBlendMode()286 void TestQgsVectorLayer::QgsVectorLayersetFeatureBlendMode()
287 {
288 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
289 TestSignalReceiver receiver;
290 QObject::connect( vLayer, SIGNAL( featureBlendModeChanged( const QPainter::CompositionMode ) ),
291 &receiver, SLOT( onFeatureBlendModeChanged( const QPainter::CompositionMode ) ) );
292
293 QCOMPARE( int( receiver.featureBlendMode ), 0 );
294 vLayer->setFeatureBlendMode( QPainter::CompositionMode_Screen );
295 QCOMPARE( receiver.featureBlendMode, QPainter::CompositionMode_Screen );
296 QCOMPARE( vLayer->featureBlendMode(), QPainter::CompositionMode_Screen );
297 }
298
QgsVectorLayersetLayerTransparency()299 void TestQgsVectorLayer::QgsVectorLayersetLayerTransparency()
300 {
301 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
302 TestSignalReceiver receiver;
303 QObject::connect( vLayer, &QgsVectorLayer::opacityChanged,
304 &receiver, &TestSignalReceiver::onLayerOpacityChanged );
305
306 QCOMPARE( receiver.opacity, 1.0 );
307 vLayer->setOpacity( 0.5 );
308 QCOMPARE( receiver.opacity, 0.5 );
309 QCOMPARE( vLayer->opacity(), 0.5 );
310 }
311
uniqueValues()312 void TestQgsVectorLayer::uniqueValues()
313 {
314 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
315
316 //test with invalid field
317 QSet<QVariant> values = vLayer->uniqueValues( 1000 );
318 QCOMPARE( values.count(), 0 );
319 }
320
minimumValue()321 void TestQgsVectorLayer::minimumValue()
322 {
323 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
324
325 //test with invalid field
326 QCOMPARE( vLayer->minimumValue( 1000 ), QVariant() );
327 }
328
maximumValue()329 void TestQgsVectorLayer::maximumValue()
330 {
331 QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
332
333 //test with invalid field
334 QCOMPARE( vLayer->maximumValue( 1000 ), QVariant() );
335 }
336
isSpatial()337 void TestQgsVectorLayer::isSpatial()
338 {
339 QVERIFY( mpPointsLayer->isSpatial() );
340 QVERIFY( mpPolysLayer->isSpatial() );
341 QVERIFY( mpLinesLayer->isSpatial() );
342 QVERIFY( !mpNonSpatialLayer->isSpatial() );
343 }
344
testAddTopologicalPoints()345 void TestQgsVectorLayer::testAddTopologicalPoints()
346 {
347 // create a simple linestring layer
348
349 QgsVectorLayer *layerLine = new QgsVectorLayer( QStringLiteral( "LineString?crs=EPSG:27700" ), QStringLiteral( "layer line" ), QStringLiteral( "memory" ) );
350 QVERIFY( layerLine->isValid() );
351
352 QgsPolylineXY line1;
353 line1 << QgsPointXY( 2, 1 ) << QgsPointXY( 1, 1 ) << QgsPointXY( 1, 5 );
354 QgsFeature lineF1;
355 lineF1.setGeometry( QgsGeometry::fromPolylineXY( line1 ) );
356
357 layerLine->startEditing();
358 layerLine->addFeature( lineF1 );
359 QgsFeatureId fidLineF1 = lineF1.id();
360 QCOMPARE( layerLine->featureCount(), ( long )1 );
361
362 QCOMPARE( layerLine->undoStack()->index(), 1 );
363
364 // outside of the linestring - nothing should happen
365 int result = layerLine->addTopologicalPoints( QgsPoint( 2, 2 ) );
366 QCOMPARE( result, 2 );
367
368 QCOMPARE( layerLine->undoStack()->index(), 1 );
369 QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry().asWkt(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 5)" ).asWkt() );
370
371 // add point at an existing vertex
372 result = layerLine->addTopologicalPoints( QgsPoint( 1, 1 ) );
373 QCOMPARE( result, 2 );
374
375 QCOMPARE( layerLine->undoStack()->index(), 1 );
376 QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry().asWkt(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 5)" ).asWkt() );
377
378 // add point on segment of linestring
379 result = layerLine->addTopologicalPoints( QgsPoint( 1, 2 ) );
380 QCOMPARE( result, 0 );
381
382 QCOMPARE( layerLine->undoStack()->index(), 2 );
383 QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry().asWkt(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 2, 1 5)" ).asWkt() );
384
385 // add points from disjoint geometry - nothing should happen
386 result = layerLine->addTopologicalPoints( QgsGeometry::fromWkt( "LINESTRING(2 0, 2 1, 2 2)" ) );
387 QCOMPARE( result, 2 );
388
389 QCOMPARE( layerLine->undoStack()->index(), 2 );
390 QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry().asWkt(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 2, 1 5)" ).asWkt() );
391
392 // add 2 out of 3 points from intersecting geometry
393 result = layerLine->addTopologicalPoints( QgsGeometry::fromWkt( "LINESTRING(2 0, 2 1, 2 3, 1 3, 0 3, 0 4, 1 4)" ) );
394 QCOMPARE( result, 0 );
395
396 QCOMPARE( layerLine->undoStack()->index(), 2 );
397 QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry().asWkt(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 2, 1 3, 1 4, 1 5)" ).asWkt() );
398
399 delete layerLine;
400
401 // Test error results -1: layer error, 1: geometry error
402 QgsVectorLayer *nonSpatialLayer = new QgsVectorLayer( QStringLiteral( "None" ), QStringLiteral( "non spatial layer" ), QStringLiteral( "memory" ) );
403 QVERIFY( nonSpatialLayer->isValid() );
404
405 result = nonSpatialLayer->addTopologicalPoints( QgsPoint( 2, 2 ) );
406 QCOMPARE( result, -1 ); // Non editable
407
408 nonSpatialLayer->startEditing();
409 result = nonSpatialLayer->addTopologicalPoints( QgsPoint( 2, 2 ) );
410 QCOMPARE( result, 1 ); // Non spatial
411
412 delete nonSpatialLayer;
413
414 QgsVectorLayer *layerPoint = new QgsVectorLayer( QStringLiteral( "Point?crs=EPSG:27700" ), QStringLiteral( "layer point" ), QStringLiteral( "memory" ) );
415 QVERIFY( layerPoint->isValid() );
416
417 layerPoint->startEditing();
418 result = layerPoint->addTopologicalPoints( QgsGeometry() );
419 QCOMPARE( result, 1 ); // Null geometry
420
421 delete layerPoint;
422
423 QgsVectorLayer *layerInvalid = new QgsVectorLayer( QStringLiteral(), QStringLiteral( "layer invalid" ), QStringLiteral( "none" ) );
424 QVERIFY( !layerInvalid->isValid() );
425
426 result = layerInvalid->addTopologicalPoints( QgsPoint( 2, 2 ) );
427 QCOMPARE( result, -1 ); // Invalid layer
428
429 delete layerInvalid;
430 }
431
testCopyPasteFieldConfiguration_data()432 void TestQgsVectorLayer::testCopyPasteFieldConfiguration_data()
433 {
434 QTest::addColumn<QgsMapLayer::StyleCategories>( "categories" );
435 // QTest::addColumn<double>( "flagExpected" );
436 // QTest::addColumn<double>( "widgetExpected" );
437
438 QTest::newRow( "forms_and_fields" ) << ( QgsMapLayer::Fields | QgsMapLayer::Forms );
439 QTest::newRow( "forms" ) << QgsMapLayer::StyleCategories( QgsMapLayer::Forms );
440 QTest::newRow( "fields" ) << QgsMapLayer::StyleCategories( QgsMapLayer::Fields );
441 QTest::newRow( "none" ) << QgsMapLayer::StyleCategories( QgsMapLayer::StyleCategories() );
442 }
443
testCopyPasteFieldConfiguration()444 void TestQgsVectorLayer::testCopyPasteFieldConfiguration()
445 {
446 QFETCH( QgsMapLayer::StyleCategories, categories );
447
448 QgsVectorLayer layer1( QStringLiteral( "Point?field=name:string" ), QStringLiteral( "layer1" ), QStringLiteral( "memory" ) );
449 QVERIFY( layer1.isValid() );
450 QVERIFY( layer1.editorWidgetSetup( 0 ).type().isEmpty() );
451 QCOMPARE( layer1.fieldConfigurationFlags( 0 ), QgsField::ConfigurationFlags() );
452
453 layer1.setEditorWidgetSetup( 0, QgsEditorWidgetSetup( "ValueMap", QVariantMap() ) );
454 QCOMPARE( layer1.editorWidgetSetup( 0 ).type(), QStringLiteral( "ValueMap" ) );
455 layer1.setFieldConfigurationFlags( 0, QgsField::ConfigurationFlag::NotSearchable );
456 QCOMPARE( layer1.fieldConfigurationFlags( 0 ), QgsField::ConfigurationFlag::NotSearchable );
457
458 // export given categories, import all
459 QString errorMsg;
460 QDomDocument doc( QStringLiteral( "qgis" ) );
461 QgsReadWriteContext context;
462 layer1.exportNamedStyle( doc, errorMsg, context, categories );
463 QVERIFY( errorMsg.isEmpty() );
464
465 QgsVectorLayer layer2( QStringLiteral( "Point?field=name:string" ), QStringLiteral( "layer2" ), QStringLiteral( "memory" ) );
466 QVERIFY( layer2.isValid() );
467 QVERIFY( layer2.editorWidgetSetup( 0 ).type().isEmpty() );
468 QCOMPARE( layer2.fieldConfigurationFlags( 0 ), QgsField::ConfigurationFlags() );
469
470 QVERIFY( layer2.importNamedStyle( doc, errorMsg ) );
471 QCOMPARE( layer2.editorWidgetSetup( 0 ).type(), categories.testFlag( QgsMapLayer::Forms ) ? QStringLiteral( "ValueMap" ) : QString( "" ) );
472 QCOMPARE( layer2.fieldConfigurationFlags( 0 ), categories.testFlag( QgsMapLayer::Fields ) ? QgsField::ConfigurationFlag::NotSearchable : QgsField::ConfigurationFlags() );
473
474 // export all, import given categories
475 QDomDocument doc2( QStringLiteral( "qgis" ) );
476 layer1.exportNamedStyle( doc2, errorMsg, context );
477 QVERIFY( errorMsg.isEmpty() );
478
479 QgsVectorLayer layer3( QStringLiteral( "Point?field=name:string" ), QStringLiteral( "layer3" ), QStringLiteral( "memory" ) );
480 QVERIFY( layer3.isValid() );
481 QVERIFY( layer3.editorWidgetSetup( 0 ).type().isEmpty() );
482 QCOMPARE( layer3.fieldConfigurationFlags( 0 ), QgsField::ConfigurationFlags() );
483
484 QVERIFY( layer3.importNamedStyle( doc2, errorMsg, categories ) );
485 QCOMPARE( layer3.editorWidgetSetup( 0 ).type(), categories.testFlag( QgsMapLayer::Forms ) ? QStringLiteral( "ValueMap" ) : QString( "" ) );
486 QCOMPARE( layer3.fieldConfigurationFlags( 0 ), categories.testFlag( QgsMapLayer::Fields ) ? QgsField::ConfigurationFlag::NotSearchable : QgsField::ConfigurationFlags() );
487 }
488
489 QGSTEST_MAIN( TestQgsVectorLayer )
490 #include "testqgsvectorlayer.moc"
491