diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/qmltests/BLACKLIST | 3 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/data/tst_mouseMove.qml | 96 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/data/tst_viewSource.qml | 9 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/qmltests.pro | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquickwebengineview/qquickwebengineview.pro | 2 | ||||
-rw-r--r-- | tests/auto/quick/quick.pro | 2 | ||||
-rw-r--r-- | tests/auto/quick/tests.pri | 2 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp | 97 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/qwebenginepage.pro | 2 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/resources/bar.txt | 1 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/resources/foo.txt | 1 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/resources/path with spaces.txt | 1 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 160 | ||||
-rw-r--r-- | tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc | 3 | ||||
-rw-r--r-- | tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 54 | ||||
-rw-r--r-- | tests/auto/widgets/widgets.pro | 4 |
16 files changed, 397 insertions, 43 deletions
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST index 19d75dfb7..f449f4949 100644 --- a/tests/auto/quick/qmltests/BLACKLIST +++ b/tests/auto/quick/qmltests/BLACKLIST @@ -19,3 +19,6 @@ linux [WebEngineViewSingleFileUpload::test_acceptSingleFileSelection] * + +[WebViewFindText::test_findTextInterruptedByLoad] +* diff --git a/tests/auto/quick/qmltests/data/tst_mouseMove.qml b/tests/auto/quick/qmltests/data/tst_mouseMove.qml new file mode 100644 index 000000000..adb937139 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_mouseMove.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtWebEngine 1.4 + +Rectangle { + id: root + width: 200 + height: 200 + + Column { + anchors.fill: parent + Rectangle { + id: placeHolder + width: parent.width + height: 100 + color: "red" + } + + TestWebEngineView { + id: webEngineView + width: parent.width + height: 100 + + function getInnerText(element) { + var innerText; + runJavaScript("document.getElementById('" + element + "').innerText", function(result) { + innerText = result; + }); + testCase.tryVerify(function() { return innerText != undefined; }); + return innerText; + } + } + } + + TestCase { + id: testCase + name: "WebEngineViewMouseMove" + when: windowShown + + function test_mouseLeave() { + mouseMove(root, 0, 0); + webEngineView.loadHtml( + "<html>" + + "<head><script>" + + "function init() {" + + " var div = document.getElementById('testDiv');" + + " div.onmouseenter = function(e) { div.innerText = 'Mouse IN' };" + + " div.onmouseleave = function(e) { div.innerText = 'Mouse OUT' };" + + "}" + + "</script></head>" + + "<body onload='init()' style='margin: 0px; padding: 0px'>" + + " <div id='testDiv' style='width: 100%; height: 100%; background-color: green' />" + + "</body>" + + "</html>"); + verify(webEngineView.waitForLoadSucceeded()); + verify(!webEngineView.getInnerText("testDiv")); + + for (var i = 90; i < 110; ++i) + mouseMove(root, 50, i); + tryVerify(function() { return webEngineView.getInnerText("testDiv") == "Mouse IN" }); + + for (var i = 110; i > 90; --i) + mouseMove(root, 50, i); + tryVerify(function() { return webEngineView.getInnerText("testDiv") == "Mouse OUT" }); + } + } +} + diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml index 22c3947d3..576035ef2 100644 --- a/tests/auto/quick/qmltests/data/tst_viewSource.qml +++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml @@ -63,7 +63,7 @@ TestWebEngineView { name: "WebEngineViewSource" function init() { - webEngineView.url = Qt.resolvedUrl("about:blank"); + webEngineView.url = Qt.resolvedUrl("test1.html"); verify(webEngineView.waitForLoadSucceeded()); newViewRequestedSpy.clear(); @@ -103,8 +103,8 @@ TestWebEngineView { { tag: "view-source:about:blank", userInputUrl: "view-source:about:blank", loadSucceed: true, url: "view-source:about:blank", title: "view-source:about:blank" }, { tag: testLocalUrl, userInputUrl: testLocalUrl, loadSucceed: true, url: testLocalUrl, title: "test1.html" }, { tag: testLocalUrlWithoutScheme, userInputUrl: testLocalUrlWithoutScheme, loadSucceed: true, url: testLocalUrl, title: "test1.html" }, - { tag: "view-source:http://non.existent", userInputUrl: "view-source:http://non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "non.existent" }, - { tag: "view-source:non.existent", userInputUrl: "view-source:non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "non.existent" }, + { tag: "view-source:http://non.existent", userInputUrl: "view-source:http://non.existent", loadSucceed: false, url: "http://non.existent/", title: "non.existent" }, + { tag: "view-source:non.existent", userInputUrl: "view-source:non.existent", loadSucceed: false, url: "http://non.existent/", title: "non.existent" }, ]; } @@ -114,11 +114,10 @@ TestWebEngineView { if (row.loadSucceed) { verify(webEngineView.waitForLoadSucceeded()); - tryVerify(function() { return titleChangedSpy.count >= 1; }); } else { verify(webEngineView.waitForLoadFailed()); - tryVerify(function() { return titleChangedSpy.count >= 2; }); } + tryVerify(function() { return titleChangedSpy.count == 1; }); compare(webEngineView.url, row.url); tryCompare(webEngineView, "title", row.title); diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index 9530e115c..bb209a70c 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -62,6 +62,7 @@ OTHER_FILES += \ $$PWD/data/tst_loadRecursionCrash.qml \ $$PWD/data/tst_loadUrl.qml \ $$PWD/data/tst_mouseClick.qml \ + $$PWD/data/tst_mouseMove.qml \ $$PWD/data/tst_navigationHistory.qml \ $$PWD/data/tst_navigationRequested.qml \ $$PWD/data/tst_newViewRequest.qml \ @@ -100,7 +101,7 @@ OTHER_FILES += \ load(qt_build_paths) DEFINES += QUICK_TEST_SOURCE_DIR=\\\"$$re_escape($$PWD$${QMAKE_DIR_SEP}data)\\\" -!qtConfig(testsupport) { +!qtConfig(webengine-testsupport) { PLUGIN_EXTENSION = .so PLUGIN_PREFIX = lib osx: PLUGIN_PREFIX = .dylib diff --git a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro index 0f62ec21d..25bf44597 100644 --- a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro +++ b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro @@ -5,7 +5,7 @@ QT_PRIVATE += webengine-private gui-private HEADERS += ../shared/util.h -qtConfig(printing-and-pdf) { +qtConfig(webengine-printing-and-pdf) { DEFINES += ENABLE_PDF } diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 2e6343469..e67cf0ed0 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -8,7 +8,7 @@ SUBDIRS += \ qquickwebenginedefaultsurfaceformat \ qquickwebengineview -qtConfig(testsupport) { +qtConfig(webengine-testsupport) { SUBDIRS += \ qmltests \ qquickwebengineviewgraphics diff --git a/tests/auto/quick/tests.pri b/tests/auto/quick/tests.pri index 15f6517a4..7983a248f 100644 --- a/tests/auto/quick/tests.pri +++ b/tests/auto/quick/tests.pri @@ -19,7 +19,7 @@ QT += testlib network quick webengine # This define is used by some tests to look up resources in the source tree DEFINES += TESTS_SOURCE_DIR=\\\"$$PWD/\\\" -qtConfig(testsupport) { +qtConfig(webengine-testsupport) { DEFINES += ENABLE_QML_TESTSUPPORT_API } diff --git a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp index 9531d0cf4..7094c8e4b 100644 --- a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp +++ b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include <QCoreApplication> +#include <QSignalSpy> #include <QStandardPaths> #include <QTemporaryDir> #include <QTest> @@ -37,6 +38,18 @@ #include <httpserver.h> #include <waitforsignal.h> +static std::unique_ptr<HttpReqRep> waitForFaviconRequest(HttpServer *server) +{ + auto rr = waitForRequest(server); + if (!rr || + rr->requestMethod() != QByteArrayLiteral("GET") || + rr->requestPath() != QByteArrayLiteral("/favicon.ico")) + return nullptr; + rr->setResponseStatus(404); + rr->sendResponse(); + return std::move(rr); +} + class tst_QWebEngineDownloads : public QObject { Q_OBJECT @@ -46,6 +59,7 @@ private Q_SLOTS: void downloadTwoLinks(); void downloadPage_data(); void downloadPage(); + void downloadViaSetUrl(); }; enum DownloadTestUserAction { @@ -317,12 +331,8 @@ void tst_QWebEngineDownloads::downloadLink() QVERIFY(loadOk); // 1.1. Ignore favicon request - auto favIconRR = waitForRequest(&server); + auto favIconRR = waitForFaviconRequest(&server); QVERIFY(favIconRR); - QCOMPARE(favIconRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(favIconRR->requestPath(), QByteArrayLiteral("/favicon.ico")); - favIconRR->setResponseStatus(404); - favIconRR->sendResponse(); // 2. Simulate user action // @@ -439,12 +449,8 @@ void tst_QWebEngineDownloads::downloadTwoLinks() QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; })); QVERIFY(loadOk); - auto favIconRR = waitForRequest(&server); + auto favIconRR = waitForFaviconRequest(&server); QVERIFY(favIconRR); - QCOMPARE(favIconRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(favIconRR->requestPath(), QByteArrayLiteral("/favicon.ico")); - favIconRR->setResponseStatus(404); - favIconRR->sendResponse(); QTRY_VERIFY(view.focusWidget()); QWidget *renderWidget = view.focusWidget(); @@ -541,12 +547,8 @@ void tst_QWebEngineDownloads::downloadPage() QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; })); QVERIFY(loadOk); - auto favIconRR = waitForRequest(&server); + auto favIconRR = waitForFaviconRequest(&server); QVERIFY(favIconRR); - QCOMPARE(favIconRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(favIconRR->requestPath(), QByteArrayLiteral("/favicon.ico")); - favIconRR->setResponseStatus(404); - favIconRR->sendResponse(); QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); @@ -593,5 +595,70 @@ void tst_QWebEngineDownloads::downloadPage() QVERIFY(file.exists()); } +void tst_QWebEngineDownloads::downloadViaSetUrl() +{ + // Reproduce the scenario described in QTBUG-63388 by triggering downloads + // of the same file multiple times via QWebEnginePage::setUrl + + HttpServer server; + QWebEngineProfile profile; + QWebEnginePage page(&profile); + QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished); + QSignalSpy urlSpy(&page, &QWebEnginePage::urlChanged); + const QUrl indexUrl = server.url(); + const QUrl fileUrl = server.url(QByteArrayLiteral("/file")); + + // Set up the test scenario by trying to load some unrelated HTML. + + page.setUrl(indexUrl); + + auto indexRR = waitForRequest(&server); + QVERIFY(indexRR); + QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); + QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); + indexRR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + indexRR->setResponseBody(QByteArrayLiteral("<html><body>Hello</body></html>")); + indexRR->sendResponse(); + + auto indexFavRR = waitForFaviconRequest(&server); + QVERIFY(indexFavRR); + + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(urlSpy.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), indexUrl); + + // Download files via setUrl. With QTBUG-63388 after the first iteration the + // downloads would be triggered for indexUrl and not fileUrl. + + QVector<QUrl> downloadUrls; + QObject::connect(&profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { + downloadUrls.append(item->url()); + }); + + for (int i = 0; i != 3; ++i) { + page.setUrl(fileUrl); + QCOMPARE(page.url(), fileUrl); + + auto fileRR = waitForRequest(&server); + QVERIFY(fileRR); + fileRR->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); + fileRR->setResponseBody(QByteArrayLiteral("redacted")); + fileRR->sendResponse(); + + auto fileFavRR = waitForFaviconRequest(&server); + QVERIFY(fileFavRR); + + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(urlSpy.count(), 2); + QTRY_COMPARE(downloadUrls.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), fileUrl); + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), indexUrl); + QCOMPARE(downloadUrls.takeFirst(), fileUrl); + QCOMPARE(page.url(), indexUrl); + } +} + QTEST_MAIN(tst_QWebEngineDownloads) #include "tst_qwebenginedownloads.moc" diff --git a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro index a2dbd4d70..47c09e1ce 100644 --- a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro +++ b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro @@ -1,4 +1,4 @@ include(../tests.pri) QT *= core-private -qtConfig(printing-and-pdf): DEFINES+=QWEBENGINEPAGE_PDFPRINTINGENABLED +qtConfig(webengine-printing-and-pdf): DEFINES+=QWEBENGINEPAGE_PDFPRINTINGENABLED diff --git a/tests/auto/widgets/qwebenginepage/resources/bar.txt b/tests/auto/widgets/qwebenginepage/resources/bar.txt new file mode 100644 index 000000000..5716ca598 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/bar.txt @@ -0,0 +1 @@ +bar diff --git a/tests/auto/widgets/qwebenginepage/resources/foo.txt b/tests/auto/widgets/qwebenginepage/resources/foo.txt new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/foo.txt @@ -0,0 +1 @@ +foo diff --git a/tests/auto/widgets/qwebenginepage/resources/path with spaces.txt b/tests/auto/widgets/qwebenginepage/resources/path with spaces.txt new file mode 100644 index 000000000..4f79cb0dd --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/path with spaces.txt @@ -0,0 +1 @@ +contents with spaces diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index b4b1abc8c..1c9b668ae 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -193,6 +193,8 @@ private Q_SLOTS: void setUrlWithPendingLoads(); void setUrlToEmpty(); void setUrlToInvalid(); + void setUrlToBadDomain(); + void setUrlToBadPort(); void setUrlHistory(); void setUrlUsingStateObject(); void setUrlThenLoads_data(); @@ -200,6 +202,7 @@ private Q_SLOTS: void loadFinishedAfterNotFoundError(); void loadInSignalHandlers_data(); void loadInSignalHandlers(); + void loadFromQrc(); void restoreHistory(); void toPlainTextLoadFinishedRace_data(); @@ -2655,18 +2658,19 @@ Q_OBJECT public: GetUserMediaTestPage() : m_gotRequest(false) + , m_loadSucceeded(false) { connect(this, &QWebEnginePage::featurePermissionRequested, this, &GetUserMediaTestPage::onFeaturePermissionRequested); - + connect(this, &QWebEnginePage::loadFinished, [this](bool success){ + m_loadSucceeded = success; + }); // We need to load content from a resource in order for the securityOrigin to be valid. - QSignalSpy loadSpy(this, SIGNAL(loadFinished(bool))); load(QUrl("qrc:///resources/content.html")); - QTRY_COMPARE(loadSpy.count(), 1); } void jsGetUserMedia(const QString & constraints) { - runJavaScript( + evaluateJavaScriptSync(this, QStringLiteral( "var promiseFulfilled = false;" "var promiseRejected = false;" @@ -2707,6 +2711,11 @@ public: return m_gotRequest; } + bool loadSucceeded() const + { + return m_loadSucceeded; + } + private Q_SLOTS: void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature) { @@ -2717,6 +2726,7 @@ private Q_SLOTS: private: bool m_gotRequest; + bool m_loadSucceeded; QWebEnginePage::Feature m_requestedFeature; QUrl m_requestSecurityOrigin; @@ -2747,6 +2757,7 @@ void tst_QWebEnginePage::getUserMediaRequest() QFETCH(QWebEnginePage::Feature, feature); GetUserMediaTestPage page; + QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 20000); page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); // 1. Rejecting request on C++ side should reject promise on JS side. @@ -2775,6 +2786,7 @@ void tst_QWebEnginePage::getUserMediaRequest() void tst_QWebEnginePage::getUserMediaRequestDesktopAudio() { GetUserMediaTestPage page; + QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 20000); page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); // Audio-only desktop capture is not supported. JS Promise should be @@ -2792,6 +2804,7 @@ void tst_QWebEnginePage::getUserMediaRequestDesktopAudio() void tst_QWebEnginePage::getUserMediaRequestSettingDisabled() { GetUserMediaTestPage page; + QTRY_VERIFY_WITH_TIMEOUT(page.loadSucceeded(), 20000); page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false); // With the setting disabled, the JS Promise should be rejected without @@ -3180,21 +3193,19 @@ void tst_QWebEnginePage::progressSignal() void tst_QWebEnginePage::urlChange() { - QSignalSpy urlSpy(m_page, SIGNAL(urlChanged(QUrl))); + QSignalSpy urlSpy(m_page, &QWebEnginePage::urlChanged); QUrl dataUrl("data:text/html,<h1>Test"); m_view->setUrl(dataUrl); - QVERIFY(urlSpy.wait()); - - QCOMPARE(urlSpy.size(), 1); + QTRY_COMPARE(urlSpy.size(), 1); + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), dataUrl); QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>"); m_view->setUrl(dataUrl2); - QVERIFY(urlSpy.wait()); - - QCOMPARE(urlSpy.size(), 2); + QTRY_COMPARE(urlSpy.size(), 1); + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), dataUrl2); } class FakeReply : public QNetworkReply { @@ -3305,7 +3316,7 @@ void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures() page.load(second); QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 12000); - QCOMPARE(page.url(), first); + QCOMPARE(page.url(), second); QCOMPARE(page.requestedUrl(), second); QVERIFY(!spy.at(1).first().toBool()); } @@ -3819,6 +3830,90 @@ void tst_QWebEnginePage::setUrlToInvalid() QCOMPARE(baseUrlSync(&page), aboutBlank); } +void tst_QWebEnginePage::setUrlToBadDomain() +{ + // Failing to load a URL should still emit a urlChanged signal. + // + // This test is based on the scenario in QTBUG-48995 where the second setUrl + // call first triggers an unexpected additional urlChanged signal with the + // original url before the expected signal with the new url. + + // RFC 2606 says the .invalid TLD should be invalid. + const QUrl url1 = QStringLiteral("http://this.is.definitely.invalid/"); + const QUrl url2 = QStringLiteral("http://this.is.also.invalid/"); + QWebEnginePage page; + QSignalSpy urlSpy(&page, &QWebEnginePage::urlChanged); + QSignalSpy titleSpy(&page, &QWebEnginePage::titleChanged); + QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished); + + page.setUrl(url1); + + QTRY_COMPARE(urlSpy.count(), 1); + QTRY_COMPARE(titleSpy.count(), 1); + QTRY_COMPARE(loadSpy.count(), 1); + + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), url1); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url1.host()); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); + + QCOMPARE(page.url(), url1); + QCOMPARE(page.title(), url1.host()); + + page.setUrl(url2); + + QTRY_COMPARE(urlSpy.count(), 1); + QTRY_COMPARE(titleSpy.count(), 1); + QTRY_COMPARE(loadSpy.count(), 1); + + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), url2); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url2.host()); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); + + QCOMPARE(page.url(), url2); + QCOMPARE(page.title(), url2.host()); +} + +void tst_QWebEnginePage::setUrlToBadPort() +{ + // Failing to load a URL should still emit a urlChanged signal. + + // Ports 244-245 are hopefully unbound (marked unassigned in RFC1700). + const QUrl url1 = QStringLiteral("http://127.0.0.1:244/"); + const QUrl url2 = QStringLiteral("http://127.0.0.1:245/"); + QWebEnginePage page; + QSignalSpy urlSpy(&page, &QWebEnginePage::urlChanged); + QSignalSpy titleSpy(&page, &QWebEnginePage::titleChanged); + QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished); + + page.setUrl(url1); + + QTRY_COMPARE(urlSpy.count(), 1); + QTRY_COMPARE(titleSpy.count(), 2); + QTRY_COMPARE(loadSpy.count(), 1); + + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), url1); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url1.authority()); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url1.host()); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); + + QCOMPARE(page.url(), url1); + QCOMPARE(page.title(), url1.host()); + + page.setUrl(url2); + + QTRY_COMPARE(urlSpy.count(), 1); + QTRY_COMPARE(titleSpy.count(), 2); + QTRY_COMPARE(loadSpy.count(), 1); + + QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), url2); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url2.authority()); + QCOMPARE(titleSpy.takeFirst().value(0).toString(), url2.host()); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); + + QCOMPARE(page.url(), url2); + QCOMPARE(page.title(), url2.host()); +} + static QStringList collectHistoryUrls(QWebEngineHistory *history) { QStringList urls; @@ -3979,9 +4074,8 @@ void tst_QWebEnginePage::setUrlThenLoads() const QUrl urlToLoad1("qrc:/resources/test2.html"); const QUrl urlToLoad2("qrc:/resources/test1.html"); - // Just after first load. URL didn't changed yet. m_page->load(urlToLoad1); - QCOMPARE(m_page->url(), url); + QCOMPARE(m_page->url(), urlToLoad1); QCOMPARE(m_page->requestedUrl(), urlToLoad1); // baseUrlSync spins an event loop and this sometimes return the next result. // QCOMPARE(baseUrlSync(m_page), baseUrl); @@ -3995,9 +4089,8 @@ void tst_QWebEnginePage::setUrlThenLoads() QCOMPARE(m_page->requestedUrl(), urlToLoad1); QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1)); - // Just after second load. URL didn't changed yet. m_page->load(urlToLoad2); - QCOMPARE(m_page->url(), urlToLoad1); + QCOMPARE(m_page->url(), urlToLoad2); QCOMPARE(m_page->requestedUrl(), urlToLoad2); QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1)); QTRY_COMPARE(startedSpy.count(), 3); @@ -4120,6 +4213,41 @@ void tst_QWebEnginePage::loadInSignalHandlers() QCOMPARE(m_page->url(), urlForSetter); } +void tst_QWebEnginePage::loadFromQrc() +{ + QWebEnginePage page; + QSignalSpy spy(&page, &QWebEnginePage::loadFinished); + + // Standard case. + page.load(QStringLiteral("qrc:///resources/foo.txt")); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().value(0).toBool(), true); + QCOMPARE(toPlainTextSync(&page), QStringLiteral("foo\n")); + + // Query and fragment parts are ignored. + page.load(QStringLiteral("qrc:///resources/bar.txt?foo=1#bar")); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().value(0).toBool(), true); + QCOMPARE(toPlainTextSync(&page), QStringLiteral("bar\n")); + + // Literal spaces are OK. + page.load(QStringLiteral("qrc:///resources/path with spaces.txt")); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().value(0).toBool(), true); + QCOMPARE(toPlainTextSync(&page), QStringLiteral("contents with spaces\n")); + + // Escaped spaces are OK too. + page.load(QStringLiteral("qrc:///resources/path%20with%20spaces.txt")); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().value(0).toBool(), true); + QCOMPARE(toPlainTextSync(&page), QStringLiteral("contents with spaces\n")); + + // Resource not found, loading fails. + page.load(QStringLiteral("qrc:///nope")); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst().value(0).toBool(), false); +} + void tst_QWebEnginePage::restoreHistory() { QWebChannel channel; diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc index 4fddd7a3f..fc83aefa5 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc @@ -19,5 +19,8 @@ <file>resources/test2.html</file> <file>resources/testiframe.html</file> <file>resources/testiframe2.html</file> + <file>resources/foo.txt</file> + <file>resources/bar.txt</file> + <file>resources/path with spaces.txt</file> </qresource> </RCC> diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index c3c8f9b28..8d2f92d96 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -35,6 +35,7 @@ #include <qtemporarydir.h> #include <QClipboard> #include <QCompleter> +#include <QLabel> #include <QLineEdit> #include <QHBoxLayout> #include <QMenu> @@ -172,6 +173,9 @@ private Q_SLOTS: void imeCompositionQueryEvent_data(); void imeCompositionQueryEvent(); void newlineInTextarea(); + + void mouseLeave(); + #ifndef QT_NO_CLIPBOARD void globalMouseSelection(); #endif @@ -2423,5 +2427,55 @@ void tst_QWebEngineView::contextMenu() QTRY_COMPARE(view.findChildren<QMenu *>().count(), childrenCount); } +void tst_QWebEngineView::mouseLeave() +{ + QScopedPointer<QWidget> containerWidget(new QWidget); + + QLabel *label = new QLabel(containerWidget.data()); + label->setStyleSheet("background-color: red;"); + label->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + label->setMinimumHeight(100); + + QWebEngineView *view = new QWebEngineView(containerWidget.data()); + view->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + view->setMinimumHeight(100); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setAlignment(Qt::AlignTop); + layout->setSpacing(0); + layout->setMargin(0); + layout->addWidget(label); + layout->addWidget(view); + containerWidget->setLayout(layout); + containerWidget->show(); + QVERIFY(QTest::qWaitForWindowExposed(containerWidget.data())); + QTest::mouseMove(containerWidget->windowHandle(), QPoint(0, 0)); + + auto innerText = [view]() -> QString { + return evaluateJavaScriptSync(view->page(), "document.getElementById('testDiv').innerText").toString(); + }; + + QSignalSpy loadFinishedSpy(view, SIGNAL(loadFinished(bool))); + view->setHtml("<html>" + "<head><script>" + "function init() {" + " var div = document.getElementById('testDiv');" + " div.onmouseenter = function(e) { div.innerText = 'Mouse IN' };" + " div.onmouseleave = function(e) { div.innerText = 'Mouse OUT' };" + "}" + "</script></head>" + "<body onload='init()' style='margin: 0px; padding: 0px'>" + " <div id='testDiv' style='width: 100%; height: 100%; background-color: green' />" + "</body>" + "</html>"); + QVERIFY(loadFinishedSpy.wait()); + QVERIFY(innerText().isEmpty()); + + QTest::mouseMove(containerWidget->windowHandle(), QPoint(50, 150)); + QTRY_COMPARE(innerText(), QStringLiteral("Mouse IN")); + QTest::mouseMove(containerWidget->windowHandle(), QPoint(50, 50)); + QTRY_COMPARE(innerText(), QStringLiteral("Mouse OUT")); +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro index 027eeb235..32a7806fe 100644 --- a/tests/auto/widgets/widgets.pro +++ b/tests/auto/widgets/widgets.pro @@ -19,8 +19,8 @@ qtConfig(accessibility) { SUBDIRS += qwebengineaccessibility } -qtConfig(spellchecker):!cross_compile { - !qtConfig(native-spellchecker) { +qtConfig(webengine-spellchecker):!cross_compile { + !qtConfig(webengine-native-spellchecker) { SUBDIRS += qwebenginespellcheck } else { message("Spellcheck test will not be built because it depends on usage of Hunspell dictionaries.") |