5 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
6 #include <QtQuick1/QDeclarativeItem>
7 #include <QtQuick1/QDeclarativeView>
9 #include <QDeclarativeItem>
10 #include <QDeclarativeView>
12 #include <QDeclarativeComponent>
13 #include <QDeclarativeEngine>
14 #include <QDeclarativeProperty>
16 #include <QGraphicsWebView>
20 #include "qdeclarativewebview_p.h"
22 class tst_QDeclarativeWebView : public QObject {
26 tst_QDeclarativeWebView();
30 void cleanupTestCase();
32 void basicProperties();
37 void multipleWindows();
38 void newWindowComponent();
39 void newWindowParent();
40 void preferredWidthTest();
41 void preferredHeightTest();
42 void preferredWidthDefaultTest();
43 void preferredHeightDefaultTest();
45 void renderingEnabled();
48 #if QT_VERSION >= 0x040704
49 void backgroundColor();
53 void checkNoErrors(const QDeclarativeComponent&);
54 QString tmpDir() const
56 static QString tmpd = QDir::tempPath() + "/tst_qdeclarativewebview-"
57 + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss"));
62 tst_QDeclarativeWebView::tst_QDeclarativeWebView()
64 Q_UNUSED(waitForSignal)
67 static QString strippedHtml(QString html)
69 html.replace(QRegExp("\\s+"), "");
73 static QString fileContents(const QString& filename)
76 file.open(QIODevice::ReadOnly);
77 return QString::fromUtf8(file.readAll());
80 static void removeRecursive(const QString& dirname)
83 QFileInfoList entries(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
84 for (int i = 0; i < entries.count(); ++i)
85 if (entries[i].isDir())
86 removeRecursive(entries[i].filePath());
88 dir.remove(entries[i].fileName());
89 QDir().rmdir(dirname);
92 void tst_QDeclarativeWebView::initTestCase()
94 QWebSettings::setIconDatabasePath(tmpDir());
95 QWebSettings::enablePersistentStorage(tmpDir());
98 void tst_QDeclarativeWebView::cleanupTestCase()
100 removeRecursive(tmpDir());
103 void tst_QDeclarativeWebView::basicProperties()
105 QDeclarativeEngine engine;
106 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
107 checkNoErrors(component);
108 QWebSettings::enablePersistentStorage(tmpDir());
110 QObject* wv = component.create();
112 waitForSignal(wv, SIGNAL(iconChanged()));
113 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
114 QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
115 QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48);
116 QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap(":/resources/basic.png"));
117 QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here"));
118 QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
119 QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue);
120 QCOMPARE(wv->property("preferredWidth").toInt(), 0);
121 QEXPECT_FAIL("", "TODO: get preferred height from QGraphicsWebView result", Continue);
122 QCOMPARE(wv->property("preferredHeight").toInt(), 0);
123 QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
124 QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
126 QAction* reloadAction = wv->property("reload").value<QAction*>();
127 QVERIFY(reloadAction);
128 QVERIFY(reloadAction->isEnabled());
129 QAction* backAction = wv->property("back").value<QAction*>();
131 QVERIFY(!backAction->isEnabled());
132 QAction* forwardAction = wv->property("forward").value<QAction*>();
133 QVERIFY(forwardAction);
134 QVERIFY(!forwardAction->isEnabled());
135 QAction* stopAction = wv->property("stop").value<QAction*>();
137 QVERIFY(!stopAction->isEnabled());
139 wv->setProperty("pixelCacheSize", 0); // mainly testing that it doesn't crash or anything!
140 QCOMPARE(wv->property("pixelCacheSize").toInt(), 0);
141 reloadAction->trigger();
142 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
145 void tst_QDeclarativeWebView::elementAreaAt()
147 QSKIP("This test should be changed to test 'heuristicZoom' instead.", SkipAll);
148 QDeclarativeEngine engine;
149 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/elements.qml"));
150 checkNoErrors(component);
151 QObject* wv = component.create();
153 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
155 // FIXME: Tests disabled since elementAreaAt isn't exported.
156 // Areas from elements.html.
157 // const QRect areaA(1, 1, 75, 54);
158 // const QRect areaB(78, 3, 110, 50);
159 // const QRect wholeView(0, 0, 310, 100);
160 // const QRect areaBC(76, 1, 223, 54);
162 // QCOMPARE(wv->elementAreaAt(40, 30, 100, 100), areaA);
163 // QCOMPARE(wv->elementAreaAt(130, 30, 200, 100), areaB);
164 // QCOMPARE(wv->elementAreaAt(40, 30, 400, 400), wholeView);
165 // QCOMPARE(wv->elementAreaAt(130, 30, 280, 280), areaBC);
166 // QCOMPARE(wv->elementAreaAt(130, 30, 400, 400), wholeView);
169 void tst_QDeclarativeWebView::historyNav()
171 QDeclarativeEngine engine;
172 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
173 checkNoErrors(component);
174 QWebSettings::enablePersistentStorage(tmpDir());
176 QObject* wv = component.create();
178 waitForSignal(wv, SIGNAL(iconChanged()));
180 QAction* reloadAction = wv->property("reload").value<QAction*>();
181 QVERIFY(reloadAction);
182 QAction* backAction = wv->property("back").value<QAction*>();
184 QAction* forwardAction = wv->property("forward").value<QAction*>();
185 QVERIFY(forwardAction);
186 QAction* stopAction = wv->property("stop").value<QAction*>();
189 for (int i = 1; i <= 2; ++i) {
190 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
191 QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
192 QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48);
193 QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap(":/resources/basic.png"));
194 QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here"));
195 QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
196 QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue);
197 QCOMPARE(wv->property("preferredWidth").toDouble(), 0.0);
198 QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
199 QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
200 QVERIFY(reloadAction->isEnabled());
201 QVERIFY(!backAction->isEnabled());
202 QVERIFY(!forwardAction->isEnabled());
203 QVERIFY(!stopAction->isEnabled());
204 reloadAction->trigger();
205 waitForSignal(wv, SIGNAL(iconChanged()));
208 wv->setProperty("url", QUrl("qrc:///resources/forward.html"));
209 waitForSignal(wv, SIGNAL(iconChanged()));
210 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
211 QCOMPARE(wv->property("title").toString(), QLatin1String("Forward"));
212 QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 32);
213 QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")), QPixmap(":/resources/forward.png"));
214 QCOMPARE(strippedHtml(fileContents(":/resources/forward.html")), strippedHtml(wv->property("html").toString()));
215 QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/forward.html"));
216 QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
217 QCOMPARE(wv->property("statusText").toString(), QString());
219 QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=61042", Continue);
220 QVERIFY(reloadAction->isEnabled());
221 QVERIFY(backAction->isEnabled());
222 QVERIFY(!forwardAction->isEnabled());
223 QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=61042", Continue);
224 QVERIFY(!stopAction->isEnabled());
226 backAction->trigger();
227 waitForSignal(wv, SIGNAL(loadFinished()));
229 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
230 QCOMPARE(wv->property("title").toString(), QLatin1String("Basic"));
231 QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString()));
232 QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html"));
233 QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready));
235 QVERIFY(reloadAction->isEnabled());
236 QVERIFY(!backAction->isEnabled());
237 QVERIFY(forwardAction->isEnabled());
238 QVERIFY(!stopAction->isEnabled());
241 static inline QVariant callEvaluateJavaScript(QObject *object, const QString& snippet)
244 QMetaObject::invokeMethod(object, "evaluateJavaScript", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, snippet));
248 void tst_QDeclarativeWebView::javaScript()
250 QDeclarativeEngine engine;
251 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/javaScript.qml"));
252 checkNoErrors(component);
253 QObject* wv = component.create();
255 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
257 QCOMPARE(callEvaluateJavaScript(wv, "123").toInt(), 123);
258 QCOMPARE(callEvaluateJavaScript(wv, "window.status").toString(), QLatin1String("status here"));
259 QCOMPARE(callEvaluateJavaScript(wv, "window.myjsname.qmlprop").toString(), QLatin1String("qmlvalue"));
262 void tst_QDeclarativeWebView::loadError()
264 QDeclarativeEngine engine;
265 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/loadError.qml"));
266 checkNoErrors(component);
267 QWebSettings::enablePersistentStorage(tmpDir());
269 QObject* wv = component.create();
271 QAction* reloadAction = wv->property("reload").value<QAction*>();
272 QVERIFY(reloadAction);
274 for (int i = 1; i <= 2; ++i) {
275 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
276 QCOMPARE(wv->property("title").toString(), QString());
277 QCOMPARE(wv->property("statusText").toString(), QString()); // HTML 'status bar' text, not error message
278 QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/does-not-exist.html")); // Unlike QWebPage, which loses url
279 QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Error));
280 reloadAction->trigger();
284 void tst_QDeclarativeWebView::multipleWindows()
286 QDeclarativeEngine engine;
287 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/newwindows.qml"));
288 checkNoErrors(component);
290 QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
293 QTRY_COMPARE(rootItem->property("pagesOpened").toInt(), 4);
295 QDeclarativeProperty prop(rootItem, "firstPageOpened");
296 QObject* firstPageOpened = qvariant_cast<QObject*>(prop.read());
297 QVERIFY(firstPageOpened);
299 QDeclarativeProperty xProp(firstPageOpened, "x");
300 QTRY_COMPARE(xProp.read().toReal(), qreal(150.0));
303 void tst_QDeclarativeWebView::newWindowComponent()
305 QDeclarativeEngine engine;
306 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
307 checkNoErrors(component);
308 QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
310 QObject* wv = rootItem->findChild<QObject*>("webView");
312 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
314 QDeclarativeComponent substituteComponent(&engine);
315 substituteComponent.setData("import QtQuick 1.0; WebView { objectName: 'newWebView'; url: 'basic.html'; }", QUrl::fromLocalFile(""));
316 QSignalSpy newWindowComponentSpy(wv, SIGNAL(newWindowComponentChanged()));
318 wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent));
319 QCOMPARE(wv->property("newWindowComponent"), QVariant::fromValue(&substituteComponent));
320 QCOMPARE(newWindowComponentSpy.count(), 1);
322 wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent));
323 QCOMPARE(newWindowComponentSpy.count(), 1);
325 wv->setProperty("newWindowComponent", QVariant::fromValue((QDeclarativeComponent*)0));
326 QCOMPARE(newWindowComponentSpy.count(), 2);
329 void tst_QDeclarativeWebView::newWindowParent()
331 QDeclarativeEngine engine;
332 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
333 checkNoErrors(component);
334 QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
336 QObject* wv = rootItem->findChild<QObject*>("webView");
338 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
340 QDeclarativeItem* oldWindowParent = rootItem->findChild<QDeclarativeItem*>("oldWindowParent");
341 QCOMPARE(qvariant_cast<QDeclarativeItem*>(wv->property("newWindowParent")), oldWindowParent);
342 QSignalSpy newWindowParentSpy(wv, SIGNAL(newWindowParentChanged()));
344 QDeclarativeItem* newWindowParent = rootItem->findChild<QDeclarativeItem*>("newWindowParent");
345 wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent));
346 QVERIFY(newWindowParent);
347 QVERIFY(oldWindowParent);
348 QCOMPARE(oldWindowParent->childItems().count(), 0);
349 QCOMPARE(wv->property("newWindowParent"), QVariant::fromValue(newWindowParent));
350 QCOMPARE(newWindowParentSpy.count(), 1);
352 wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent));
353 QCOMPARE(newWindowParentSpy.count(), 1);
355 wv->setProperty("newWindowParent", QVariant::fromValue((QDeclarativeItem*)0));
356 QCOMPARE(newWindowParentSpy.count(), 2);
359 void tst_QDeclarativeWebView::preferredWidthTest()
361 QDeclarativeEngine engine;
362 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml"));
363 checkNoErrors(component);
364 QObject* wv = component.create();
366 wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
367 QCOMPARE(wv->property("prefWidth").toInt(), 600);
370 void tst_QDeclarativeWebView::preferredHeightTest()
372 QDeclarativeEngine engine;
373 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml"));
374 checkNoErrors(component);
375 QObject* wv = component.create();
377 wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
378 QCOMPARE(wv->property("prefHeight").toInt(), 500);
381 void tst_QDeclarativeWebView::preferredWidthDefaultTest()
383 QGraphicsWebView view;
384 view.load(QUrl("qrc:///resources/sample.html"));
386 QDeclarativeEngine engine;
387 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml"));
388 checkNoErrors(component);
389 QObject* wv = component.create();
391 wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
392 QCOMPARE(wv->property("prefWidth").toDouble(), view.preferredWidth());
395 void tst_QDeclarativeWebView::preferredHeightDefaultTest()
397 QGraphicsWebView view;
398 view.load(QUrl("qrc:///resources/sample.html"));
400 QDeclarativeEngine engine;
401 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml"));
402 checkNoErrors(component);
403 QObject* wv = component.create();
405 wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html"));
406 QCOMPARE(wv->property("prefHeight").toDouble(), view.preferredHeight());
409 void tst_QDeclarativeWebView::pressGrabTime()
411 QDeclarativeEngine engine;
412 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
413 checkNoErrors(component);
414 QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
416 QObject* wv = rootItem->findChild<QObject*>("webView");
418 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
419 QCOMPARE(wv->property("pressGrabTime").toInt(), 200);
420 QSignalSpy pressGrabTimeSpy(wv, SIGNAL(pressGrabTimeChanged()));
422 wv->setProperty("pressGrabTime", 100);
423 QCOMPARE(wv->property("pressGrabTime").toInt(), 100);
424 QCOMPARE(pressGrabTimeSpy.count(), 1);
426 wv->setProperty("pressGrabTime", 100);
427 QCOMPARE(pressGrabTimeSpy.count(), 1);
429 wv->setProperty("pressGrabTime", 0);
430 QCOMPARE(pressGrabTimeSpy.count(), 2);
433 void tst_QDeclarativeWebView::renderingEnabled()
435 QDeclarativeEngine engine;
436 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml"));
437 checkNoErrors(component);
438 QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(component.create());
440 QObject* wv = rootItem->findChild<QObject*>("webView");
442 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
444 QVERIFY(wv->property("renderingEnabled").toBool());
445 QSignalSpy renderingEnabledSpy(wv, SIGNAL(renderingEnabledChanged()));
447 wv->setProperty("renderingEnabled", false);
448 QVERIFY(!wv->property("renderingEnabled").toBool());
449 QCOMPARE(renderingEnabledSpy.count(), 1);
451 wv->setProperty("renderingEnabled", false);
452 QCOMPARE(renderingEnabledSpy.count(), 1);
454 wv->setProperty("renderingEnabled", true);
455 QCOMPARE(renderingEnabledSpy.count(), 2);
458 void tst_QDeclarativeWebView::setHtml()
460 QDeclarativeEngine engine;
461 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/sethtml.qml"));
462 checkNoErrors(component);
463 QObject* wv = component.create();
465 QCOMPARE(wv->property("html").toString(), QLatin1String("<html><head></head><body><p>This is a <b>string</b> set on the WebView</p></body></html>"));
467 QSignalSpy spy(wv, SIGNAL(htmlChanged()));
468 wv->setProperty("html", QLatin1String("<html><head><title>Basic</title></head><body><p>text</p></body></html>"));
469 QCOMPARE(spy.count(), 1);
472 void tst_QDeclarativeWebView::settings()
474 QDeclarativeEngine engine;
475 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml"));
476 checkNoErrors(component);
477 QObject* wv = component.create();
479 QTRY_COMPARE(wv->property("progress").toDouble(), 1.0);
481 QObject* s = QDeclarativeProperty(wv, "settings").object();
484 QStringList settingsList;
485 settingsList << QString::fromAscii("autoLoadImages")
486 << QString::fromAscii("developerExtrasEnabled")
487 << QString::fromAscii("javaEnabled")
488 << QString::fromAscii("javascriptCanAccessClipboard")
489 << QString::fromAscii("javascriptCanOpenWindows")
490 << QString::fromAscii("javascriptEnabled")
491 << QString::fromAscii("linksIncludedInFocusChain")
492 << QString::fromAscii("localContentCanAccessRemoteUrls")
493 << QString::fromAscii("localStorageDatabaseEnabled")
494 << QString::fromAscii("offlineStorageDatabaseEnabled")
495 << QString::fromAscii("offlineWebApplicationCacheEnabled")
496 << QString::fromAscii("pluginsEnabled")
497 << QString::fromAscii("printElementBackgrounds")
498 << QString::fromAscii("privateBrowsingEnabled")
499 << QString::fromAscii("zoomTextOnly");
501 // Merely tests that setting gets stored (in QWebSettings), behavioural tests are in WebKit.
502 for (int b = 0; b <= 1; b++) {
504 foreach (const QString& name, settingsList)
505 s->setProperty(name.toAscii().data(), value);
506 for (int i = 0; i < 2; i++) {
507 foreach (const QString& name, settingsList)
508 QCOMPARE(s->property(name.toAscii().data()).toBool(), value);
513 #if QT_VERSION >= 0x040704
514 void tst_QDeclarativeWebView::backgroundColor()
516 // We test here the rendering of the background.
517 QDeclarativeEngine engine;
518 QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewbackgroundcolor.qml"));
519 checkNoErrors(component);
520 QObject* wv = component.create();
522 QCOMPARE(wv->property("backgroundColor").value<QColor>(), QColor(Qt::red));
523 QDeclarativeView view;
524 view.setSource(QUrl("qrc:///resources/webviewbackgroundcolor.qml"));
526 QTest::qWaitForWindowShown(&view);
527 QPixmap result(view.width(), view.height());
528 QPainter painter(&result);
529 view.render(&painter);
530 QPixmap reference(view.width(), view.height());
531 reference.fill(Qt::red);
532 QCOMPARE(reference, result);
534 // We test the emission of the backgroundColorChanged signal.
535 QSignalSpy spyColorChanged(wv, SIGNAL(backgroundColorChanged()));
536 wv->setProperty("backgroundColor", Qt::red);
537 QCOMPARE(spyColorChanged.count(), 0);
538 wv->setProperty("backgroundColor", Qt::green);
539 QCOMPARE(spyColorChanged.count(), 1);
543 void tst_QDeclarativeWebView::checkNoErrors(const QDeclarativeComponent& component)
545 // Wait until the component is ready
546 QTRY_VERIFY(component.isReady() || component.isError());
547 if (component.isError()) {
548 QList<QDeclarativeError> errors = component.errors();
549 for (int ii = 0; ii < errors.count(); ++ii) {
550 const QDeclarativeError &error = errors.at(ii);
551 QByteArray errorStr = QByteArray::number(error.line()) + ":" +
552 QByteArray::number(error.column()) + ":" +
553 error.description().toUtf8();
554 qWarning() << errorStr;
557 QVERIFY(!component.isError());
560 QTEST_MAIN(tst_QDeclarativeWebView)
561 #include "tst_qdeclarativewebview.moc"