1 /***************************************************************************
2 testqgstexteditwidgetwrapper.cpp
3 --------------------------------------
4 Date : 30 09 2019
5 Copyright : (C) 2019 Stephen Knox
6 Email : stephenknox73 at gmail 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
17 #include "qgstest.h"
18
19 #include <editorwidgets/core/qgseditorwidgetregistry.h>
20 #include "qgsattributeform.h"
21 #include <qgsapplication.h>
22 #include <qgsproject.h>
23 #include <qgsvectorlayer.h>
24 #include "qgseditorwidgetwrapper.h"
25 #include "qgsattributeformeditorwidget.h"
26 #include <editorwidgets/qgstexteditwrapper.h>
27 #include <QTableWidget>
28 #include "qgsgui.h"
29 #include <nlohmann/json.hpp>
30 #include "qgsjsonutils.h"
31
32 class TestQgsTextEditWrapper : public QObject
33 {
34 Q_OBJECT
35 public:
36 TestQgsTextEditWrapper() = default;
37
38 private:
39 QTemporaryDir tempDir;
40
41 private slots:
42 void initTestCase(); // will be called before the first testfunction is executed.
43 void cleanupTestCase(); // will be called after the last testfunction was executed.
44 void init(); // will be called before each testfunction is executed.
45 void cleanup(); // will be called after every testfunction.
46
47 void testWithJsonInPostgres();
48 void testWithJsonBInPostgres();
49 };
50
initTestCase()51 void TestQgsTextEditWrapper::initTestCase()
52 {
53 QgsApplication::init();
54 QgsApplication::initQgis();
55 QgsGui::editorWidgetRegistry()->initEditors();
56 testWithJsonInPostgres();
57 }
58
cleanupTestCase()59 void TestQgsTextEditWrapper::cleanupTestCase()
60 {
61 QgsApplication::exitQgis();
62 }
63
init()64 void TestQgsTextEditWrapper::init()
65 {
66 }
67
cleanup()68 void TestQgsTextEditWrapper::cleanup()
69 {
70 }
71
testWithJsonInPostgres()72 void TestQgsTextEditWrapper::testWithJsonInPostgres()
73 {
74 #ifdef ENABLE_PGTEST
75 // create pg layers
76 QString dbConn = getenv( "QGIS_PGTEST_DB" );
77 if ( dbConn.isEmpty() )
78 {
79 dbConn = "service=\"qgis_test\"";
80 }
81 QgsVectorLayer *vl_json = new QgsVectorLayer( QStringLiteral( "%1 sslmode=disable key=\"pk\" table=\"qgis_test\".\"json\" sql=" ).arg( dbConn ), QStringLiteral( "json" ), QStringLiteral( "postgres" ) );
82 QVERIFY( vl_json->isValid() );
83
84 QgsProject::instance()->addMapLayer( vl_json, false, false );
85 QCOMPARE( vl_json->fields().at( 1 ).type(), QVariant::Map );
86
87 QgsTextEditWrapper w_json( vl_json, vl_json->fields().indexOf( QLatin1String( "jvalue" ) ), nullptr, nullptr );
88 QLineEdit *widget = qobject_cast< QLineEdit * >( w_json.widget() );
89 w_json.setEnabled( true );
90
91 // check text output from DB
92 w_json.setFeature( vl_json->getFeature( 1 ) );
93 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "[1,2,3]" ) );
94 w_json.setFeature( vl_json->getFeature( 2 ) );
95 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "{\"a\":1,\"b\":2}" ) );
96
97 // check input into widget
98 // test array
99 widget->setText( QString( "[2]" ) );
100 QVERIFY( w_json.value().isValid() );
101 // w_json value is QListVariant
102 QVERIFY( w_json.value().userType() == QMetaType::QVariantList );
103 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_array() );
104 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "[2]" ) );
105
106 //test object
107 widget->setText( QString( "{\"foo\":\"bar\"}" ) );
108 QVERIFY( w_json.value().isValid() );
109 // w_json value is QMapVariant
110 QVERIFY( w_json.value().userType() == QMetaType::QVariantMap );
111 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_object() );
112 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "{\"foo\":\"bar\"}" ) );
113
114 //test complex object
115 widget->setText( QString( "{\"foo\":\"bar\",\"baz\":[1,2,3]}" ) );
116 QVERIFY( w_json.value().isValid() );
117 QVERIFY( w_json.value().userType() == QMetaType::QVariantMap );
118 json complexJson = QgsJsonUtils::jsonFromVariant( w_json.value() );
119 QVERIFY( complexJson.is_object() );
120 const json jsonArr = complexJson.at( "baz" );
121 QCOMPARE( QString::fromStdString( jsonArr.dump() ), QStringLiteral( "[1,2,3]" ) );
122
123 //test empty
124 widget->setText( QString( "" ) );
125 QVERIFY( w_json.value().isValid() );
126 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
127 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "\"\"" ) );
128
129 //test quoted empty
130 widget->setText( QString( "\"\"" ) );
131 QVERIFY( w_json.value().isValid() );
132 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
133 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "\"\"" ) );
134
135 // test invalid JSON
136 widget->setText( QString( "{\"body\";\"text\"}" ) );
137 QVERIFY( !w_json.value().isValid() );
138
139 // test with primitive integer (without container) which is valid JSON
140 widget->setText( QString( "2" ) );
141 QVERIFY( w_json.value().isValid() );
142 QCOMPARE( w_json.value(), QVariant( 2 ) );
143 QVERIFY( w_json.value().userType() == QMetaType::Int );
144 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_number_integer() );
145 const int n = QgsJsonUtils::jsonFromVariant( w_json.value() ).front();
146 QCOMPARE( QVariant( n ), QVariant( 2 ) );
147
148 // test with primitive boolean
149 widget->setText( QString( "true" ) );
150 QVERIFY( w_json.value().isValid() );
151 QCOMPARE( w_json.value(), QVariant( true ) );
152 QVERIFY( w_json.value().userType() == QMetaType::Bool );
153 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_boolean() );
154 const bool x = QgsJsonUtils::jsonFromVariant( w_json.value() ).front();
155 QCOMPARE( QVariant( x ), QVariant( true ) );
156
157 // test with primitive null
158 widget->setText( QString( "null" ) );
159 QVERIFY( w_json.value().isNull() );
160 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_null() );
161 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "null" ) );
162
163 // test with bare string (not valid JSON)
164 widget->setText( QString( "abc" ) );
165 QVERIFY( !w_json.value().isValid() );
166
167 // test with quoted string (valid JSON)
168 widget->setText( QString( "\"abc\"" ) );
169 QVERIFY( w_json.value().isValid() ) ;
170 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
171 // avoid dumping as strings are quoted, so would be double quoted
172 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "abc" ) );
173 #endif
174 }
175
testWithJsonBInPostgres()176 void TestQgsTextEditWrapper::testWithJsonBInPostgres()
177 {
178 #ifdef ENABLE_PGTEST
179 //create pg layers
180 QString dbConn = getenv( "QGIS_PGTEST_DB" );
181 if ( dbConn.isEmpty() )
182 {
183 dbConn = "service=\"qgis_test\"";
184 }
185 QgsVectorLayer *vl_json = new QgsVectorLayer( QStringLiteral( "%1 sslmode=disable key=\"pk\" table=\"qgis_test\".\"json\" sql=" ).arg( dbConn ), QStringLiteral( "json" ), QStringLiteral( "postgres" ) );
186 QVERIFY( vl_json->isValid() );
187
188 QgsProject::instance()->addMapLayer( vl_json, false, false );
189 QCOMPARE( vl_json->fields().at( 1 ).type(), QVariant::Map );
190
191 QgsTextEditWrapper w_json( vl_json, vl_json->fields().indexOf( QLatin1String( "jbvalue" ) ), nullptr, nullptr );
192 QLineEdit *widget = qobject_cast< QLineEdit * >( w_json.widget() );
193 w_json.setEnabled( true );
194
195 // check text output from DB
196 w_json.setFeature( vl_json->getFeature( 1 ) );
197 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "[4,5,6]" ) );
198 w_json.setFeature( vl_json->getFeature( 2 ) );
199 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "{\"c\":4,\"d\":5}" ) );
200
201 // check input into widget
202 // test array
203 widget->setText( QString( "[2]" ) );
204 QVERIFY( w_json.value().isValid() );
205 // w_json value is QListVariant
206 QVERIFY( w_json.value().userType() == QMetaType::QVariantList );
207 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_array() );
208 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "[2]" ) );
209
210 //test object
211 widget->setText( QString( "{\"foo\":\"bar\"}" ) );
212 QVERIFY( w_json.value().isValid() );
213 // w_json value is QMapVaJsonDocriant
214 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_object() );
215 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "{\"foo\":\"bar\"}" ) );
216
217 //test complex object
218 widget->setText( QString( "{\"foo\":\"bar\",\"baz\":[1,2,3]}" ) );
219 QVERIFY( w_json.value().isValid() );
220 QVERIFY( w_json.value().userType() == QMetaType::QVariantMap );
221 json complexJson = QgsJsonUtils::jsonFromVariant( w_json.value() );
222 QVERIFY( complexJson.is_object() );
223 const json jsonArr = complexJson.at( "baz" );
224 QCOMPARE( QString::fromStdString( jsonArr.dump() ), QStringLiteral( "[1,2,3]" ) );
225
226
227 //test empty
228 widget->setText( QString( "" ) );
229 QVERIFY( w_json.value().isValid() );
230 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
231 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "\"\"" ) );
232
233
234 //test quoted empty
235 widget->setText( QString( "\"\"" ) );
236 QVERIFY( w_json.value().isValid() );
237 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
238 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "\"\"" ) );
239
240 // test invalid JSON
241 widget->setText( QString( "{\"body\";\"text\"}" ) );
242 QVERIFY( !w_json.value().isValid() );
243
244 // test with primitive integer (without container) which is valid JSON
245 widget->setText( QString( "2" ) );
246 QVERIFY( w_json.value().isValid() );
247 QCOMPARE( w_json.value(), QVariant( 2 ) );
248 QVERIFY( w_json.value().userType() == QMetaType::Int );
249 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_number_integer() );
250 const int n = QgsJsonUtils::jsonFromVariant( w_json.value() ).front();
251 QCOMPARE( QVariant( n ), QVariant( 2 ) );
252
253 // test with primitive boolean
254 widget->setText( QString( "true" ) );
255 QVERIFY( w_json.value().isValid() );
256 QCOMPARE( w_json.value(), QVariant( true ) );
257 QVERIFY( w_json.value().userType() == QMetaType::Bool );
258 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_boolean() );
259 const bool x = QgsJsonUtils::jsonFromVariant( w_json.value() ).front();
260 QCOMPARE( QVariant( x ), QVariant( true ) );
261
262 // test with primitive null
263 widget->setText( QString( "null" ) );
264 QVERIFY( w_json.value().isNull() );
265 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_null() );
266 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).dump() ), QStringLiteral( "null" ) );
267
268
269 // test with bare string (not valid JSON)
270 widget->setText( QString( "abc" ) );
271 QVERIFY( !w_json.value().isValid() );
272
273 // test with quoted string (valid JSON)
274 widget->setText( QString( "\"abc\"" ) );
275 QVERIFY( w_json.value().isValid() ) ;
276 QVERIFY( QgsJsonUtils::jsonFromVariant( w_json.value() ).is_string() );
277 // avoid dumping as strings are quoted, so would be double quoted
278 QCOMPARE( QString::fromStdString( QgsJsonUtils::jsonFromVariant( w_json.value() ).front( ) ), QStringLiteral( "abc" ) );
279 #endif
280 }
281
282 QGSTEST_MAIN( TestQgsTextEditWrapper )
283 #include "testqgstexteditwrapper.moc"
284