From a8b637e9b70bb420690523cd3f77f139813deec8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 26 Sep 2012 10:49:56 +0200 Subject: Add QtQuick1 WebKit integration (from QtWebKit module) This adds the QML1 QDeclarativeWebView integration to the default build (it was added a while ago) as well as the unit tests. Change-Id: I7324f5a3b00716d4b300e8c11d9ea3b8b9577da3 Reviewed-by: Pierre Rossi --- .../tst_qdeclarativewebview.cpp | 543 +++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp (limited to 'tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp') diff --git a/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp b/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp new file mode 100644 index 00000000..51bf3859 --- /dev/null +++ b/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp @@ -0,0 +1,543 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../shared/debugutil_p.h" +#include "qdeclarativewebview_p.h" + +class tst_QDeclarativeWebView : public QObject { + Q_OBJECT + +public: + tst_QDeclarativeWebView(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void basicProperties(); + void elementAreaAt(); + void historyNav(); + void javaScript(); + void loadError(); + void multipleWindows(); + void newWindowComponent(); + void newWindowParent(); + void preferredWidthTest(); + void preferredHeightTest(); + void preferredWidthDefaultTest(); + void preferredHeightDefaultTest(); + void pressGrabTime(); + void renderingEnabled(); + void setHtml(); + void settings(); + void backgroundColor(); + +private: + void checkNoErrors(const QDeclarativeComponent&); + QString tmpDir() const + { + static QString tmpd = QDir::tempPath() + "/tst_qdeclarativewebview-" + + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss")); + return tmpd; + } +}; + +tst_QDeclarativeWebView::tst_QDeclarativeWebView() +{ +} + +static QString strippedHtml(QString html) +{ + html.replace(QRegExp("\\s+"), ""); + return html; +} + +static QString fileContents(const QString& filename) +{ + QFile file(filename); + file.open(QIODevice::ReadOnly); + return QString::fromUtf8(file.readAll()); +} + +static void removeRecursive(const QString& dirname) +{ + QDir dir(dirname); + QFileInfoList entries(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)); + for (int i = 0; i < entries.count(); ++i) + if (entries[i].isDir()) + removeRecursive(entries[i].filePath()); + else + dir.remove(entries[i].fileName()); + QDir().rmdir(dirname); +} + +void tst_QDeclarativeWebView::initTestCase() +{ + QWebSettings::enablePersistentStorage(tmpDir()); +} + +void tst_QDeclarativeWebView::cleanupTestCase() +{ + removeRecursive(tmpDir()); +} + +void tst_QDeclarativeWebView::basicProperties() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml")); + checkNoErrors(component); + + QObject* wv = component.create(); + QVERIFY(wv); + QDeclarativeDebugTest::waitForSignal(wv, SIGNAL(iconChanged())); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("title").toString(), QLatin1String("Basic")); + QTRY_COMPARE(qvariant_cast(wv->property("icon")).width(), 48); + QVERIFY(!qvariant_cast(wv->property("icon")).isNull()); + QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here")); + QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString())); + QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue); + QCOMPARE(wv->property("preferredWidth").toInt(), 0); + QEXPECT_FAIL("", "TODO: get preferred height from QGraphicsWebView result", Continue); + QCOMPARE(wv->property("preferredHeight").toInt(), 0); + QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html")); + QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready)); + + QAction* reloadAction = wv->property("reload").value(); + QVERIFY(reloadAction); + QVERIFY(reloadAction->isEnabled()); + QAction* backAction = wv->property("back").value(); + QVERIFY(backAction); + QVERIFY(!backAction->isEnabled()); + QAction* forwardAction = wv->property("forward").value(); + QVERIFY(forwardAction); + QVERIFY(!forwardAction->isEnabled()); + QAction* stopAction = wv->property("stop").value(); + QVERIFY(stopAction); + QVERIFY(!stopAction->isEnabled()); + + wv->setProperty("pixelCacheSize", 0); // mainly testing that it doesn't crash or anything! + QCOMPARE(wv->property("pixelCacheSize").toInt(), 0); + reloadAction->trigger(); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); +} + +void tst_QDeclarativeWebView::elementAreaAt() +{ + QSKIP("This test should be changed to test 'heuristicZoom' instead."); + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/elements.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + // FIXME: Tests disabled since elementAreaAt isn't exported. + // Areas from elements.html. +// const QRect areaA(1, 1, 75, 54); +// const QRect areaB(78, 3, 110, 50); +// const QRect wholeView(0, 0, 310, 100); +// const QRect areaBC(76, 1, 223, 54); + +// QCOMPARE(wv->elementAreaAt(40, 30, 100, 100), areaA); +// QCOMPARE(wv->elementAreaAt(130, 30, 200, 100), areaB); +// QCOMPARE(wv->elementAreaAt(40, 30, 400, 400), wholeView); +// QCOMPARE(wv->elementAreaAt(130, 30, 280, 280), areaBC); +// QCOMPARE(wv->elementAreaAt(130, 30, 400, 400), wholeView); +} + +void tst_QDeclarativeWebView::historyNav() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml")); + checkNoErrors(component); + + QObject* wv = component.create(); + QVERIFY(wv); + QDeclarativeDebugTest::waitForSignal(wv, SIGNAL(iconChanged())); + + QAction* reloadAction = wv->property("reload").value(); + QVERIFY(reloadAction); + QAction* backAction = wv->property("back").value(); + QVERIFY(backAction); + QAction* forwardAction = wv->property("forward").value(); + QVERIFY(forwardAction); + QAction* stopAction = wv->property("stop").value(); + QVERIFY(stopAction); + + for (int i = 1; i <= 2; ++i) { + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("title").toString(), QLatin1String("Basic")); + QTRY_COMPARE(qvariant_cast(wv->property("icon")).width(), 48); + QCOMPARE(wv->property("statusText").toString(), QLatin1String("status here")); + QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString())); + QEXPECT_FAIL("", "TODO: get preferred width from QGraphicsWebView result", Continue); + QCOMPARE(wv->property("preferredWidth").toDouble(), 0.0); + QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html")); + QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready)); + QVERIFY(reloadAction->isEnabled()); + QVERIFY(!backAction->isEnabled()); + QVERIFY(!forwardAction->isEnabled()); + QVERIFY(!stopAction->isEnabled()); + reloadAction->trigger(); + QDeclarativeDebugTest::waitForSignal(wv, SIGNAL(iconChanged())); + } + + wv->setProperty("url", QUrl("qrc:///resources/forward.html")); + QDeclarativeDebugTest::waitForSignal(wv, SIGNAL(iconChanged())); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("title").toString(), QLatin1String("Forward")); + QTRY_COMPARE(qvariant_cast(wv->property("icon")).width(), 32); + QCOMPARE(strippedHtml(fileContents(":/resources/forward.html")), strippedHtml(wv->property("html").toString())); + QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/forward.html")); + QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready)); + QCOMPARE(wv->property("statusText").toString(), QString()); + + QVERIFY(reloadAction->isEnabled()); + QVERIFY(backAction->isEnabled()); + QVERIFY(!forwardAction->isEnabled()); + QVERIFY(!stopAction->isEnabled()); + + backAction->trigger(); + QDeclarativeDebugTest::waitForSignal(wv, SIGNAL(loadFinished())); + + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("title").toString(), QLatin1String("Basic")); + QCOMPARE(strippedHtml(fileContents(":/resources/basic.html")), strippedHtml(wv->property("html").toString())); + QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/basic.html")); + QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Ready)); + + QVERIFY(reloadAction->isEnabled()); + QVERIFY(!backAction->isEnabled()); + QVERIFY(forwardAction->isEnabled()); + QVERIFY(!stopAction->isEnabled()); +} + +static inline QVariant callEvaluateJavaScript(QObject *object, const QString& snippet) +{ + QVariant result; + QMetaObject::invokeMethod(object, "evaluateJavaScript", Q_RETURN_ARG(QVariant, result), Q_ARG(QString, snippet)); + return result; +} + +void tst_QDeclarativeWebView::javaScript() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/javaScript.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + QCOMPARE(callEvaluateJavaScript(wv, "123").toInt(), 123); + QCOMPARE(callEvaluateJavaScript(wv, "window.status").toString(), QLatin1String("status here")); + QCOMPARE(callEvaluateJavaScript(wv, "window.myjsname.qmlprop").toString(), QLatin1String("qmlvalue")); +} + +void tst_QDeclarativeWebView::loadError() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/loadError.qml")); + checkNoErrors(component); + + QObject* wv = component.create(); + QVERIFY(wv); + QAction* reloadAction = wv->property("reload").value(); + QVERIFY(reloadAction); + + for (int i = 1; i <= 2; ++i) { + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("title").toString(), QString()); + QCOMPARE(wv->property("statusText").toString(), QString()); // HTML 'status bar' text, not error message + QCOMPARE(wv->property("url").toUrl(), QUrl("qrc:///resources/does-not-exist.html")); // Unlike QWebPage, which loses url + QCOMPARE(wv->property("status").toInt(), int(QDeclarativeWebView::Error)); + reloadAction->trigger(); + } +} + +void tst_QDeclarativeWebView::multipleWindows() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/newwindows.qml")); + checkNoErrors(component); + + QDeclarativeItem* rootItem = qobject_cast(component.create()); + QVERIFY(rootItem); + + QTRY_COMPARE(rootItem->property("pagesOpened").toInt(), 4); + + QDeclarativeProperty prop(rootItem, "firstPageOpened"); + QObject* firstPageOpened = qvariant_cast(prop.read()); + QVERIFY(firstPageOpened); + + QDeclarativeProperty xProp(firstPageOpened, "x"); + QTRY_COMPARE(xProp.read().toReal(), qreal(150.0)); +} + +void tst_QDeclarativeWebView::newWindowComponent() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml")); + checkNoErrors(component); + QDeclarativeItem* rootItem = qobject_cast(component.create()); + QVERIFY(rootItem); + QObject* wv = rootItem->findChild("webView"); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + QDeclarativeComponent substituteComponent(&engine); + substituteComponent.setData("import QtQuick 1.0; WebView { objectName: 'newWebView'; url: 'basic.html'; }", QUrl::fromLocalFile("")); + QSignalSpy newWindowComponentSpy(wv, SIGNAL(newWindowComponentChanged())); + + wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); + QCOMPARE(wv->property("newWindowComponent"), QVariant::fromValue(&substituteComponent)); + QCOMPARE(newWindowComponentSpy.count(), 1); + + wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); + QCOMPARE(newWindowComponentSpy.count(), 1); + + wv->setProperty("newWindowComponent", QVariant::fromValue((QDeclarativeComponent*)0)); + QCOMPARE(newWindowComponentSpy.count(), 2); +} + +void tst_QDeclarativeWebView::newWindowParent() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml")); + checkNoErrors(component); + QDeclarativeItem* rootItem = qobject_cast(component.create()); + QVERIFY(rootItem); + QObject* wv = rootItem->findChild("webView"); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + QDeclarativeItem* oldWindowParent = rootItem->findChild("oldWindowParent"); + QCOMPARE(qvariant_cast(wv->property("newWindowParent")), oldWindowParent); + QSignalSpy newWindowParentSpy(wv, SIGNAL(newWindowParentChanged())); + + QDeclarativeItem* newWindowParent = rootItem->findChild("newWindowParent"); + wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); + QVERIFY(newWindowParent); + QVERIFY(oldWindowParent); + QCOMPARE(oldWindowParent->childItems().count(), 0); + QCOMPARE(wv->property("newWindowParent"), QVariant::fromValue(newWindowParent)); + QCOMPARE(newWindowParentSpy.count(), 1); + + wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); + QCOMPARE(newWindowParentSpy.count(), 1); + + wv->setProperty("newWindowParent", QVariant::fromValue((QDeclarativeItem*)0)); + QCOMPARE(newWindowParentSpy.count(), 2); +} + +void tst_QDeclarativeWebView::preferredWidthTest() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html")); + QCOMPARE(wv->property("prefWidth").toInt(), 600); +} + +void tst_QDeclarativeWebView::preferredHeightTest() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtest.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html")); + QCOMPARE(wv->property("prefHeight").toInt(), 500); +} + +void tst_QDeclarativeWebView::preferredWidthDefaultTest() +{ + QGraphicsWebView view; + view.load(QUrl("qrc:///resources/sample.html")); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html")); + QCOMPARE(wv->property("prefWidth").toDouble(), view.preferredWidth()); +} + +void tst_QDeclarativeWebView::preferredHeightDefaultTest() +{ + QGraphicsWebView view; + view.load(QUrl("qrc:///resources/sample.html")); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewtestdefault.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + wv->setProperty("testUrl", QUrl("qrc:///resources/sample.html")); + QCOMPARE(wv->property("prefHeight").toDouble(), view.preferredHeight()); +} + +void tst_QDeclarativeWebView::pressGrabTime() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml")); + checkNoErrors(component); + QDeclarativeItem* rootItem = qobject_cast(component.create()); + QVERIFY(rootItem); + QObject* wv = rootItem->findChild("webView"); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + QCOMPARE(wv->property("pressGrabTime").toInt(), 200); + QSignalSpy pressGrabTimeSpy(wv, SIGNAL(pressGrabTimeChanged())); + + wv->setProperty("pressGrabTime", 100); + QCOMPARE(wv->property("pressGrabTime").toInt(), 100); + QCOMPARE(pressGrabTimeSpy.count(), 1); + + wv->setProperty("pressGrabTime", 100); + QCOMPARE(pressGrabTimeSpy.count(), 1); + + wv->setProperty("pressGrabTime", 0); + QCOMPARE(pressGrabTimeSpy.count(), 2); +} + +void tst_QDeclarativeWebView::renderingEnabled() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/propertychanges.qml")); + checkNoErrors(component); + QDeclarativeItem* rootItem = qobject_cast(component.create()); + QVERIFY(rootItem); + QObject* wv = rootItem->findChild("webView"); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + QVERIFY(wv->property("renderingEnabled").toBool()); + QSignalSpy renderingEnabledSpy(wv, SIGNAL(renderingEnabledChanged())); + + wv->setProperty("renderingEnabled", false); + QVERIFY(!wv->property("renderingEnabled").toBool()); + QCOMPARE(renderingEnabledSpy.count(), 1); + + wv->setProperty("renderingEnabled", false); + QCOMPARE(renderingEnabledSpy.count(), 1); + + wv->setProperty("renderingEnabled", true); + QCOMPARE(renderingEnabledSpy.count(), 2); +} + +void tst_QDeclarativeWebView::setHtml() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/sethtml.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + QCOMPARE(wv->property("html").toString(), QLatin1String("

