1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtQml/qqmlengine.h>
43 #include <QtQml/qqmlcomponent.h>
44 #include <QtCore/qcoreapplication.h>
45 #include <QtCore/qfile.h>
46 #include <QtCore/qdebug.h>
47 #include <QtCore/qfileinfo.h>
48 #include <QtCore/qdir.h>
51 #include <private/qqmlproperty_p.h>
52 #include <private/qqmlmetatype_p.h>
53 #include <private/qqmlglobal_p.h>
55 #include "testtypes.h"
56 #include "testhttpserver.h"
58 DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
61 Returns the path to some testdata file or directory.
63 QString testdata(QString const& name = QString())
65 static const QString dataDirectory = QDir::currentPath() + QLatin1String("/data");
66 QString result = dataDirectory;
67 if (!name.isEmpty()) {
68 result += QLatin1Char('/');
75 This test case covers QML language issues. This covers everything that does not
76 involve evaluating ECMAScript expressions and bindings.
78 Evaluation of expressions and bindings is covered in qmlecmascript
80 class tst_qqmllanguage : public QObject
85 QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
86 engine.addImportPath(testdata("lib"));
91 void cleanupTestCase();
96 void insertedSemicolon_data();
97 void insertedSemicolon();
100 void simpleContainer();
101 void interfaceProperty();
102 void interfaceQList();
103 void assignObjectToSignal();
104 void assignObjectToVariant();
105 void assignLiteralSignalProperty();
106 void assignQmlComponent();
107 void assignBasicTypes();
108 void assignTypeExtremes();
109 void assignCompositeToType();
110 void assignLiteralToVariant();
111 void assignLiteralToVar();
112 void assignLiteralToJSValue();
113 void bindJSValueToVar();
114 void bindJSValueToVariant();
115 void bindJSValueToType();
116 void bindTypeToJSValue();
117 void customParserTypes();
118 void rootAsQmlComponent();
119 void inlineQmlComponents();
121 void autoNotifyConnection();
123 void dynamicProperties();
124 void dynamicPropertiesNested();
125 void listProperties();
126 void dynamicObjectProperties();
127 void dynamicSignalsAndSlots();
128 void simpleBindings();
129 void autoComponentCreation();
130 void propertyValueSource();
131 void attachedProperties();
132 void dynamicObjects();
133 void customVariantTypes();
136 void aliasProperties();
137 void aliasPropertiesAndSignals();
138 void aliasPropertyChangeSignals();
139 void componentCompositeType();
143 void onDestruction();
145 void defaultPropertyListOrder();
146 void declaredPropertyValues();
147 void dontDoubleCallClassBegin();
148 void reservedWords_data();
149 void reservedWords();
150 void inlineAssignmentsOverrideBindings();
151 void nestedComponentRoots();
152 void registrationOrder();
156 void basicRemote_data();
158 void importsBuiltin_data();
159 void importsBuiltin();
160 void importsLocal_data();
162 void importsRemote_data();
163 void importsRemote();
164 void importsInstalled_data();
165 void importsInstalled();
166 void importsOrder_data();
168 void importIncorrectCase();
169 void importJs_data();
172 void qmlAttachedPropertiesObjectMethod();
173 void customOnProperty();
174 void variantNotify();
177 void revisionOverloads();
180 void remoteLoadCrash();
181 void signalWithDefaultArg();
183 // regression tests for crashes
191 void testType(const QString& qml, const QString& type, const QString& error, bool partialMatch = false);
194 #define DETERMINE_ERRORS(errorfile,expected,actual)\
195 QList<QByteArray> expected; \
196 QList<QByteArray> actual; \
198 QFile file(testdata(QLatin1String(errorfile))); \
199 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
200 QByteArray data = file.readAll(); \
202 expected = data.split('\n'); \
203 expected.removeAll(QByteArray("")); \
204 QList<QQmlError> errors = component.errors(); \
205 for (int ii = 0; ii < errors.count(); ++ii) { \
206 const QQmlError &error = errors.at(ii); \
207 QByteArray errorStr = QByteArray::number(error.line()) + ":" + \
208 QByteArray::number(error.column()) + ":" + \
209 error.description().toUtf8(); \
210 actual << errorStr; \
214 #define VERIFY_ERRORS(errorfile) \
216 if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
217 qWarning() << "Unexpected Errors:" << component.errors(); \
218 QVERIFY(!component.isError()); \
219 QVERIFY(component.errors().isEmpty()); \
221 DETERMINE_ERRORS(errorfile,actual,expected);\
222 if (qgetenv("DEBUG") != "" && expected != actual) \
223 qWarning() << "Expected:" << expected << "Actual:" << actual; \
224 if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
225 QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
226 QVERIFY(file.open(QIODevice::WriteOnly)); \
227 for (int ii = 0; ii < actual.count(); ++ii) { \
228 file.write(actual.at(ii)); file.write("\n"); \
232 QCOMPARE(expected, actual); \
236 inline QUrl TEST_FILE(const QString &filename)
238 return QUrl::fromLocalFile(testdata(filename));
241 inline QUrl TEST_FILE(const char *filename)
243 return TEST_FILE(QLatin1String(filename));
246 void tst_qqmllanguage::cleanupTestCase()
248 QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
251 void tst_qqmllanguage::insertedSemicolon_data()
253 QTest::addColumn<QString>("file");
254 QTest::addColumn<QString>("errorFile");
255 QTest::addColumn<bool>("create");
257 QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false;
260 void tst_qqmllanguage::insertedSemicolon()
262 QFETCH(QString, file);
263 QFETCH(QString, errorFile);
264 QFETCH(bool, create);
266 QQmlComponent component(&engine, TEST_FILE(file));
269 QObject *object = component.create();
270 QVERIFY(object == 0);
273 VERIFY_ERRORS(errorFile.toLatin1().constData());
276 void tst_qqmllanguage::errors_data()
278 QTest::addColumn<QString>("file");
279 QTest::addColumn<QString>("errorFile");
280 QTest::addColumn<bool>("create");
282 QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
283 QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
284 QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
285 QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
286 QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
287 QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
289 QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
290 QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
291 QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
293 QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
294 QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
295 QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
296 QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
297 QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
298 QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
299 QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
300 QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
301 QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
302 QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
303 QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
304 QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
305 QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false;
306 QTest::newRow("wrongType (int for enum)") << "wrongType.17.qml" << "wrongType.17.errors.txt" << false;
308 QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
309 QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
310 QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
311 QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false;
312 QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false;
314 QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
315 QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
316 QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
318 QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
319 QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
320 QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
321 QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
322 QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
323 QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
324 QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false;
325 QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false;
326 QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false;
328 QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false;
329 QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false;
331 QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
332 QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
333 QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
334 QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
335 QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
336 QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
337 QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
338 QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
339 QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
340 QTest::newRow("missingSignal2") << "missingSignal.2.qml" << "missingSignal.2.errors.txt" << false;
341 QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
342 QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
344 QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
345 QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
346 QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
347 QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
348 QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
349 QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
350 QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
351 QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false;
352 QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false;
353 QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false;
355 QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
356 QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
357 QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
358 QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false;
359 QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false;
360 QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false;
361 QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
362 QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false;
364 QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
365 QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
366 QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
367 QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false;
368 QTest::newRow("signal.5") << "signal.5.qml" << "signal.5.errors.txt" << false;
370 QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false;
372 QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
373 QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
374 QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
375 QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
376 QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false;
377 QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false;
379 QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false;
381 QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
382 QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
383 QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
384 QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
385 QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
386 QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
387 QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false;
388 QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false;
389 QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false;
391 QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false;
392 QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false;
393 QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false;
394 QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false;
395 QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false;
396 QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false;
397 QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false;
398 QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false;
399 QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false;
400 QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false;
401 QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false;
403 QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false;
404 QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false;
405 QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false;
406 QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false;
407 QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false;
409 QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false;
410 QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false;
411 QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false;
412 QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false;
413 QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false;
414 QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false;
415 QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false;
416 QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
417 QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
418 QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
420 QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
421 QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
422 QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
423 QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
424 QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
425 QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
426 QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
427 QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
428 QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
429 QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
430 QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
431 QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false;
432 QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false;
434 QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false;
435 QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
437 QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
438 QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
439 QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
440 QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
441 QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
442 QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false;
443 QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false;
444 QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false;
445 QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false;
446 QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false;
447 QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false;
448 QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false;
449 QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
450 QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
451 QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
452 QTest::newRow("incorrectCase") << "incorrectCase.qml"
453 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
454 << "incorrectCase.errors.insensitive.txt"
456 << "incorrectCase.errors.sensitive.txt"
460 QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false;
461 QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false;
462 QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false;
464 QTest::newRow("invalidRoot.1") << "invalidRoot.1.qml" << "invalidRoot.1.errors.txt" << false;
465 QTest::newRow("invalidRoot.2") << "invalidRoot.2.qml" << "invalidRoot.2.errors.txt" << false;
466 QTest::newRow("invalidRoot.3") << "invalidRoot.3.qml" << "invalidRoot.3.errors.txt" << false;
467 QTest::newRow("invalidRoot.4") << "invalidRoot.4.qml" << "invalidRoot.4.errors.txt" << false;
469 QTest::newRow("invalidTypeName.1") << "invalidTypeName.1.qml" << "invalidTypeName.1.errors.txt" << false;
470 QTest::newRow("invalidTypeName.2") << "invalidTypeName.2.qml" << "invalidTypeName.2.errors.txt" << false;
471 QTest::newRow("invalidTypeName.3") << "invalidTypeName.3.qml" << "invalidTypeName.3.errors.txt" << false;
472 QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
474 QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
478 void tst_qqmllanguage::errors()
480 QFETCH(QString, file);
481 QFETCH(QString, errorFile);
482 QFETCH(bool, create);
484 QQmlComponent component(&engine, TEST_FILE(file));
487 QObject *object = component.create();
488 QVERIFY(object == 0);
491 VERIFY_ERRORS(errorFile.toLatin1().constData());
494 void tst_qqmllanguage::simpleObject()
496 QQmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
498 QObject *object = component.create();
499 QVERIFY(object != 0);
502 void tst_qqmllanguage::simpleContainer()
504 QQmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
506 MyContainer *container= qobject_cast<MyContainer*>(component.create());
507 QVERIFY(container != 0);
508 QCOMPARE(container->getChildren()->count(),2);
511 void tst_qqmllanguage::interfaceProperty()
513 QQmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
515 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
516 QVERIFY(object != 0);
517 QVERIFY(object->interface());
518 QVERIFY(object->interface()->id == 913);
521 void tst_qqmllanguage::interfaceQList()
523 QQmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
525 MyContainer *container= qobject_cast<MyContainer*>(component.create());
526 QVERIFY(container != 0);
527 QVERIFY(container->getQListInterfaces()->count() == 2);
528 for(int ii = 0; ii < 2; ++ii)
529 QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
532 void tst_qqmllanguage::assignObjectToSignal()
534 QQmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
536 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
537 QVERIFY(object != 0);
538 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
539 emit object->basicSignal();
542 void tst_qqmllanguage::assignObjectToVariant()
544 QQmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
546 QObject *object = component.create();
547 QVERIFY(object != 0);
548 QVariant v = object->property("a");
549 QVERIFY(v.userType() == qMetaTypeId<QObject *>());
552 void tst_qqmllanguage::assignLiteralSignalProperty()
554 QQmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
556 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
557 QVERIFY(object != 0);
558 QCOMPARE(object->onLiteralSignal(), 10);
561 // Test is an external component can be loaded and assigned (to a qlist)
562 void tst_qqmllanguage::assignQmlComponent()
564 QQmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
566 MyContainer *object = qobject_cast<MyContainer *>(component.create());
567 QVERIFY(object != 0);
568 QVERIFY(object->getChildren()->count() == 1);
569 QObject *child = object->getChildren()->at(0);
570 QCOMPARE(child->property("x"), QVariant(10));
571 QCOMPARE(child->property("y"), QVariant(11));
574 // Test literal assignment to all the basic types
575 void tst_qqmllanguage::assignBasicTypes()
577 QQmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
579 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
580 QVERIFY(object != 0);
581 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
582 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
583 QCOMPARE(object->qtEnumProperty(), Qt::RichText);
584 QCOMPARE(object->mirroredEnumProperty(), MyTypeObject::MirroredEnumVal3);
585 QCOMPARE(object->stringProperty(), QString("Hello World!"));
586 QCOMPARE(object->uintProperty(), uint(10));
587 QCOMPARE(object->intProperty(), -19);
588 QCOMPARE((float)object->realProperty(), float(23.2));
589 QCOMPARE((float)object->doubleProperty(), float(-19.7));
590 QCOMPARE((float)object->floatProperty(), float(8.5));
591 QCOMPARE(object->colorProperty(), QColor("red"));
592 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
593 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
594 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
595 QCOMPARE(object->pointProperty(), QPoint(99,13));
596 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
597 QCOMPARE(object->sizeProperty(), QSize(99, 13));
598 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
599 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
600 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
601 QCOMPARE(object->boolProperty(), true);
602 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
603 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
604 QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3));
606 encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
607 QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
608 QVERIFY(object->objectProperty() != 0);
609 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
611 QCOMPARE(child->intProperty(), 8);
613 //these used to go via script. Ensure they no longer do
614 QCOMPARE(object->property("qtEnumTriggeredChange").toBool(), false);
615 QCOMPARE(object->property("mirroredEnumTriggeredChange").toBool(), false);
618 // Test edge case type assignments
619 void tst_qqmllanguage::assignTypeExtremes()
621 QQmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
623 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
624 QVERIFY(object != 0);
625 QCOMPARE(object->uintProperty(), 0xEE6B2800);
626 QCOMPARE(object->intProperty(), -0x77359400);
629 // Test that a composite type can assign to a property of its base type
630 void tst_qqmllanguage::assignCompositeToType()
632 QQmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
634 QObject *object = component.create();
635 QVERIFY(object != 0);
638 // Test that literals are stored correctly in variant properties
639 void tst_qqmllanguage::assignLiteralToVariant()
641 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml"));
643 QObject *object = component.create();
644 QVERIFY(object != 0);
646 QCOMPARE(object->property("test1").userType(), (int)QVariant::Int);
647 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
648 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
649 QCOMPARE(object->property("test4").userType(), (int)QVariant::Color);
650 QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF);
651 QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF);
652 QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF);
653 QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D);
654 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
655 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
656 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
657 QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
659 QVERIFY(object->property("test1") == QVariant(1));
660 QVERIFY(object->property("test2") == QVariant((double)1.7));
661 QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
662 QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
663 QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
664 QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
665 QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
666 QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
667 QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
668 QVERIFY(object->property("test10") == QVariant(bool(true)));
669 QVERIFY(object->property("test11") == QVariant(bool(false)));
670 QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
675 // Test that literals are stored correctly in "var" properties
676 // Note that behaviour differs from "variant" properties in that
677 // no conversion from "special strings" to QVariants is performed.
678 void tst_qqmllanguage::assignLiteralToVar()
680 QQmlComponent component(&engine, TEST_FILE("assignLiteralToVar.qml"));
682 QObject *object = component.create();
683 QVERIFY(object != 0);
685 QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
686 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
687 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
688 QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
689 QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
690 QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
691 QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
692 QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
693 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
694 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
695 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
696 QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
697 QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
698 QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
699 QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
700 QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
701 QCOMPARE(object->property("variantTest1Bound").userType(), (int)QMetaType::Int);
702 QCOMPARE(object->property("test1Bound").userType(), (int)QMetaType::Int);
704 QCOMPARE(object->property("test1"), QVariant(5));
705 QCOMPARE(object->property("test2"), QVariant((double)1.7));
706 QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
707 QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
708 QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
709 QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
710 QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
711 QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
712 QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
713 QCOMPARE(object->property("test10"), QVariant(bool(true)));
714 QCOMPARE(object->property("test11"), QVariant(bool(false)));
715 QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
716 QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
717 QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
718 QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
719 QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
720 QCOMPARE(object->property("variantTest1Bound"), QVariant(9));
721 QCOMPARE(object->property("test1Bound"), QVariant(11));
726 void tst_qqmllanguage::assignLiteralToJSValue()
728 QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
730 QObject *root = component.create();
734 MyQmlObject *object = root->findChild<MyQmlObject *>("test1");
735 QJSValue value = object->qjsvalue();
736 QVERIFY(value.isNumber());
737 QCOMPARE(value.toNumber(), qreal(5));
739 MyQmlObject *object = root->findChild<MyQmlObject *>("test2");
740 QJSValue value = object->qjsvalue();
741 QVERIFY(value.isNumber());
742 QCOMPARE(value.toNumber(), qreal(1.7));
744 MyQmlObject *object = root->findChild<MyQmlObject *>("test3");
745 QJSValue value = object->qjsvalue();
746 QVERIFY(value.isString());
747 QCOMPARE(value.toString(), QString(QLatin1String("Hello world!")));
749 MyQmlObject *object = root->findChild<MyQmlObject *>("test4");
750 QJSValue value = object->qjsvalue();
751 QVERIFY(value.isString());
752 QCOMPARE(value.toString(), QString(QLatin1String("#FF008800")));
754 MyQmlObject *object = root->findChild<MyQmlObject *>("test5");
755 QJSValue value = object->qjsvalue();
756 QVERIFY(value.isString());
757 QCOMPARE(value.toString(), QString(QLatin1String("10,10,10x10")));
759 MyQmlObject *object = root->findChild<MyQmlObject *>("test6");
760 QJSValue value = object->qjsvalue();
761 QVERIFY(value.isString());
762 QCOMPARE(value.toString(), QString(QLatin1String("10,10")));
764 MyQmlObject *object = root->findChild<MyQmlObject *>("test7");
765 QJSValue value = object->qjsvalue();
766 QVERIFY(value.isString());
767 QCOMPARE(value.toString(), QString(QLatin1String("10x10")));
769 MyQmlObject *object = root->findChild<MyQmlObject *>("test8");
770 QJSValue value = object->qjsvalue();
771 QVERIFY(value.isString());
772 QCOMPARE(value.toString(), QString(QLatin1String("100,100,100")));
774 MyQmlObject *object = root->findChild<MyQmlObject *>("test9");
775 QJSValue value = object->qjsvalue();
776 QVERIFY(value.isString());
777 QCOMPARE(value.toString(), QString(QLatin1String("#FF008800")));
779 MyQmlObject *object = root->findChild<MyQmlObject *>("test10");
780 QJSValue value = object->qjsvalue();
781 QVERIFY(value.isBool());
782 QCOMPARE(value.toBool(), true);
784 MyQmlObject *object = root->findChild<MyQmlObject *>("test11");
785 QJSValue value = object->qjsvalue();
786 QVERIFY(value.isBool());
787 QCOMPARE(value.toBool(), false);
789 MyQmlObject *object = root->findChild<MyQmlObject *>("test20");
790 QJSValue value = object->qjsvalue();
791 QVERIFY(value.isCallable());
792 QCOMPARE(value.call(QList<QJSValue> () << QJSValue(4)).toInt(), 12);
794 MyQmlObject *object = root->findChild<MyQmlObject *>("test21");
795 QJSValue value = object->qjsvalue();
796 QVERIFY(value.isUndefined());
798 MyQmlObject *object = root->findChild<MyQmlObject *>("test22");
799 QJSValue value = object->qjsvalue();
800 QVERIFY(value.isNull());
802 MyQmlObject *object = root->findChild<MyQmlObject *>("test1Bound");
803 QJSValue value = object->qjsvalue();
804 QVERIFY(value.isNumber());
805 QCOMPARE(value.toNumber(), qreal(9));
807 MyQmlObject *object = root->findChild<MyQmlObject *>("test20Bound");
808 QJSValue value = object->qjsvalue();
809 QVERIFY(value.isNumber());
810 QCOMPARE(value.toNumber(), qreal(27));
814 void tst_qqmllanguage::bindJSValueToVar()
816 QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
819 QObject *root = component.create();
822 QObject *object = root->findChild<QObject *>("varProperties");
824 QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
825 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
826 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
827 QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
828 QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
829 QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
830 QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
831 QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
832 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
833 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
834 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
835 QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
836 QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
837 QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
838 QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
839 QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
840 QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
841 QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Int);
843 QCOMPARE(object->property("test1"), QVariant(5));
844 QCOMPARE(object->property("test2"), QVariant((double)1.7));
845 QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
846 QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
847 QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
848 QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
849 QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
850 QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
851 QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
852 QCOMPARE(object->property("test10"), QVariant(bool(true)));
853 QCOMPARE(object->property("test11"), QVariant(bool(false)));
854 QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
855 QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
856 QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
857 QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
858 QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
859 QCOMPARE(object->property("test1Bound"), QVariant(9));
860 QCOMPARE(object->property("test20Bound"), QVariant(27));
863 void tst_qqmllanguage::bindJSValueToVariant()
865 QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
868 QObject *root = component.create();
871 QObject *object = root->findChild<QObject *>("variantProperties");
873 QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
874 QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
875 QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
876 QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
877 QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
878 QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
879 QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
880 QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
881 QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
882 QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
883 QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
884 QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
885 QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
886 QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
887 QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
888 QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
889 QCOMPARE(object->property("test1Bound").userType(), (int)QVariant::Int);
890 QCOMPARE(object->property("test20Bound").userType(), (int)QVariant::Int);
892 QCOMPARE(object->property("test1"), QVariant(5));
893 QCOMPARE(object->property("test2"), QVariant((double)1.7));
894 QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
895 QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
896 QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
897 QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
898 QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
899 QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
900 QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
901 QCOMPARE(object->property("test10"), QVariant(bool(true)));
902 QCOMPARE(object->property("test11"), QVariant(bool(false)));
903 QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
904 QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
905 QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
906 QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
907 QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
908 QCOMPARE(object->property("test1Bound"), QVariant(9));
909 QCOMPARE(object->property("test20Bound"), QVariant(27));
912 void tst_qqmllanguage::bindJSValueToType()
914 QQmlComponent component(&engine, TEST_FILE("assignLiteralToJSValue.qml"));
917 QObject *root = component.create();
921 MyTypeObject *object = root->findChild<MyTypeObject *>("typedProperties");
923 QCOMPARE(object->intProperty(), 5);
924 QCOMPARE(object->doubleProperty(), double(1.7));
925 QCOMPARE(object->stringProperty(), QString(QLatin1String("Hello world!")));
926 QCOMPARE(object->boolProperty(), true);
927 QCOMPARE(object->colorProperty(), QColor::fromRgbF(0.2, 0.3, 0.4, 0.5));
928 QCOMPARE(object->rectFProperty(), QRectF(10, 10, 10, 10));
929 QCOMPARE(object->pointFProperty(), QPointF(10, 10));
930 QCOMPARE(object->sizeFProperty(), QSizeF(10, 10));
931 QCOMPARE(object->vectorProperty(), QVector3D(100, 100, 100));
933 MyTypeObject *object = root->findChild<MyTypeObject *>("stringProperties");
935 QCOMPARE(object->intProperty(), 1);
936 QCOMPARE(object->doubleProperty(), double(1.7));
937 QCOMPARE(object->stringProperty(), QString(QLatin1String("Hello world!")));
938 QCOMPARE(object->boolProperty(), true);
939 QCOMPARE(object->colorProperty(), QColor::fromRgb(0x00, 0x88, 0x00, 0xFF));
940 QCOMPARE(object->rectFProperty(), QRectF(10, 10, 10, 10));
941 QCOMPARE(object->pointFProperty(), QPointF(10, 10));
942 QCOMPARE(object->sizeFProperty(), QSizeF(10, 10));
943 QCOMPARE(object->vectorProperty(), QVector3D(100, 100, 100));
947 void tst_qqmllanguage::bindTypeToJSValue()
949 QQmlComponent component(&engine, TEST_FILE("bindTypeToJSValue.qml"));
952 QObject *root = component.create();
956 MyQmlObject *object = root->findChild<MyQmlObject *>("flagProperty");
958 QJSValue value = object->qjsvalue();
959 QVERIFY(value.isNumber());
960 QCOMPARE(value.toNumber(), qreal(MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3));
962 MyQmlObject *object = root->findChild<MyQmlObject *>("enumProperty");
963 QJSValue value = object->qjsvalue();
964 QVERIFY(value.isNumber());
965 QCOMPARE(value.toNumber(), qreal(MyTypeObject::EnumVal2));
967 MyQmlObject *object = root->findChild<MyQmlObject *>("stringProperty");
968 QJSValue value = object->qjsvalue();
969 QVERIFY(value.isString());
970 QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
972 MyQmlObject *object = root->findChild<MyQmlObject *>("uintProperty");
973 QJSValue value = object->qjsvalue();
974 QVERIFY(value.isNumber());
975 QCOMPARE(value.toNumber(), qreal(10));
977 MyQmlObject *object = root->findChild<MyQmlObject *>("intProperty");
978 QJSValue value = object->qjsvalue();
979 QVERIFY(value.isNumber());
980 QCOMPARE(value.toNumber(), qreal(-19));
982 MyQmlObject *object = root->findChild<MyQmlObject *>("realProperty");
983 QJSValue value = object->qjsvalue();
984 QVERIFY(value.isNumber());
985 QCOMPARE(value.toNumber(), qreal(23.2));
987 MyQmlObject *object = root->findChild<MyQmlObject *>("doubleProperty");
988 QJSValue value = object->qjsvalue();
989 QVERIFY(value.isNumber());
990 QCOMPARE(value.toNumber(), qreal(-19.7));
992 MyQmlObject *object = root->findChild<MyQmlObject *>("floatProperty");
993 QJSValue value = object->qjsvalue();
994 QVERIFY(value.isNumber());
995 QCOMPARE(value.toNumber(), qreal(8.5));
997 MyQmlObject *object = root->findChild<MyQmlObject *>("colorProperty");
998 QJSValue value = object->qjsvalue();
999 QVERIFY(value.isObject());
1000 QCOMPARE(value.property(QLatin1String("r")).toNumber(), qreal(1.0));
1001 QCOMPARE(value.property(QLatin1String("g")).toNumber(), qreal(0.0));
1002 QCOMPARE(value.property(QLatin1String("b")).toNumber(), qreal(0.0));
1004 MyQmlObject *object = root->findChild<MyQmlObject *>("dateProperty");
1005 QJSValue value = object->qjsvalue();
1006 QCOMPARE(value.toDateTime().isValid(), true);
1008 MyQmlObject *object = root->findChild<MyQmlObject *>("timeProperty");
1009 QJSValue value = object->qjsvalue();
1010 QCOMPARE(value.toDateTime().isValid(), true);
1012 MyQmlObject *object = root->findChild<MyQmlObject *>("dateTimeProperty");
1013 QJSValue value = object->qjsvalue();
1014 QCOMPARE(value.toDateTime().isValid(), true);
1016 MyQmlObject *object = root->findChild<MyQmlObject *>("pointProperty");
1017 QJSValue value = object->qjsvalue();
1018 QVERIFY(value.isObject());
1019 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(99));
1020 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(13));
1022 MyQmlObject *object = root->findChild<MyQmlObject *>("pointFProperty");
1023 QJSValue value = object->qjsvalue();
1024 QVERIFY(value.isObject());
1025 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(-10.1));
1026 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(12.3));
1028 MyQmlObject *object = root->findChild<MyQmlObject *>("rectProperty");
1029 QJSValue value = object->qjsvalue();
1030 QVERIFY(value.isObject());
1031 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(9));
1032 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(7));
1033 QCOMPARE(value.property(QLatin1String("width")).toNumber(), qreal(100));
1034 QCOMPARE(value.property(QLatin1String("height")).toNumber(), qreal(200));
1036 MyQmlObject *object = root->findChild<MyQmlObject *>("rectFProperty");
1037 QJSValue value = object->qjsvalue();
1038 QVERIFY(value.isObject());
1039 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(1000.1));
1040 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(-10.9));
1041 QCOMPARE(value.property(QLatin1String("width")).toNumber(), qreal(400));
1042 QCOMPARE(value.property(QLatin1String("height")).toNumber(), qreal(90.99));
1044 MyQmlObject *object = root->findChild<MyQmlObject *>("boolProperty");
1045 QJSValue value = object->qjsvalue();
1046 QVERIFY(value.isBool());
1047 QCOMPARE(value.toBool(), true);
1049 MyQmlObject *object = root->findChild<MyQmlObject *>("variantProperty");
1050 QJSValue value = object->qjsvalue();
1051 QVERIFY(value.isString());
1052 QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
1054 MyQmlObject *object = root->findChild<MyQmlObject *>("vectorProperty");
1055 QJSValue value = object->qjsvalue();
1056 QVERIFY(value.isObject());
1057 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(10.0f));
1058 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(1.0f));
1059 QCOMPARE(value.property(QLatin1String("z")).toNumber(), qreal(2.2f));
1061 MyQmlObject *object = root->findChild<MyQmlObject *>("vector4Property");
1062 QJSValue value = object->qjsvalue();
1063 QVERIFY(value.isObject());
1064 QCOMPARE(value.property(QLatin1String("x")).toNumber(), qreal(10.0f));
1065 QCOMPARE(value.property(QLatin1String("y")).toNumber(), qreal(1.0f));
1066 QCOMPARE(value.property(QLatin1String("z")).toNumber(), qreal(2.2f));
1067 QCOMPARE(value.property(QLatin1String("w")).toNumber(), qreal(2.3f));
1069 MyQmlObject *object = root->findChild<MyQmlObject *>("urlProperty");
1070 QJSValue value = object->qjsvalue();
1071 QVERIFY(value.isString());
1073 encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
1074 QCOMPARE(value.toString(), component.url().resolved(encoded).toString());
1076 MyQmlObject *object = root->findChild<MyQmlObject *>("objectProperty");
1077 QJSValue value = object->qjsvalue();
1078 QVERIFY(value.isQObject());
1079 QVERIFY(qobject_cast<MyTypeObject *>(value.toQObject()));
1081 MyQmlObject *object = root->findChild<MyQmlObject *>("varProperty");
1082 QJSValue value = object->qjsvalue();
1083 QVERIFY(value.isString());
1084 QCOMPARE(value.toString(), QString(QLatin1String("Hello World!")));
1088 // Tests that custom parser types can be instantiated
1089 void tst_qqmllanguage::customParserTypes()
1091 QQmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
1093 QObject *object = component.create();
1094 QVERIFY(object != 0);
1095 QVERIFY(object->property("count") == QVariant(2));
1098 // Tests that the root item can be a custom component
1099 void tst_qqmllanguage::rootAsQmlComponent()
1101 QQmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
1103 MyContainer *object = qobject_cast<MyContainer *>(component.create());
1104 QVERIFY(object != 0);
1105 QCOMPARE(object->property("x"), QVariant(11));
1106 QCOMPARE(object->getChildren()->count(), 2);
1109 // Tests that components can be specified inline
1110 void tst_qqmllanguage::inlineQmlComponents()
1112 QQmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
1114 MyContainer *object = qobject_cast<MyContainer *>(component.create());
1115 QVERIFY(object != 0);
1116 QCOMPARE(object->getChildren()->count(), 1);
1117 QQmlComponent *comp = qobject_cast<QQmlComponent *>(object->getChildren()->at(0));
1119 MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
1120 QVERIFY(compObject != 0);
1121 QCOMPARE(compObject->value(), 11);
1124 // Tests that types that have an id property have it set
1125 void tst_qqmllanguage::idProperty()
1127 QQmlComponent component(&engine, TEST_FILE("idProperty.qml"));
1129 MyContainer *object = qobject_cast<MyContainer *>(component.create());
1130 QVERIFY(object != 0);
1131 QCOMPARE(object->getChildren()->count(), 1);
1132 MyTypeObject *child =
1133 qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
1134 QVERIFY(child != 0);
1135 QCOMPARE(child->id(), QString("myObjectId"));
1136 QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
1139 // Tests automatic connection to notify signals if "onBlahChanged" syntax is used
1140 // even if the notify signal for "blah" is not called "blahChanged"
1141 void tst_qqmllanguage::autoNotifyConnection()
1143 QQmlComponent component(&engine, TEST_FILE("autoNotifyConnection.qml"));
1145 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1146 QVERIFY(object != 0);
1147 QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify"));
1148 QVERIFY(prop.isValid());
1150 QCOMPARE(prop.read(object), QVariant::fromValue(false));
1151 object->setPropertyWithNotify(1);
1152 QCOMPARE(prop.read(object), QVariant::fromValue(true));
1155 // Tests that signals can be assigned to
1156 void tst_qqmllanguage::assignSignal()
1158 QQmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
1160 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1161 QVERIFY(object != 0);
1162 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
1163 emit object->basicSignal();
1164 QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
1165 emit object->basicParameterizedSignal(9);
1168 // Tests the creation and assignment of dynamic properties
1169 void tst_qqmllanguage::dynamicProperties()
1171 QQmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
1173 QObject *object = component.create();
1174 QVERIFY(object != 0);
1175 QCOMPARE(object->property("intProperty"), QVariant(10));
1176 QCOMPARE(object->property("boolProperty"), QVariant(false));
1177 QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
1178 QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
1179 QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
1180 QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
1181 QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
1182 QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
1183 QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
1186 // Test that nested types can use dynamic properties
1187 void tst_qqmllanguage::dynamicPropertiesNested()
1189 QQmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
1191 QObject *object = component.create();
1192 QVERIFY(object != 0);
1194 QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
1195 QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
1196 QCOMPARE(object->property("a").toInt(), 13); // New
1197 QCOMPARE(object->property("b").toInt(), 12); // New
1202 // Tests the creation and assignment to dynamic list properties
1203 void tst_qqmllanguage::listProperties()
1205 QQmlComponent component(&engine, TEST_FILE("listProperties.qml"));
1207 QObject *object = component.create();
1208 QVERIFY(object != 0);
1210 QCOMPARE(object->property("test").toInt(), 2);
1213 // Tests the creation and assignment of dynamic object properties
1215 void tst_qqmllanguage::dynamicObjectProperties()
1218 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
1220 QObject *object = component.create();
1221 QVERIFY(object != 0);
1223 QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
1224 QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
1227 QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml"));
1228 QEXPECT_FAIL("", "QTBUG-10822", Abort);
1230 QObject *object = component.create();
1231 QVERIFY(object != 0);
1233 QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0));
1237 // Tests the declaration of dynamic signals and slots
1238 void tst_qqmllanguage::dynamicSignalsAndSlots()
1240 QTest::ignoreMessage(QtDebugMsg, "1921");
1242 QQmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
1244 QObject *object = component.create();
1245 QVERIFY(object != 0);
1246 QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
1247 QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
1248 QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
1249 QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
1251 QCOMPARE(object->property("test").toInt(), 0);
1252 QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
1253 QCOMPARE(object->property("test").toInt(), 10);
1256 void tst_qqmllanguage::simpleBindings()
1258 QQmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
1260 QObject *object = component.create();
1261 QVERIFY(object != 0);
1262 QCOMPARE(object->property("value1"), QVariant(10));
1263 QCOMPARE(object->property("value2"), QVariant(10));
1264 QCOMPARE(object->property("value3"), QVariant(21));
1265 QCOMPARE(object->property("value4"), QVariant(10));
1266 QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
1269 void tst_qqmllanguage::autoComponentCreation()
1271 QQmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
1273 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1274 QVERIFY(object != 0);
1275 QVERIFY(object->componentProperty() != 0);
1276 MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
1277 QVERIFY(child != 0);
1278 QCOMPARE(child->realProperty(), qreal(9));
1281 void tst_qqmllanguage::propertyValueSource()
1284 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
1286 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1287 QVERIFY(object != 0);
1289 QList<QObject *> valueSources;
1290 QObjectList allChildren = object->findChildren<QObject*>();
1291 foreach (QObject *child, allChildren) {
1292 if (qobject_cast<QQmlPropertyValueSource *>(child))
1293 valueSources.append(child);
1296 QCOMPARE(valueSources.count(), 1);
1297 MyPropertyValueSource *valueSource =
1298 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
1299 QVERIFY(valueSource != 0);
1300 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
1301 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
1305 QQmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
1307 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1308 QVERIFY(object != 0);
1310 QList<QObject *> valueSources;
1311 QObjectList allChildren = object->findChildren<QObject*>();
1312 foreach (QObject *child, allChildren) {
1313 if (qobject_cast<QQmlPropertyValueSource *>(child))
1314 valueSources.append(child);
1317 QCOMPARE(valueSources.count(), 1);
1318 MyPropertyValueSource *valueSource =
1319 qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
1320 QVERIFY(valueSource != 0);
1321 QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
1322 QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
1326 void tst_qqmllanguage::attachedProperties()
1328 QQmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
1330 QObject *object = component.create();
1331 QVERIFY(object != 0);
1332 QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
1333 QVERIFY(attached != 0);
1334 QCOMPARE(attached->property("value"), QVariant(10));
1335 QCOMPARE(attached->property("value2"), QVariant(13));
1338 // Tests non-static object properties
1339 void tst_qqmllanguage::dynamicObjects()
1341 QQmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
1343 QObject *object = component.create();
1344 QVERIFY(object != 0);
1347 // Tests the registration of custom variant string converters
1348 void tst_qqmllanguage::customVariantTypes()
1350 QQmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
1352 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1353 QVERIFY(object != 0);
1354 QCOMPARE(object->customType().a, 10);
1357 void tst_qqmllanguage::valueTypes()
1359 QQmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
1362 QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\"";
1363 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
1364 QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
1366 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1367 QVERIFY(object != 0);
1370 QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
1371 QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
1372 QCOMPARE(object->intProperty(), 10);
1374 QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
1375 QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
1376 QCOMPARE(object->intProperty(), 12);
1380 QQmlProperty p(object, "rectProperty.x");
1381 QCOMPARE(p.read(), QVariant(12));
1383 QCOMPARE(p.read(), QVariant(13));
1385 quint32 r = QQmlPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
1387 QQmlPropertyPrivate::restore(p2, r, object);
1388 QCOMPARE(p2.read(), QVariant(13));
1392 void tst_qqmllanguage::cppnamespace()
1395 QQmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
1397 QObject *object = component.create();
1398 QVERIFY(object != 0);
1403 QQmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
1405 QObject *object = component.create();
1406 QVERIFY(object != 0);
1411 void tst_qqmllanguage::aliasProperties()
1413 // Simple "int" alias
1415 QQmlComponent component(&engine, TEST_FILE("alias.1.qml"));
1417 QObject *object = component.create();
1418 QVERIFY(object != 0);
1420 // Read through alias
1421 QCOMPARE(object->property("valueAlias").toInt(), 10);
1422 object->setProperty("value", QVariant(13));
1423 QCOMPARE(object->property("valueAlias").toInt(), 13);
1425 // Write through alias
1426 object->setProperty("valueAlias", QVariant(19));
1427 QCOMPARE(object->property("valueAlias").toInt(), 19);
1428 QCOMPARE(object->property("value").toInt(), 19);
1433 // Complex object alias
1435 QQmlComponent component(&engine, TEST_FILE("alias.2.qml"));
1437 QObject *object = component.create();
1438 QVERIFY(object != 0);
1440 // Read through alias
1442 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1444 QCOMPARE(v->value(), 10);
1446 // Write through alias
1447 MyQmlObject *v2 = new MyQmlObject();
1448 v2->setParent(object);
1449 object->setProperty("aliasObject", qVariantFromValue(v2));
1451 qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
1460 QQmlComponent component(&engine, TEST_FILE("alias.3.qml"));
1462 QObject *object = component.create();
1463 QVERIFY(object != 0);
1465 QCOMPARE(object->property("value").toInt(), 1892);
1466 QCOMPARE(object->property("value2").toInt(), 1892);
1468 object->setProperty("value", QVariant(1313));
1469 QCOMPARE(object->property("value").toInt(), 1313);
1470 QCOMPARE(object->property("value2").toInt(), 1313);
1472 object->setProperty("value2", QVariant(8080));
1473 QCOMPARE(object->property("value").toInt(), 8080);
1474 QCOMPARE(object->property("value2").toInt(), 8080);
1481 QQmlComponent component(&engine, TEST_FILE("alias.4.qml"));
1483 QObject *object = component.create();
1484 QVERIFY(object != 0);
1486 QCOMPARE(object->property("enumAlias").toInt(), 1);
1493 QQmlComponent component(&engine, TEST_FILE("alias.5.qml"));
1495 QObject *object = component.create();
1496 QVERIFY(object != 0);
1498 QVariant v = object->property("otherAlias");
1499 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1500 MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
1501 QCOMPARE(o->value(), 10);
1505 v = object->property("otherAlias");
1506 QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
1507 o = qvariant_cast<MyQmlObject*>(v);
1513 // Nested aliases - this used to cause a crash
1515 QQmlComponent component(&engine, TEST_FILE("alias.6.qml"));
1517 QObject *object = component.create();
1518 QVERIFY(object != 0);
1520 QCOMPARE(object->property("a").toInt(), 1923);
1523 // Ptr Alias Cleanup - check that aliases to ptr types return 0
1524 // if the object aliased to is removed
1526 QQmlComponent component(&engine, TEST_FILE("alias.7.qml"));
1529 QObject *object = component.create();
1530 QVERIFY(object != 0);
1532 QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
1533 QVERIFY(object1 != 0);
1534 QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
1535 QVERIFY(object2 != 0);
1537 QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
1538 QVERIFY(alias == object2);
1542 QObject *alias2 = object; // "Random" start value
1544 void *a[] = { &alias2, 0, &status };
1545 QMetaObject::metacall(object, QMetaObject::ReadProperty,
1546 object->metaObject()->indexOfProperty("aliasedObject"), a);
1547 QVERIFY(alias2 == 0);
1550 // Simple composite type
1552 QQmlComponent component(&engine, TEST_FILE("alias.8.qml"));
1554 QObject *object = component.create();
1555 QVERIFY(object != 0);
1557 QCOMPARE(object->property("value").toInt(), 10);
1562 // Complex composite type
1564 QQmlComponent component(&engine, TEST_FILE("alias.9.qml"));
1566 QObject *object = component.create();
1567 QVERIFY(object != 0);
1569 QCOMPARE(object->property("value").toInt(), 10);
1575 // Simple "int" alias
1577 QQmlComponent component(&engine, TEST_FILE("alias.10.qml"));
1579 QObject *object = component.create();
1580 QVERIFY(object != 0);
1582 // Read through alias
1583 QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8));
1584 object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100)));
1585 QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100));
1587 // Write through alias
1588 object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9)));
1589 QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9));
1590 QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9));
1595 // Valuetype sub-alias
1597 QQmlComponent component(&engine, TEST_FILE("alias.11.qml"));
1599 QObject *object = component.create();
1600 QVERIFY(object != 0);
1602 // Read through alias
1603 QCOMPARE(object->property("aliasProperty").toInt(), 19);
1604 object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111)));
1605 QCOMPARE(object->property("aliasProperty").toInt(), 33);
1607 // Write through alias
1608 object->setProperty("aliasProperty", QVariant(4));
1609 QCOMPARE(object->property("aliasProperty").toInt(), 4);
1610 QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111));
1616 // QTBUG-13374 Test that alias properties and signals can coexist
1617 void tst_qqmllanguage::aliasPropertiesAndSignals()
1619 QQmlComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml"));
1621 QObject *o = component.create();
1623 QCOMPARE(o->property("test").toBool(), true);
1627 // Test that the root element in a composite type can be a Component
1628 void tst_qqmllanguage::componentCompositeType()
1630 QQmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
1632 QObject *object = component.create();
1633 QVERIFY(object != 0);
1636 class TestType : public QObject {
1639 TestType(QObject *p=0) : QObject(p) {}
1642 class TestType2 : public QObject {
1645 TestType2(QObject *p=0) : QObject(p) {}
1648 void tst_qqmllanguage::i18n_data()
1650 QTest::addColumn<QString>("file");
1651 QTest::addColumn<QString>("stringProperty");
1652 QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
1653 QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
1654 QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
1655 QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
1656 QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
1657 QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
1660 void tst_qqmllanguage::i18n()
1662 QFETCH(QString, file);
1663 QFETCH(QString, stringProperty);
1664 QQmlComponent component(&engine, TEST_FILE(file));
1666 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
1667 QVERIFY(object != 0);
1668 QCOMPARE(object->stringProperty(), stringProperty);
1673 // Check that the Component::onCompleted attached property works
1674 void tst_qqmllanguage::onCompleted()
1676 QQmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
1678 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1679 QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
1680 QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
1681 QObject *object = component.create();
1682 QVERIFY(object != 0);
1685 // Check that the Component::onDestruction attached property works
1686 void tst_qqmllanguage::onDestruction()
1688 QQmlComponent component(&engine, TEST_FILE("onDestruction.qml"));
1690 QObject *object = component.create();
1691 QVERIFY(object != 0);
1692 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1693 QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
1694 QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11");
1698 // Check that assignments to QQmlScriptString properties work
1699 void tst_qqmllanguage::scriptString()
1702 QQmlComponent component(&engine, TEST_FILE("scriptString.qml"));
1705 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1706 QVERIFY(object != 0);
1707 QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
1708 QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast<QObject*>(object));
1709 QCOMPARE(object->scriptProperty().context(), qmlContext(object));
1711 QVERIFY(object->grouped() != 0);
1712 QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
1713 QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast<QObject*>(object));
1714 QCOMPARE(object->grouped()->script().context(), qmlContext(object));
1718 QQmlComponent component(&engine, TEST_FILE("scriptString2.qml"));
1721 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1722 QVERIFY(object != 0);
1723 QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\""));
1727 QQmlComponent component(&engine, TEST_FILE("scriptString3.qml"));
1730 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1731 QVERIFY(object != 0);
1732 QCOMPARE(object->scriptProperty().script(), QString("12.345"));
1736 QQmlComponent component(&engine, TEST_FILE("scriptString4.qml"));
1739 MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
1740 QVERIFY(object != 0);
1741 QCOMPARE(object->scriptProperty().script(), QString("true"));
1745 // Check that default property assignments are correctly spliced into explicit
1746 // property assignments
1747 void tst_qqmllanguage::defaultPropertyListOrder()
1749 QQmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
1752 MyContainer *container = qobject_cast<MyContainer *>(component.create());
1753 QVERIFY(container != 0);
1755 QCOMPARE(container->getChildren()->count(), 6);
1756 QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0));
1757 QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1));
1758 QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2));
1759 QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3));
1760 QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4));
1761 QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5));
1764 void tst_qqmllanguage::declaredPropertyValues()
1766 QQmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
1770 void tst_qqmllanguage::dontDoubleCallClassBegin()
1772 QQmlComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml"));
1773 QObject *o = component.create();
1776 MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object")));
1778 QCOMPARE(o2->classBeginCount(), 1);
1779 QCOMPARE(o2->componentCompleteCount(), 1);
1784 void tst_qqmllanguage::reservedWords_data()
1786 QTest::addColumn<QByteArray>("word");
1788 QTest::newRow("abstract") << QByteArray("abstract");
1789 QTest::newRow("as") << QByteArray("as");
1790 QTest::newRow("boolean") << QByteArray("boolean");
1791 QTest::newRow("break") << QByteArray("break");
1792 QTest::newRow("byte") << QByteArray("byte");
1793 QTest::newRow("case") << QByteArray("case");
1794 QTest::newRow("catch") << QByteArray("catch");
1795 QTest::newRow("char") << QByteArray("char");
1796 QTest::newRow("class") << QByteArray("class");
1797 QTest::newRow("continue") << QByteArray("continue");
1798 QTest::newRow("const") << QByteArray("const");
1799 QTest::newRow("debugger") << QByteArray("debugger");
1800 QTest::newRow("default") << QByteArray("default");
1801 QTest::newRow("delete") << QByteArray("delete");
1802 QTest::newRow("do") << QByteArray("do");
1803 QTest::newRow("double") << QByteArray("double");
1804 QTest::newRow("else") << QByteArray("else");
1805 QTest::newRow("enum") << QByteArray("enum");
1806 QTest::newRow("export") << QByteArray("export");
1807 QTest::newRow("extends") << QByteArray("extends");
1808 QTest::newRow("false") << QByteArray("false");
1809 QTest::newRow("final") << QByteArray("final");
1810 QTest::newRow("finally") << QByteArray("finally");
1811 QTest::newRow("float") << QByteArray("float");
1812 QTest::newRow("for") << QByteArray("for");
1813 QTest::newRow("function") << QByteArray("function");
1814 QTest::newRow("goto") << QByteArray("goto");
1815 QTest::newRow("if") << QByteArray("if");
1816 QTest::newRow("implements") << QByteArray("implements");
1817 QTest::newRow("import") << QByteArray("import");
1818 QTest::newRow("in") << QByteArray("in");
1819 QTest::newRow("instanceof") << QByteArray("instanceof");
1820 QTest::newRow("int") << QByteArray("int");
1821 QTest::newRow("interface") << QByteArray("interface");
1822 QTest::newRow("long") << QByteArray("long");
1823 QTest::newRow("native") << QByteArray("native");
1824 QTest::newRow("new") << QByteArray("new");
1825 QTest::newRow("null") << QByteArray("null");
1826 QTest::newRow("package") << QByteArray("package");
1827 QTest::newRow("private") << QByteArray("private");
1828 QTest::newRow("protected") << QByteArray("protected");
1829 QTest::newRow("public") << QByteArray("public");
1830 QTest::newRow("return") << QByteArray("return");
1831 QTest::newRow("short") << QByteArray("short");
1832 QTest::newRow("static") << QByteArray("static");
1833 QTest::newRow("super") << QByteArray("super");
1834 QTest::newRow("switch") << QByteArray("switch");
1835 QTest::newRow("synchronized") << QByteArray("synchronized");
1836 QTest::newRow("this") << QByteArray("this");
1837 QTest::newRow("throw") << QByteArray("throw");
1838 QTest::newRow("throws") << QByteArray("throws");
1839 QTest::newRow("transient") << QByteArray("transient");
1840 QTest::newRow("true") << QByteArray("true");
1841 QTest::newRow("try") << QByteArray("try");
1842 QTest::newRow("typeof") << QByteArray("typeof");
1843 QTest::newRow("var") << QByteArray("var");
1844 QTest::newRow("void") << QByteArray("void");
1845 QTest::newRow("volatile") << QByteArray("volatile");
1846 QTest::newRow("while") << QByteArray("while");
1847 QTest::newRow("with") << QByteArray("with");
1850 void tst_qqmllanguage::reservedWords()
1852 QFETCH(QByteArray, word);
1853 QQmlComponent component(&engine);
1854 component.setData("import QtQuick 2.0\nQtObject { property string " + word + " }", QUrl());
1855 QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n"));
1858 // Check that first child of qml is of given type. Empty type insists on error.
1859 void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror, bool partialMatch)
1861 QQmlComponent component(&engine);
1862 component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
1864 QTRY_VERIFY(!component.isLoading());
1866 if (type.isEmpty()) {
1867 QVERIFY(component.isError());
1868 QString actualerror;
1869 foreach (const QQmlError e, component.errors()) {
1870 if (!actualerror.isEmpty())
1871 actualerror.append("; ");
1872 actualerror.append(e.description());
1874 QCOMPARE(actualerror.left(partialMatch ? expectederror.length(): -1),expectederror);
1877 QObject *object = component.create();
1878 QVERIFY(object != 0);
1879 QCOMPARE(QString(object->metaObject()->className()), type);
1885 void tst_qqmllanguage::inlineAssignmentsOverrideBindings()
1887 QQmlComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml"));
1889 QObject *o = component.create();
1891 QCOMPARE(o->property("test").toInt(), 11);
1896 void tst_qqmllanguage::nestedComponentRoots()
1898 QQmlComponent component(&engine, TEST_FILE("nestedComponentRoots.qml"));
1901 // Import tests (QT-558)
1902 void tst_qqmllanguage::importsBuiltin_data()
1906 QTest::addColumn<QString>("qml");
1907 QTest::addColumn<QString>("type");
1908 QTest::addColumn<QString>("error");
1911 QTest::newRow("missing import")
1914 << "Test is not a type";
1915 QTest::newRow("not in version 0.0")
1916 << "import com.nokia.Test 0.0\n"
1919 << "Test is not a type";
1920 QTest::newRow("version not installed")
1921 << "import com.nokia.Test 99.0\n"
1924 << "module \"com.nokia.Test\" version 99.0 is not installed";
1925 QTest::newRow("in version 0.0")
1926 << "import com.nokia.Test 0.0\n"
1930 QTest::newRow("qualified in version 0.0")
1931 << "import com.nokia.Test 0.0 as T\n"
1935 QTest::newRow("in version 1.0")
1936 << "import com.nokia.Test 1.0\n"
1940 QTest::newRow("qualified wrong")
1941 << "import com.nokia.Test 1.0 as T\n" // QT-610
1944 << "Test is not a type";
1945 QTest::newRow("qualified right")
1946 << "import com.nokia.Test 1.0 as T\n"
1950 QTest::newRow("qualified right but not in version 0.0")
1951 << "import com.nokia.Test 0.0 as T\n"
1954 << "T.Test is not a type";
1955 QTest::newRow("in version 1.1")
1956 << "import com.nokia.Test 1.1\n"
1960 QTest::newRow("in version 1.3")
1961 << "import com.nokia.Test 1.3\n"
1965 QTest::newRow("in version 1.5")
1966 << "import com.nokia.Test 1.5\n"
1970 QTest::newRow("changed in version 1.8")
1971 << "import com.nokia.Test 1.8\n"
1975 QTest::newRow("in version 1.12")
1976 << "import com.nokia.Test 1.12\n"
1980 QTest::newRow("old in version 1.9")
1981 << "import com.nokia.Test 1.9\n"
1985 QTest::newRow("old in version 1.11")
1986 << "import com.nokia.Test 1.11\n"
1990 QTest::newRow("multiversion 1")
1991 << "import com.nokia.Test 1.11\n"
1992 "import com.nokia.Test 1.12\n"
1994 << (!qmlCheckTypes()?"TestType2":"")
1995 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
1996 QTest::newRow("multiversion 2")
1997 << "import com.nokia.Test 1.11\n"
1998 "import com.nokia.Test 1.12\n"
2000 << (!qmlCheckTypes()?"TestType":"")
2001 << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
2002 QTest::newRow("qualified multiversion 3")
2003 << "import com.nokia.Test 1.0 as T0\n"
2004 "import com.nokia.Test 1.8 as T8\n"
2008 QTest::newRow("qualified multiversion 4")
2009 << "import com.nokia.Test 1.0 as T0\n"
2010 "import com.nokia.Test 1.8 as T8\n"
2016 void tst_qqmllanguage::importsBuiltin()
2018 QFETCH(QString, qml);
2019 QFETCH(QString, type);
2020 QFETCH(QString, error);
2021 testType(qml,type,error);
2024 void tst_qqmllanguage::importsLocal_data()
2026 QTest::addColumn<QString>("qml");
2027 QTest::addColumn<QString>("type");
2028 QTest::addColumn<QString>("error");
2031 QTest::newRow("local import")
2032 << "import \"subdir\"\n" // QT-613
2034 << "QQuickRectangle"
2036 QTest::newRow("local import second")
2037 << "import QtQuick 2.0\nimport \"subdir\"\n"
2039 << "QQuickRectangle"
2041 QTest::newRow("local import subsubdir")
2042 << "import QtQuick 2.0\nimport \"subdir/subsubdir\"\n"
2044 << "QQuickRectangle"
2046 QTest::newRow("local import QTBUG-7721 A")
2047 << "subdir.Test {}" // no longer allowed (QTBUG-7721)
2049 << "subdir.Test - subdir is not a namespace";
2050 QTest::newRow("local import QTBUG-7721 B")
2051 << "import \"subdir\" as X\n"
2052 "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
2054 << "X.subsubdir.SubTest - nested namespaces not allowed";
2055 QTest::newRow("local import as")
2056 << "import \"subdir\" as T\n"
2058 << "QQuickRectangle"
2060 QTest::newRow("wrong local import as")
2061 << "import \"subdir\" as T\n"
2064 << "Test is not a type";
2065 QTest::newRow("library precedence over local import")
2066 << "import \"subdir\"\n"
2067 "import com.nokia.Test 1.0\n"
2069 << (!qmlCheckTypes()?"TestType":"")
2070 << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ and in subdir/");
2073 void tst_qqmllanguage::importsLocal()
2075 QFETCH(QString, qml);
2076 QFETCH(QString, type);
2077 QFETCH(QString, error);
2078 testType(qml,type,error);
2081 void tst_qqmllanguage::basicRemote_data()
2083 QTest::addColumn<QUrl>("url");
2084 QTest::addColumn<QString>("type");
2085 QTest::addColumn<QString>("error");
2087 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage/";
2089 QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
2090 QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
2091 QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
2094 void tst_qqmllanguage::basicRemote()
2097 QFETCH(QString, type);
2098 QFETCH(QString, error);
2100 TestHTTPServer server(14447);
2101 server.serveDirectory(testdata());
2103 QQmlComponent component(&engine, url);
2105 QTRY_VERIFY(!component.isLoading());
2107 if (error.isEmpty()) {
2108 if (component.isError())
2109 qDebug() << component.errors();
2110 QVERIFY(!component.isError());
2112 QVERIFY(component.isError());
2116 void tst_qqmllanguage::importsRemote_data()
2118 QTest::addColumn<QString>("qml");
2119 QTest::addColumn<QString>("type");
2120 QTest::addColumn<QString>("error");
2122 QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage";
2124 QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QQuickRectangle"
2126 QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QQuickText"
2128 QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
2130 QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
2131 << "WrongTestLocal is not a type";
2132 QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
2133 << "LocalInternal is not a type";
2134 QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << ""
2135 << "UndeclaredLocal is not a type";
2138 void tst_qqmllanguage::importsRemote()
2140 QFETCH(QString, qml);
2141 QFETCH(QString, type);
2142 QFETCH(QString, error);
2144 TestHTTPServer server(14447);
2145 server.serveDirectory(testdata());
2147 testType(qml,type,error);
2150 void tst_qqmllanguage::importsInstalled_data()
2154 QTest::addColumn<QString>("qml");
2155 QTest::addColumn<QString>("type");
2156 QTest::addColumn<QString>("error");
2159 QTest::newRow("installed import 0")
2160 << "import com.nokia.installedtest0 0.0\n"
2161 "InstalledTestTP {}"
2162 << "QQuickRectangle"
2164 QTest::newRow("installed import 0 as TP")
2165 << "import com.nokia.installedtest0 0.0 as TP\n"
2166 "TP.InstalledTestTP {}"
2167 << "QQuickRectangle"
2169 QTest::newRow("installed import 1")
2170 << "import com.nokia.installedtest 1.0\n"
2172 << "QQuickRectangle"
2174 QTest::newRow("installed import 2")
2175 << "import com.nokia.installedtest 1.3\n"
2177 << "QQuickRectangle"
2179 QTest::newRow("installed import 3")
2180 << "import com.nokia.installedtest 1.4\n"
2184 QTest::newRow("installed import minor version not available") // QTBUG-11936
2185 << "import com.nokia.installedtest 0.1\n"
2188 << "module \"com.nokia.installedtest\" version 0.1 is not installed";
2189 QTest::newRow("installed import minor version not available") // QTBUG-9627
2190 << "import com.nokia.installedtest 1.10\n"
2193 << "module \"com.nokia.installedtest\" version 1.10 is not installed";
2194 QTest::newRow("installed import major version not available") // QTBUG-9627
2195 << "import com.nokia.installedtest 9.0\n"
2198 << "module \"com.nokia.installedtest\" version 9.0 is not installed";
2199 QTest::newRow("installed import visibility") // QT-614
2200 << "import com.nokia.installedtest 1.4\n"
2203 << "PrivateType is not a type";
2204 QTest::newRow("installed import version QML clash")
2205 << "import com.nokia.installedtest1 1.0\n"
2208 << "\"Test\" version 1.0 is already defined in module \"com.nokia.installedtest1\"";
2209 QTest::newRow("installed import version JS clash")
2210 << "import com.nokia.installedtest2 1.0\n"
2213 << "\"Test\" version 1.0 is already defined in module \"com.nokia.installedtest2\"";
2216 void tst_qqmllanguage::importsInstalled()
2218 QFETCH(QString, qml);
2219 QFETCH(QString, type);
2220 QFETCH(QString, error);
2221 testType(qml,type,error);
2225 void tst_qqmllanguage::importsOrder_data()
2227 QTest::addColumn<QString>("qml");
2228 QTest::addColumn<QString>("type");
2229 QTest::addColumn<QString>("error");
2230 QTest::addColumn<bool>("partialMatch");
2232 QTest::newRow("double import") <<
2233 "import com.nokia.installedtest 1.4\n"
2234 "import com.nokia.installedtest 1.4\n"
2236 << (!qmlCheckTypes()?"QQuickText":"")
2237 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.4")
2239 QTest::newRow("installed import overrides 1") <<
2240 "import com.nokia.installedtest 1.0\n"
2241 "import com.nokia.installedtest 1.4\n"
2243 << (!qmlCheckTypes()?"QQuickText":"")
2244 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
2246 QTest::newRow("installed import overrides 2") <<
2247 "import com.nokia.installedtest 1.4\n"
2248 "import com.nokia.installedtest 1.0\n"
2250 << (!qmlCheckTypes()?"QQuickRectangle":"")
2251 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
2253 QTest::newRow("installed import re-overrides 1") <<
2254 "import com.nokia.installedtest 1.4\n"
2255 "import com.nokia.installedtest 1.0\n"
2256 "import com.nokia.installedtest 1.4\n"
2258 << (!qmlCheckTypes()?"QQuickText":"")
2259 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
2261 QTest::newRow("installed import re-overrides 2") <<
2262 "import com.nokia.installedtest 1.4\n"
2263 "import com.nokia.installedtest 1.0\n"
2264 "import com.nokia.installedtest 1.4\n"
2265 "import com.nokia.installedtest 1.0\n"
2267 << (!qmlCheckTypes()?"QQuickRectangle":"")
2268 << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
2270 QTest::newRow("installed import versus builtin 1") <<
2271 "import com.nokia.installedtest 1.5\n"
2272 "import QtQuick 2.0\n"
2274 << (!qmlCheckTypes()?"QQuickRectangle":"")
2275 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in file://")
2277 QTest::newRow("installed import versus builtin 2") <<
2278 "import QtQuick 2.0\n"
2279 "import com.nokia.installedtest 1.5\n"
2281 << (!qmlCheckTypes()?"QQuickText":"")
2282 << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest/ and in file://")
2284 QTest::newRow("namespaces cannot be overridden by types 1") <<
2285 "import QtQuick 2.0 as Rectangle\n"
2286 "import com.nokia.installedtest 1.5\n"
2289 << "Namespace Rectangle cannot be used as a type"
2291 QTest::newRow("namespaces cannot be overridden by types 2") <<
2292 "import QtQuick 2.0 as Rectangle\n"
2293 "import com.nokia.installedtest 1.5\n"
2294 "Rectangle.Image {}"
2298 QTest::newRow("local last 1") <<
2303 QTest::newRow("local last 2") <<
2304 "import com.nokia.installedtest 1.0\n"
2306 << (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
2307 << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest/ and in ")
2311 void tst_qqmllanguage::importsOrder()
2313 QFETCH(QString, qml);
2314 QFETCH(QString, type);
2315 QFETCH(QString, error);
2316 QFETCH(bool, partialMatch);
2317 testType(qml,type,error,partialMatch);
2320 void tst_qqmllanguage::importIncorrectCase()
2322 QQmlComponent component(&engine, TEST_FILE("importIncorrectCase.qml"));
2324 QList<QQmlError> errors = component.errors();
2325 QCOMPARE(errors.count(), 1);
2327 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
2328 QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + testdata("lib/com/Nokia/installedtest/qmldir") + QLatin1String("\"");
2330 QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed");
2333 QCOMPARE(errors.at(0).description(), expectedError);
2336 void tst_qqmllanguage::importJs_data()
2338 QTest::addColumn<QString>("file");
2339 QTest::addColumn<QString>("errorFile");
2340 QTest::addColumn<bool>("performTest");
2342 QTest::newRow("defaultVersion")
2344 << "importJs.1.errors.txt"
2347 QTest::newRow("specifiedVersion")
2349 << "importJs.2.errors.txt"
2352 QTest::newRow("excludeExcessiveVersion")
2354 << "importJs.3.errors.txt"
2357 QTest::newRow("includeAppropriateVersion")
2359 << "importJs.4.errors.txt"
2362 QTest::newRow("noDefaultVersion")
2364 << "importJs.5.errors.txt"
2367 QTest::newRow("repeatImportFails")
2369 << "importJs.6.errors.txt"
2372 QTest::newRow("multipleVersionImportFails")
2374 << "importJs.7.errors.txt"
2377 QTest::newRow("namespacedImport")
2379 << "importJs.8.errors.txt"
2382 QTest::newRow("namespacedVersionedImport")
2384 << "importJs.9.errors.txt"
2387 QTest::newRow("namespacedRepeatImport")
2388 << "importJs.10.qml"
2389 << "importJs.10.errors.txt"
2393 void tst_qqmllanguage::importJs()
2395 QFETCH(QString, file);
2396 QFETCH(QString, errorFile);
2397 QFETCH(bool, performTest);
2399 QQmlComponent component(&engine, TEST_FILE(file));
2402 DETERMINE_ERRORS(errorFile.toLatin1().constData(),expected,actual);
2403 QCOMPARE(expected.size(), actual.size());
2404 for (int i = 0; i < expected.size(); ++i)
2406 size_t compareLen = std::min(expected.at(i).length(), actual.at(i).length());
2407 QCOMPARE(expected.at(i).left(compareLen), actual.at(i).left(compareLen));
2412 QObject *object = component.create();
2413 QVERIFY(object != 0);
2414 QCOMPARE(object->property("test").toBool(),true);
2419 void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
2423 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
2424 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
2427 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
2429 QObject *object = component.create();
2430 QVERIFY(object != 0);
2432 QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
2433 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2437 QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
2439 QObject *object = component.create();
2440 QVERIFY(object != 0);
2442 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
2443 QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
2447 void tst_qqmllanguage::crash1()
2449 QQmlComponent component(&engine);
2450 component.setData("import QtQuick 2.0\nComponent {}", QUrl());
2453 void tst_qqmllanguage::crash2()
2455 QQmlComponent component(&engine, TEST_FILE("crash2.qml"));
2459 void tst_qqmllanguage::customOnProperty()
2461 QQmlComponent component(&engine, TEST_FILE("customOnProperty.qml"));
2464 QObject *object = component.create();
2465 QVERIFY(object != 0);
2467 QCOMPARE(object->property("on").toInt(), 10);
2473 void tst_qqmllanguage::variantNotify()
2475 QQmlComponent component(&engine, TEST_FILE("variantNotify.qml"));
2478 QObject *object = component.create();
2479 QVERIFY(object != 0);
2481 QCOMPARE(object->property("notifyCount").toInt(), 1);
2486 void tst_qqmllanguage::revisions()
2489 QQmlComponent component(&engine, TEST_FILE("revisions11.qml"));
2492 MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create());
2493 QVERIFY(object != 0);
2495 QCOMPARE(object->prop2(), 10.0);
2500 QQmlEngine myEngine;
2501 QQmlComponent component(&myEngine, TEST_FILE("revisionssub11.qml"));
2504 MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create());
2505 QVERIFY(object != 0);
2507 QCOMPARE(object->prop1(), 10.0);
2508 QCOMPARE(object->prop2(), 10.0);
2509 QCOMPARE(object->prop3(), 10.0);
2510 QCOMPARE(object->prop4(), 10.0);
2515 QQmlComponent component(&engine, TEST_FILE("versionedbase.qml"));
2517 MySubclass *object = qobject_cast<MySubclass*>(component.create());
2518 QVERIFY(object != 0);
2520 QCOMPARE(object->prop1(), 10.0);
2521 QCOMPARE(object->prop2(), 10.0);
2527 void tst_qqmllanguage::revisionOverloads()
2530 QQmlComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml"));
2534 QQmlComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml"));
2535 QEXPECT_FAIL("", "QTBUG-13849", Abort);
2537 VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt");
2541 void tst_qqmllanguage::initTestCase()
2543 QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();
2544 QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
2548 // Registering the TestType class in other modules should have no adverse effects
2549 qmlRegisterType<TestType>("com.nokia.TestPre", 1, 0, "Test");
2551 qmlRegisterType<TestType>("com.nokia.Test", 0, 0, "TestTP");
2552 qmlRegisterType<TestType>("com.nokia.Test", 1, 0, "Test");
2553 qmlRegisterType<TestType>("com.nokia.Test", 1, 5, "Test");
2554 qmlRegisterType<TestType2>("com.nokia.Test", 1, 8, "Test");
2555 qmlRegisterType<TestType>("com.nokia.Test", 1, 9, "OldTest");
2556 qmlRegisterType<TestType2>("com.nokia.Test", 1, 12, "Test");
2558 // Registering the TestType class in other modules should have no adverse effects
2559 qmlRegisterType<TestType>("com.nokia.TestPost", 1, 0, "Test");
2561 // Create locale-specific file
2562 // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
2563 // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
2564 // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
2565 QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
2566 QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString())));
2567 QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
2568 QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString())));
2569 out.write(in.readAll());
2572 void tst_qqmllanguage::aliasPropertyChangeSignals()
2575 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml"));
2578 QObject *o = component.create();
2581 QCOMPARE(o->property("test").toBool(), true);
2586 // QTCREATORBUG-2769
2588 QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml"));
2591 QObject *o = component.create();
2594 QCOMPARE(o->property("test").toBool(), true);
2600 // Tests property initializers
2601 void tst_qqmllanguage::propertyInit()
2604 QQmlComponent component(&engine, TEST_FILE("propertyInit.1.qml"));
2607 QObject *o = component.create();
2610 QCOMPARE(o->property("test").toInt(), 1);
2616 QQmlComponent component(&engine, TEST_FILE("propertyInit.2.qml"));
2619 QObject *o = component.create();
2622 QCOMPARE(o->property("test").toInt(), 123);
2628 // Test that registration order doesn't break type availability
2630 void tst_qqmllanguage::registrationOrder()
2632 QQmlComponent component(&engine, TEST_FILE("registrationOrder.qml"));
2634 QObject *o = component.create();
2636 QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
2640 void tst_qqmllanguage::readonly()
2642 QQmlComponent component(&engine, TEST_FILE("readonly.qml"));
2644 QObject *o = component.create();
2647 QCOMPARE(o->property("test1").toInt(), 10);
2648 QCOMPARE(o->property("test2").toInt(), 18);
2649 QCOMPARE(o->property("test3").toInt(), 13);
2651 o->setProperty("testData", 13);
2653 QCOMPARE(o->property("test1").toInt(), 10);
2654 QCOMPARE(o->property("test2").toInt(), 22);
2655 QCOMPARE(o->property("test3").toInt(), 13);
2657 o->setProperty("testData2", 2);
2659 QCOMPARE(o->property("test1").toInt(), 10);
2660 QCOMPARE(o->property("test2").toInt(), 22);
2661 QCOMPARE(o->property("test3").toInt(), 2);
2663 o->setProperty("test1", 11);
2664 o->setProperty("test2", 11);
2665 o->setProperty("test3", 11);
2667 QCOMPARE(o->property("test1").toInt(), 10);
2668 QCOMPARE(o->property("test2").toInt(), 22);
2669 QCOMPARE(o->property("test3").toInt(), 2);
2674 void tst_qqmllanguage::receivers()
2676 QQmlComponent component(&engine, TEST_FILE("receivers.qml"));
2678 MyReceiversTestObject *o = qobject_cast<MyReceiversTestObject*>(component.create());
2680 QCOMPARE(o->mySignalCount(), 1);
2681 QCOMPARE(o->propChangedCount(), 2);
2687 void tst_qqmllanguage::remoteLoadCrash()
2689 TestHTTPServer server(14448);
2690 server.serveDirectory(testdata());
2692 QQmlComponent component(&engine);
2693 component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
2694 while (component.isLoading())
2695 QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
2697 QObject *o = component.create();
2701 void tst_qqmllanguage::signalWithDefaultArg()
2703 QQmlComponent component(&engine, TEST_FILE("signalWithDefaultArg.qml"));
2705 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2706 QVERIFY(object != 0);
2708 QCOMPARE(object->property("signalCount").toInt(), 0);
2709 QCOMPARE(object->property("signalArg").toInt(), 0);
2711 emit object->signalWithDefaultArg();
2712 QCOMPARE(object-> property("signalCount").toInt(), 1);
2713 QCOMPARE(object->property("signalArg").toInt(), 5);
2715 emit object->signalWithDefaultArg(15);
2716 QCOMPARE(object->property("signalCount").toInt(), 2);
2717 QCOMPARE(object->property("signalArg").toInt(), 15);
2719 const QMetaObject *metaObject = object->metaObject();
2721 metaObject->invokeMethod(object, "emitNoArgSignal");
2722 QCOMPARE(object->property("signalCount").toInt(), 3);
2723 QCOMPARE(object->property("signalArg").toInt(), 5);
2725 metaObject->invokeMethod(object, "emitArgSignal");
2726 QCOMPARE(object->property("signalCount").toInt(), 4);
2727 QCOMPARE(object->property("signalArg").toInt(), 22);
2733 void tst_qqmllanguage::globalEnums()
2735 qRegisterMetaType<MyEnum1Class::EnumA>();
2736 qRegisterMetaType<MyEnum2Class::EnumB>();
2737 qRegisterMetaType<Qt::TextFormat>();
2739 QQmlComponent component(&engine, TEST_FILE("globalEnums.qml"));
2741 QObject *o = component.create();
2744 MyEnum1Class *enum1Class = o->findChild<MyEnum1Class *>(QString::fromLatin1("enum1Class"));
2745 QVERIFY(enum1Class != 0);
2746 QVERIFY(enum1Class->getValue() == -1);
2748 MyEnumDerivedClass *enum2Class = o->findChild<MyEnumDerivedClass *>(QString::fromLatin1("enumDerivedClass"));
2749 QVERIFY(enum2Class != 0);
2750 QVERIFY(enum2Class->getValueA() == -1);
2751 QVERIFY(enum2Class->getValueB() == -1);
2752 QVERIFY(enum2Class->getValueC() == 0);
2753 QVERIFY(enum2Class->getValueD() == 0);
2754 QVERIFY(enum2Class->getValueE() == -1);
2755 QVERIFY(enum2Class->getValueE2() == -1);
2757 QVERIFY(enum2Class->property("aValue") == 0);
2758 QVERIFY(enum2Class->property("bValue") == 0);
2759 QVERIFY(enum2Class->property("cValue") == 0);
2760 QVERIFY(enum2Class->property("dValue") == 0);
2761 QVERIFY(enum2Class->property("eValue") == 0);
2762 QVERIFY(enum2Class->property("e2Value") == 0);
2764 QSignalSpy signalA(enum2Class, SIGNAL(valueAChanged(MyEnum1Class::EnumA)));
2765 QSignalSpy signalB(enum2Class, SIGNAL(valueBChanged(MyEnum2Class::EnumB)));
2767 QMetaObject::invokeMethod(o, "setEnumValues");
2769 QVERIFY(enum1Class->getValue() == MyEnum1Class::A_13);
2770 QVERIFY(enum2Class->getValueA() == MyEnum1Class::A_11);
2771 QVERIFY(enum2Class->getValueB() == MyEnum2Class::B_37);
2772 QVERIFY(enum2Class->getValueC() == Qt::RichText);
2773 QVERIFY(enum2Class->getValueD() == Qt::ElideMiddle);
2774 QVERIFY(enum2Class->getValueE() == MyEnum2Class::E_14);
2775 QVERIFY(enum2Class->getValueE2() == MyEnum2Class::E_76);
2777 QVERIFY(signalA.count() == 1);
2778 QVERIFY(signalB.count() == 1);
2780 QVERIFY(enum2Class->property("aValue") == MyEnum1Class::A_11);
2781 QVERIFY(enum2Class->property("bValue") == 37);
2782 QVERIFY(enum2Class->property("cValue") == 1);
2783 QVERIFY(enum2Class->property("dValue") == 2);
2784 QVERIFY(enum2Class->property("eValue") == 14);
2785 QVERIFY(enum2Class->property("e2Value") == 76);
2790 QTEST_MAIN(tst_qqmllanguage)
2792 #include "tst_qqmllanguage.moc"