1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include <QDeclarativeEngine>
45 #include <QDeclarativeContext>
46 #include <QDeclarativeComponent>
47 #include <QDeclarativeExpression>
50 // In Symbian OS test data is located in applications private dir
54 class tst_qdeclarativecontext : public QObject
58 tst_qdeclarativecontext() {}
65 void setContextProperty();
66 void setContextObject();
68 void idAsContextProperty();
69 void readOnlyContexts();
72 QDeclarativeEngine engine;
75 void tst_qdeclarativecontext::baseUrl()
77 QDeclarativeContext ctxt(&engine);
79 QCOMPARE(ctxt.baseUrl(), QUrl());
81 ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
83 QCOMPARE(ctxt.baseUrl(), QUrl("http://www.nokia.com/"));
86 void tst_qdeclarativecontext::resolvedUrl()
88 // Relative to the component
90 QDeclarativeContext ctxt(&engine);
91 ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
93 QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), QUrl("http://www.nokia.com/main.qml"));
96 // Relative to a parent
98 QDeclarativeContext ctxt(&engine);
99 ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
101 QDeclarativeContext ctxt2(&ctxt);
102 QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
105 // Relative to the engine
107 QDeclarativeContext ctxt(&engine);
108 QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), engine.baseUrl().resolved(QUrl("main.qml")));
111 // Relative to a deleted parent
113 QDeclarativeContext *ctxt = new QDeclarativeContext(&engine);
114 ctxt->setBaseUrl(QUrl("http://www.nokia.com/"));
116 QDeclarativeContext ctxt2(ctxt);
117 QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
119 delete ctxt; ctxt = 0;
121 QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
126 QDeclarativeContext ctxt(&engine);
128 QCOMPARE(ctxt.resolvedUrl(QUrl("http://www.nokia.com/main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
129 QCOMPARE(ctxt.resolvedUrl(QUrl("file:///main2.qml")), QUrl("file:///main2.qml"));
133 void tst_qdeclarativecontext::engineMethod()
135 QDeclarativeEngine *engine = new QDeclarativeEngine;
137 QDeclarativeContext ctxt(engine);
138 QDeclarativeContext ctxt2(&ctxt);
139 QDeclarativeContext ctxt3(&ctxt2);
140 QDeclarativeContext ctxt4(&ctxt2);
142 QCOMPARE(ctxt.engine(), engine);
143 QCOMPARE(ctxt2.engine(), engine);
144 QCOMPARE(ctxt3.engine(), engine);
145 QCOMPARE(ctxt4.engine(), engine);
147 delete engine; engine = 0;
149 QCOMPARE(ctxt.engine(), engine);
150 QCOMPARE(ctxt2.engine(), engine);
151 QCOMPARE(ctxt3.engine(), engine);
152 QCOMPARE(ctxt4.engine(), engine);
155 void tst_qdeclarativecontext::parentContext()
157 QDeclarativeEngine *engine = new QDeclarativeEngine;
159 QCOMPARE(engine->rootContext()->parentContext(), (QDeclarativeContext *)0);
161 QDeclarativeContext *ctxt = new QDeclarativeContext(engine);
162 QDeclarativeContext *ctxt2 = new QDeclarativeContext(ctxt);
163 QDeclarativeContext *ctxt3 = new QDeclarativeContext(ctxt2);
164 QDeclarativeContext *ctxt4 = new QDeclarativeContext(ctxt2);
165 QDeclarativeContext *ctxt5 = new QDeclarativeContext(ctxt);
166 QDeclarativeContext *ctxt6 = new QDeclarativeContext(engine);
167 QDeclarativeContext *ctxt7 = new QDeclarativeContext(engine->rootContext());
169 QCOMPARE(ctxt->parentContext(), engine->rootContext());
170 QCOMPARE(ctxt2->parentContext(), ctxt);
171 QCOMPARE(ctxt3->parentContext(), ctxt2);
172 QCOMPARE(ctxt4->parentContext(), ctxt2);
173 QCOMPARE(ctxt5->parentContext(), ctxt);
174 QCOMPARE(ctxt6->parentContext(), engine->rootContext());
175 QCOMPARE(ctxt7->parentContext(), engine->rootContext());
177 delete ctxt2; ctxt2 = 0;
179 QCOMPARE(ctxt->parentContext(), engine->rootContext());
180 QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0);
181 QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0);
182 QCOMPARE(ctxt5->parentContext(), ctxt);
183 QCOMPARE(ctxt6->parentContext(), engine->rootContext());
184 QCOMPARE(ctxt7->parentContext(), engine->rootContext());
186 delete engine; engine = 0;
188 QCOMPARE(ctxt->parentContext(), (QDeclarativeContext *)0);
189 QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0);
190 QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0);
191 QCOMPARE(ctxt5->parentContext(), (QDeclarativeContext *)0);
192 QCOMPARE(ctxt6->parentContext(), (QDeclarativeContext *)0);
193 QCOMPARE(ctxt7->parentContext(), (QDeclarativeContext *)0);
203 class TestObject : public QObject
206 Q_PROPERTY(int a READ a NOTIFY aChanged)
207 Q_PROPERTY(int b READ b NOTIFY bChanged)
208 Q_PROPERTY(int c READ c NOTIFY cChanged)
211 TestObject() : _a(10), _b(10), _c(10) {}
213 int a() const { return _a; }
214 void setA(int a) { _a = a; emit aChanged(); }
216 int b() const { return _b; }
217 void setB(int b) { _b = b; emit bChanged(); }
219 int c() const { return _c; }
220 void setC(int c) { _c = c; emit cChanged(); }
233 #define TEST_CONTEXT_PROPERTY(ctxt, name, value) \
235 QDeclarativeComponent component(&engine); \
236 component.setData("import QtQuick 1.0; QtObject { property variant test: " #name " }", QUrl()); \
238 QObject *obj = component.create(ctxt); \
240 QCOMPARE(obj->property("test"), value); \
245 void tst_qdeclarativecontext::setContextProperty()
247 QDeclarativeContext ctxt(&engine);
248 QDeclarativeContext ctxt2(&ctxt);
255 // Static context properties
256 ctxt.setContextProperty("a", QVariant(10));
257 ctxt.setContextProperty("b", QVariant(9));
258 ctxt2.setContextProperty("d", &obj2);
259 ctxt2.setContextProperty("b", QVariant(19));
260 ctxt2.setContextProperty("c", QVariant(QString("Hello World!")));
261 ctxt.setContextProperty("d", &obj1);
262 ctxt.setContextProperty("e", &obj1);
264 TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(10));
265 TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(19));
266 TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hello World!")));
267 TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(-19));
268 TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(3345));
270 ctxt.setContextProperty("a", QVariant(13));
271 ctxt.setContextProperty("b", QVariant(4));
272 ctxt2.setContextProperty("b", QVariant(8));
273 ctxt2.setContextProperty("c", QVariant(QString("Hi World!")));
274 ctxt2.setContextProperty("d", &obj1);
277 TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(13));
278 TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(8));
279 TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hi World!")));
280 TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(12));
281 TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(12));
283 // Changes in context properties
285 QDeclarativeComponent component(&engine);
286 component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
288 QObject *obj = component.create(&ctxt2);
290 QCOMPARE(obj->property("test"), QVariant(13));
291 ctxt.setContextProperty("a", QVariant(19));
292 QCOMPARE(obj->property("test"), QVariant(19));
297 QDeclarativeComponent component(&engine);
298 component.setData("import QtQuick 1.0; QtObject { property variant test: b }", QUrl());
300 QObject *obj = component.create(&ctxt2);
302 QCOMPARE(obj->property("test"), QVariant(8));
303 ctxt.setContextProperty("b", QVariant(5));
304 QCOMPARE(obj->property("test"), QVariant(8));
305 ctxt2.setContextProperty("b", QVariant(1912));
306 QCOMPARE(obj->property("test"), QVariant(1912));
311 QDeclarativeComponent component(&engine);
312 component.setData("import QtQuick 1.0; QtObject { property variant test: e.a }", QUrl());
314 QObject *obj = component.create(&ctxt2);
316 QCOMPARE(obj->property("test"), QVariant(12));
318 QCOMPARE(obj->property("test"), QVariant(13));
323 // New context properties
325 QDeclarativeComponent component(&engine);
326 component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
328 QObject *obj = component.create(&ctxt2);
330 QCOMPARE(obj->property("test"), QVariant(19));
331 ctxt2.setContextProperty("a", QVariant(1945));
332 QCOMPARE(obj->property("test"), QVariant(1945));
337 // Setting an object-variant context property
339 QDeclarativeComponent component(&engine);
340 component.setData("import QtQuick 1.0; QtObject { id: root; property int a: 10; property int test: ctxtProp.a; property variant obj: root; }", QUrl());
342 QDeclarativeContext ctxt(engine.rootContext());
343 ctxt.setContextProperty("ctxtProp", QVariant());
345 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
346 QObject *obj = component.create(&ctxt);
348 QVariant v = obj->property("obj");
350 ctxt.setContextProperty("ctxtProp", v);
352 QCOMPARE(obj->property("test"), QVariant(10));
358 void tst_qdeclarativecontext::setContextObject()
360 QDeclarativeContext ctxt(&engine);
368 ctxt.setContextObject(&to);
369 ctxt.setContextProperty("c", QVariant(9));
371 // Static context properties
372 TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(2));
373 TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(192));
374 TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(9));
379 ctxt.setContextProperty("c", QVariant(3));
381 TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(12));
382 TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(100));
383 TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(3));
385 // Changes in context properties
387 QDeclarativeComponent component(&engine);
388 component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
390 QObject *obj = component.create(&ctxt);
392 QCOMPARE(obj->property("test"), QVariant(12));
394 QCOMPARE(obj->property("test"), QVariant(14));
400 void tst_qdeclarativecontext::destruction()
402 QDeclarativeContext *ctxt = new QDeclarativeContext(&engine);
405 QDeclarativeEngine::setContextForObject(&obj, ctxt);
406 QDeclarativeExpression expr(ctxt, 0, "a");
408 QCOMPARE(ctxt, QDeclarativeEngine::contextForObject(&obj));
409 QCOMPARE(ctxt, expr.context());
411 delete ctxt; ctxt = 0;
413 QCOMPARE(ctxt, QDeclarativeEngine::contextForObject(&obj));
414 QCOMPARE(ctxt, expr.context());
417 void tst_qdeclarativecontext::idAsContextProperty()
419 QDeclarativeComponent component(&engine);
420 component.setData("import QtQuick 1.0; QtObject { property variant a; a: QtObject { id: myObject } }", QUrl());
422 QObject *obj = component.create();
425 QVariant a = obj->property("a");
426 QVERIFY(a.userType() == QMetaType::QObjectStar);
428 QVariant ctxt = qmlContext(obj)->contextProperty("myObject");
429 QVERIFY(ctxt.userType() == QMetaType::QObjectStar);
436 // Internal contexts should be read-only
437 void tst_qdeclarativecontext::readOnlyContexts()
439 QDeclarativeComponent component(&engine);
440 component.setData("import QtQuick 1.0; QtObject { id: me }", QUrl());
442 QObject *obj = component.create();
445 QDeclarativeContext *context = qmlContext(obj);
448 QVERIFY(qvariant_cast<QObject*>(context->contextProperty("me")) == obj);
449 QVERIFY(context->contextObject() == obj);
451 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set property on internal context.");
452 context->setContextProperty("hello", 12);
453 QVERIFY(context->contextProperty("hello") == QVariant());
455 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set property on internal context.");
456 context->setContextProperty("hello", obj);
457 QVERIFY(context->contextProperty("hello") == QVariant());
459 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set context object for internal context.");
460 context->setContextObject(0);
461 QVERIFY(context->contextObject() == obj);
466 QTEST_MAIN(tst_qdeclarativecontext)
468 #include "tst_qdeclarativecontext.moc"