This is a string set on the WebView

")); + + QSignalSpy spy(wv, SIGNAL(htmlChanged())); + wv->setProperty("html", QLatin1String("Basic

text

")); + QCOMPARE(spy.count(), 1); +} + +void tst_QDeclarativeWebView::settings() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/basic.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); + + QObject* s = QDeclarativeProperty(wv, "settings").object(); + QVERIFY(s); + + QStringList settingsList; + settingsList << QString::fromLatin1("autoLoadImages") + << QString::fromLatin1("developerExtrasEnabled") + << QString::fromLatin1("javaEnabled") + << QString::fromLatin1("javascriptCanAccessClipboard") + << QString::fromLatin1("javascriptCanOpenWindows") + << QString::fromLatin1("javascriptEnabled") + << QString::fromLatin1("linksIncludedInFocusChain") + << QString::fromLatin1("localContentCanAccessRemoteUrls") + << QString::fromLatin1("localStorageDatabaseEnabled") + << QString::fromLatin1("offlineStorageDatabaseEnabled") + << QString::fromLatin1("offlineWebApplicationCacheEnabled") + << QString::fromLatin1("pluginsEnabled") + << QString::fromLatin1("printElementBackgrounds") + << QString::fromLatin1("privateBrowsingEnabled") + << QString::fromLatin1("zoomTextOnly"); + + // Merely tests that setting gets stored (in QWebSettings), behavioural tests are in WebKit. + for (int b = 0; b <= 1; b++) { + bool value = !!b; + foreach (const QString& name, settingsList) + s->setProperty(name.toLatin1().data(), value); + for (int i = 0; i < 2; i++) { + foreach (const QString& name, settingsList) + QCOMPARE(s->property(name.toLatin1().data()).toBool(), value); + } + } +} + +void tst_QDeclarativeWebView::backgroundColor() +{ + // We test here the rendering of the background. + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl("qrc:///resources/webviewbackgroundcolor.qml")); + checkNoErrors(component); + QObject* wv = component.create(); + QVERIFY(wv); + QCOMPARE(wv->property("backgroundColor").value(), QColor(Qt::red)); + QDeclarativeView view; + view.setSource(QUrl("qrc:///resources/webviewbackgroundcolor.qml")); + view.show(); + QTest::qWaitForWindowExposed(&view); + QPixmap result(view.width(), view.height()); + QPainter painter(&result); + view.render(&painter); + QPixmap reference(view.width(), view.height()); + reference.fill(Qt::red); + QCOMPARE(reference, result); + + // We test the emission of the backgroundColorChanged signal. + QSignalSpy spyColorChanged(wv, SIGNAL(backgroundColorChanged())); + wv->setProperty("backgroundColor", QColor(Qt::red)); + QCOMPARE(spyColorChanged.count(), 0); + wv->setProperty("backgroundColor", QColor(Qt::green)); + QCOMPARE(spyColorChanged.count(), 1); +} + +void tst_QDeclarativeWebView::checkNoErrors(const QDeclarativeComponent& component) +{ + // Wait until the component is ready + QTRY_VERIFY(component.isReady() || component.isError()); + if (component.isError()) { + QList errors = component.errors(); + for (int ii = 0; ii < errors.count(); ++ii) { + const QDeclarativeError &error = errors.at(ii); + QByteArray errorStr = QByteArray::number(error.line()) + ":" + + QByteArray::number(error.column()) + ":" + + error.description().toUtf8(); + qWarning() << errorStr; + } + } + QVERIFY(!component.isError()); +} + +QTEST_MAIN(tst_QDeclarativeWebView) +#include "tst_qdeclarativewebview.moc" -- cgit v1.2.3