diff options
Diffstat (limited to 'tests')
16 files changed, 562 insertions, 107 deletions
diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp index 65d4ec295..930c208ee 100644 --- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp +++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** 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. @@ -32,7 +32,6 @@ #include <QtWebEngineCore/qwebenginecookiestore.h> #include <QtWebEngineWidgets/qwebenginepage.h> #include <QtWebEngineWidgets/qwebengineprofile.h> -#include <QtWebEngineWidgets/qwebengineview.h> class tst_QWebEngineCookieStore : public QObject { @@ -52,6 +51,9 @@ private Q_SLOTS: void cookieSignals(); void setAndDeleteCookie(); void batchCookieTasks(); + +private: + QWebEngineProfile m_profile; }; tst_QWebEngineCookieStore::tst_QWebEngineCookieStore() @@ -68,6 +70,7 @@ void tst_QWebEngineCookieStore::init() void tst_QWebEngineCookieStore::cleanup() { + m_profile.cookieStore()->deleteAllCookies(); } void tst_QWebEngineCookieStore::initTestCase() @@ -80,15 +83,15 @@ void tst_QWebEngineCookieStore::cleanupTestCase() void tst_QWebEngineCookieStore::cookieSignals() { - QWebEngineView view; - QWebEngineCookieStore *client = view.page()->profile()->cookieStore(); - client->deleteAllCookies(); + QWebEnginePage page(&m_profile); + + QWebEngineCookieStore *client = m_profile.cookieStore(); - QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &))); QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &))); - view.load(QUrl("qrc:///resources/index.html")); + page.load(QUrl("qrc:///resources/index.html")); QTRY_COMPARE(loadSpy.count(), 1); QVariant success = loadSpy.takeFirst().takeFirst(); @@ -110,11 +113,10 @@ void tst_QWebEngineCookieStore::cookieSignals() void tst_QWebEngineCookieStore::setAndDeleteCookie() { - QWebEngineView view; - QWebEngineCookieStore *client = view.page()->profile()->cookieStore(); - client->deleteAllCookies(); + QWebEnginePage page(&m_profile); + QWebEngineCookieStore *client = m_profile.cookieStore(); - QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &))); QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &))); @@ -130,7 +132,7 @@ void tst_QWebEngineCookieStore::setAndDeleteCookie() QTRY_COMPARE(cookieAddedSpy.count(),2); client->deleteCookie(cookie1); - view.load(QUrl("qrc:///resources/content.html")); + page.load(QUrl("qrc:///resources/content.html")); QTRY_COMPARE(loadSpy.count(), 1); QVariant success = loadSpy.takeFirst().takeFirst(); @@ -151,11 +153,10 @@ void tst_QWebEngineCookieStore::setAndDeleteCookie() void tst_QWebEngineCookieStore::batchCookieTasks() { - QWebEngineView view; - QWebEngineCookieStore *client = view.page()->profile()->cookieStore(); - client->deleteAllCookies(); + QWebEnginePage page(&m_profile); + QWebEngineCookieStore *client = m_profile.cookieStore(); - QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &))); QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &))); @@ -167,7 +168,7 @@ void tst_QWebEngineCookieStore::batchCookieTasks() client->setCookie(cookie2); QTRY_COMPARE(cookieAddedSpy.count(), 2); - view.load(QUrl("qrc:///resources/index.html")); + page.load(QUrl("qrc:///resources/index.html")); QTRY_COMPARE(loadSpy.count(), 1); QVariant success = loadSpy.takeFirst().takeFirst(); diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index daf4d811e..926c3e042 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** 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. @@ -32,7 +32,6 @@ #include <QtWebEngineWidgets/qwebenginepage.h> #include <QtWebEngineWidgets/qwebengineprofile.h> #include <QtWebEngineWidgets/qwebenginesettings.h> -#include <QtWebEngineWidgets/qwebengineview.h> class tst_QWebEngineUrlRequestInterceptor : public QObject { @@ -104,20 +103,22 @@ public: void tst_QWebEngineUrlRequestInterceptor::interceptRequest() { - QWebEngineView view; + QWebEngineProfile profile; + profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); TestRequestInterceptor interceptor(/* intercept */ true); - view.page()->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + profile.setRequestInterceptor(&interceptor); - QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); - view.page()->profile()->setRequestInterceptor(&interceptor); - view.load(QUrl("qrc:///resources/index.html")); + QWebEnginePage page(&profile); + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + page.load(QUrl("qrc:///resources/index.html")); QTRY_COMPARE(loadSpy.count(), 1); QVariant success = loadSpy.takeFirst().takeFirst(); QVERIFY(success.toBool()); loadSpy.clear(); QVariant ok; - view.page()->runJavaScript("post();", [&ok](const QVariant result){ ok = result; }); + page.runJavaScript("post();", [&ok](const QVariant result){ ok = result; }); QTRY_VERIFY(ok.toBool()); QTRY_COMPARE(loadSpy.count(), 1); success = loadSpy.takeFirst().takeFirst(); @@ -125,7 +126,7 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest() QVERIFY(!success.toBool()); loadSpy.clear(); - view.load(QUrl("qrc:///resources/__placeholder__")); + page.load(QUrl("qrc:///resources/__placeholder__")); QTRY_COMPARE(loadSpy.count(), 1); success = loadSpy.takeFirst().takeFirst(); // The redirection for __placeholder__ should succeed. @@ -135,8 +136,8 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest() // Make sure that registering an observer does not modify the request. TestRequestInterceptor observer(/* intercept */ false); - view.page()->profile()->setRequestInterceptor(&observer); - view.load(QUrl("qrc:///resources/__placeholder__")); + profile.setRequestInterceptor(&observer); + page.load(QUrl("qrc:///resources/__placeholder__")); QTRY_COMPARE(loadSpy.count(), 1); success = loadSpy.takeFirst().takeFirst(); // Since we do not intercept, loading an invalid path should not succeed. @@ -163,18 +164,18 @@ public: void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding() { - QWebEngineView view; - QWebEnginePage *page = view.page(); + QWebEngineProfile profile; LocalhostContentProvider contentProvider; - QSignalSpy spyLoadFinished(page, SIGNAL(loadFinished(bool))); + profile.setRequestInterceptor(&contentProvider); - page->profile()->setRequestInterceptor(&contentProvider); + QWebEnginePage page(&profile); + QSignalSpy spyLoadFinished(&page, SIGNAL(loadFinished(bool))); - page->setHtml("<p>Hi", QUrl::fromEncoded("http://[::1]/index.html")); + page.setHtml("<p>Hi", QUrl::fromEncoded("http://[::1]/index.html")); QTRY_COMPARE(spyLoadFinished.count(), 1); QCOMPARE(contentProvider.requestedUrls.count(), 0); - evaluateJavaScriptSync(page, "var r = new XMLHttpRequest();" + evaluateJavaScriptSync(&page, "var r = new XMLHttpRequest();" "r.open('GET', 'http://[::1]/test.xml', false);" "r.send(null);" ); @@ -185,12 +186,13 @@ void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding() void tst_QWebEngineUrlRequestInterceptor::requestedUrl() { - QWebEnginePage page; - page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + QWebEngineProfile profile; + profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + TestRequestInterceptor interceptor(/* intercept */ true); + profile.setRequestInterceptor(&interceptor); + QWebEnginePage page(&profile); QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); - TestRequestInterceptor interceptor(/* intercept */ true); - page.profile()->setRequestInterceptor(&interceptor); page.setUrl(QUrl("qrc:///resources/__placeholder__")); QVERIFY(spy.wait()); @@ -214,10 +216,11 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl() void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl() { - QWebEnginePage page; + QWebEngineProfile profile; TestRequestInterceptor interceptor(/* intercept */ true); - page.profile()->setRequestInterceptor(&interceptor); + profile.setRequestInterceptor(&interceptor); + QWebEnginePage page(&profile); QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); page.setUrl(QUrl("qrc:///resources/__placeholder__")); @@ -244,10 +247,11 @@ void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl() void tst_QWebEngineUrlRequestInterceptor::firstPartyUrl() { - QWebEnginePage page; + QWebEngineProfile profile; TestRequestInterceptor interceptor(/* intercept */ false); - page.profile()->setRequestInterceptor(&interceptor); + profile.setRequestInterceptor(&interceptor); + QWebEnginePage page(&profile); QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); page.setUrl(QUrl("qrc:///resources/firstparty.html")); diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml index 9fb8c4bfe..cadad4e27 100644 --- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml +++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml @@ -82,6 +82,24 @@ WebEngineView { verifyElementHasFocus(element); } + function getElementCenter(element) { + var center; + runJavaScript("(function() {" + + " var elem = document.getElementById('" + element + "');" + + " var rect = elem.getBoundingClientRect();" + + " return { 'x': (rect.left + rect.right) / 2, 'y': (rect.top + rect.bottom) / 2 };" + + "})();", function(result) { center = result } ); + testCase.tryVerify(function() { return center !== undefined; }); + return center; + } + + function getTextSelection() { + var textSelection; + runJavaScript("window.getSelection().toString()", function(result) { textSelection = result }); + testCase.tryVerify(function() { return textSelection !== undefined; }); + return textSelection; + } + TestResult { id: testResult } TestCase { id: testCase } diff --git a/tests/auto/quick/qmltests/data/favicon.html b/tests/auto/quick/qmltests/data/favicon.html index 9823fa323..7a81194e4 100644 --- a/tests/auto/quick/qmltests/data/favicon.html +++ b/tests/auto/quick/qmltests/data/favicon.html @@ -5,6 +5,6 @@ <body> <p>It's expected that you see a favicon displayed for this page when you open it as a local file.</p> <p>The favicon looks like this:</p> -<img src="icons/favicon.png"/> +<img id='image' src="icons/favicon.png"/> </body> </html> diff --git a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml new file mode 100644 index 000000000..58947beaf --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** 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 QtQuick.Controls 1.4 +import QtTest 1.0 +import QtWebEngine 1.6 + +TestWebEngineView { + id: webEngineView + width: 400 + height: 400 + + property string linkText: "" + property var mediaType: null + property string selectedText: "" + + onContextMenuRequested: { + linkText = request.linkText; + mediaType = request.mediaType; + selectedText = request.selectedText; + } + + SignalSpy { + id: contextMenuRequestedSpy + target: webEngineView + signalName: "contextMenuRequested" + } + + function getContextMenus() { + var data = webEngineView.data; + var contextMenus = []; + + for (var i = 0; i < data.length; i++) { + if (data[i].type == MenuItemType.Menu) { + contextMenus.push(data[i]); + } + } + return contextMenus; + } + + function destroyContextMenu() { + contextMenuTest.keyPress(Qt.Key_Escape); + return getContextMenus().length == 0; + } + + TestCase { + id: contextMenuTest + name: "WebEngineViewContextMenu" + when: windowShown + + function init() { + var contextMenus = getContextMenus(); + compare(contextMenus.length, 0); + } + + function cleanup() { + contextMenuRequestedSpy.clear(); + } + + function test_contextMenu_data() { + return [ + { tag: "defaultContextMenu", userHandled: false, accepted: false }, + { tag: "defaultContextMenuWithConnect", userHandled: true, accepted: false }, + { tag: "dontShowDefaultContextMenu", userHandled: true, accepted: true }, + ]; + } + + function test_contextMenu(row) { + if (Qt.platform.os == "osx") { + skip("When the menu pops up on macOS, it does not return and the test fails after time out."); + } + + function contextMenuHandler(request) { + request.accepted = row.accepted; + } + + if (row.userHandled) { + webEngineView.contextMenuRequested.connect(contextMenuHandler); + } + + mouseClick(webEngineView, 20, 20, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + // There should be maximum one ContextMenu present at a time + var contextMenus = getContextMenus(); + verify(contextMenus.length <= 1); + compare(contextMenus[0] != null, !row.accepted); + + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + webEngineView.contextMenuRequested.disconnect(contextMenuHandler); + } + + function test_contextMenuLinkAndSelectedText() { + if (Qt.platform.os == "osx") { + skip("When the menu pops up on macOS, it does not return and the test fails after time out."); + } + + webEngineView.loadHtml("<html><body>" + + "<span id='text'>Text </span>" + + "<a id='link' href='test1.html'>Link</a>" + + "</body></html>"); + verify(webEngineView.waitForLoadSucceeded()); + + // 1. Nothing is selected, right click on the link + var linkCenter = getElementCenter("link"); + mouseClick(webEngineView, linkCenter.x, linkCenter.y, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + var contextMenus = getContextMenus(); + compare(contextMenus.length, 1); + verify(contextMenus[0]); + compare(linkText, "Link"); + compare(mediaType, ContextMenuRequest.MediaTypeNone); + compare(selectedText, ""); + + contextMenuRequestedSpy.clear(); + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + + // 2. Everything is selected, right click on the link + webEngineView.triggerWebAction(WebEngineView.SelectAll); + tryVerify(function() { return getTextSelection() == "Text Link" }); + + mouseClick(webEngineView, linkCenter.x, linkCenter.y, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + contextMenus = getContextMenus(); + compare(contextMenus.length, 1); + verify(contextMenus[0]); + compare(linkText, "Link"); + compare(mediaType, ContextMenuRequest.MediaTypeNone); + compare(selectedText, "Text Link"); + + contextMenuRequestedSpy.clear(); + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + + // 3. Everything is selected, right click on the text + var textCenter = getElementCenter("text"); + mouseClick(webEngineView, textCenter.x, textCenter.y, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + contextMenus = getContextMenus(); + compare(contextMenus.length, 1); + verify(contextMenus[0]); + compare(linkText, ""); + compare(mediaType, ContextMenuRequest.MediaTypeNone); + compare(selectedText, "Text Link"); + + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + } + + function test_contextMenuMediaType() { + if (Qt.platform.os == "osx") { + skip("When the menu pops up on macOS, it does not return and the test fails after time out."); + } + + webEngineView.url = Qt.resolvedUrl("favicon.html"); + verify(webEngineView.waitForLoadSucceeded()); + // 1. Right click on the image + var center = getElementCenter("image"); + mouseClick(webEngineView, center.x, center.y, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + var contextMenus = getContextMenus(); + compare(contextMenus.length, 1); + verify(contextMenus[0]); + compare(linkText, ""); + compare(mediaType, ContextMenuRequest.MediaTypeImage); + compare(selectedText, ""); + contextMenuRequestedSpy.clear(); + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + + // 2. Right click out of the image + mouseClick(webEngineView, center.x + 30, center.y, Qt.RightButton); + contextMenuRequestedSpy.wait(); + compare(contextMenuRequestedSpy.count, 1); + + contextMenus = getContextMenus(); + compare(contextMenus.length, 1); + verify(contextMenus[0]); + compare(linkText, ""); + compare(mediaType, ContextMenuRequest.MediaTypeNone); + compare(selectedText, ""); + + // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying + tryVerify(destroyContextMenu); + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index ea474e0dc..1159f3194 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -54,6 +54,35 @@ TestWebEngineView { return url.toString().substring(16) } + function getFaviconPixel(faviconImage) { + var grabImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { }", test) + var faviconCanvas = Qt.createQmlObject(" + import QtQuick 2.5\n + Canvas { }", test) + + test.tryVerify(function() { return faviconImage.status == Image.Ready }); + faviconImage.grabToImage(function(result) { + grabImage.source = result.url + }); + test.tryVerify(function() { return grabImage.status == Image.Ready }); + + faviconCanvas.width = faviconImage.width; + faviconCanvas.height = faviconImage.height; + var ctx = faviconCanvas.getContext("2d"); + ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height); + var imageData = ctx.getImageData(Math.round(faviconCanvas.width/2), + Math.round(faviconCanvas.height/2), + faviconCanvas.width, + faviconCanvas.height); + + grabImage.destroy(); + faviconCanvas.destroy(); + + return imageData.data; + } + SignalSpy { id: iconChangedSpy target: webEngineView @@ -285,12 +314,6 @@ TestWebEngineView { var faviconImage = Qt.createQmlObject(" import QtQuick 2.5\n Image { sourceSize: Qt.size(width, height) }", test) - var grabImage = Qt.createQmlObject(" - import QtQuick 2.5\n - Image { }", test) - var faviconCanvas = Qt.createQmlObject(" - import QtQuick 2.5\n - Canvas { }", test) compare(iconChangedSpy.count, 0) @@ -303,27 +326,53 @@ TestWebEngineView { faviconImage.width = row.size faviconImage.height = row.size faviconImage.source = webEngineView.icon - verify(_waitFor(function() { return faviconImage.status == Image.Ready } )) - faviconImage.grabToImage(function(result) { - grabImage.source = result.url - }) - verify(_waitFor(function() { return grabImage.status == Image.Ready } )) + var pixel = getFaviconPixel(faviconImage); + compare(pixel[0], row.value) - faviconCanvas.width = faviconImage.width - faviconCanvas.height = faviconImage.height - var ctx = faviconCanvas.getContext("2d") - ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height) + faviconImage.destroy() + } - var center = Math.round(row.size/2) - var imageData = ctx.getImageData(center, center, center, center) - var pixel = imageData.data + function test_dynamicFavicon() { + var faviconImage = Qt.createQmlObject(" + import QtQuick 2.5\n + Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", test) + faviconImage.source = Qt.binding(function() { return webEngineView.icon; }); - compare(pixel[0], row.value) + var colors = [ + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==", "r": 255, "g": 0, "b": 0}, + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==", "r": 0, "g": 255, "b": 0}, + {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==", "r": 0, "g": 0, "b": 255}, + ]; + var pixel; + + compare(iconChangedSpy.count, 0); + webEngineView.loadHtml( + "<html>" + + "<link rel='icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='/>" + + "</html>" + ); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(iconChangedSpy, "count", 1); + + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 0); + compare(pixel[1], 0); + compare(pixel[2], 0); + + for (var i = 0; i < colors.length; ++i) { + iconChangedSpy.clear(); + runJavaScript("document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[i]["url"] + "';"); + tryCompare(faviconImage, "source", "image://favicon/data:image/png;base64," + colors[i]["url"]); + compare(iconChangedSpy.count, 1); + + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], colors[i]["r"]); + compare(pixel[1], colors[i]["g"]); + compare(pixel[2], colors[i]["b"]); + } faviconImage.destroy() - grabImage.destroy() - faviconCanvas.destroy() } } } diff --git a/tests/auto/quick/qmltests/data/tst_mouseClick.qml b/tests/auto/quick/qmltests/data/tst_mouseClick.qml index 527102f59..bd6625a90 100644 --- a/tests/auto/quick/qmltests/data/tst_mouseClick.qml +++ b/tests/auto/quick/qmltests/data/tst_mouseClick.qml @@ -64,24 +64,6 @@ TestWebEngineView { name: "WebEngineViewMouseClick" when: windowShown - function getElementCenter(element) { - var center; - runJavaScript("(function() {" + - " var elem = document.getElementById('" + element + "');" + - " var rect = elem.getBoundingClientRect();" + - " return { 'x': (rect.left + rect.right) / 2, 'y': (rect.top + rect.bottom) / 2 };" + - "})();", function(result) { center = result } ); - tryVerify(function() { return center != undefined; }); - return center; - } - - function getTextSelection() { - var textSelection; - runJavaScript("window.getSelection().toString()", function(result) { textSelection = result }); - tryVerify(function() { return textSelection != undefined; }); - return textSelection; - } - function test_singleClick() { webEngineView.settings.focusOnNavigationEnabled = false; webEngineView.loadHtml("<html><body>" + diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml new file mode 100644 index 000000000..36efa7680 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Controls + +Controls.Menu { + id: menu + signal done() + + // Use private API for now + onAboutToHide: doneTimer.start() + + // WORKAROUND On Mac the Menu may be destroyed before the MenuItem + // is actually triggered (see qtbase commit 08cc9b9991ae9ab51) + Timer { + id: doneTimer + interval: 100 + onTriggered: menu.done() + } +} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml new file mode 100644 index 000000000..e61f4c230 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Controls + +Controls.MenuItem { } + diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index 5014fd6e3..16ecbc1bc 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -43,6 +43,7 @@ OTHER_FILES += \ $$PWD/data/keyboardEvents.html \ $$PWD/data/titleupdate.js \ $$PWD/data/tst_activeFocusOnPress.qml \ + $$PWD/data/tst_contextMenu.qml \ $$PWD/data/tst_desktopBehaviorLoadHtml.qml \ $$PWD/data/tst_download.qml \ $$PWD/data/tst_favicon.qml \ @@ -92,6 +93,8 @@ OTHER_FILES += \ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/AlertDialog.qml \ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/ConfirmDialog.qml \ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/FilePicker.qml \ + $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml \ + $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml \ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/PromptDialog.qml \ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/qmldir \ $$PWD/mock-delegates/TestParams/FilePickerParams.qml \ diff --git a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp index 6bba8a6df..3ce697faf 100644 --- a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp +++ b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp @@ -418,6 +418,13 @@ void tst_QWebEngineDownloads::downloadLink() void tst_QWebEngineDownloads::downloadTwoLinks() { HttpServer server; + QSignalSpy requestSpy(&server, &HttpServer::newRequest); + QList<HttpReqRep*> results; + connect(&server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + rr->setParent(nullptr); + results.append(rr); + }); + QWebEngineProfile profile; QWebEnginePage page(&profile); QWebEngineView view; @@ -425,7 +432,8 @@ void tst_QWebEngineDownloads::downloadTwoLinks() view.load(server.url()); view.show(); - auto indexRR = waitForRequest(&server); + QTRY_COMPARE(requestSpy.count(), 1); + std::unique_ptr<HttpReqRep> indexRR(results.takeFirst()); QVERIFY(indexRR); QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); @@ -436,19 +444,24 @@ void tst_QWebEngineDownloads::downloadTwoLinks() QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; })); QVERIFY(loadOk); - auto favIconRR = waitForFaviconRequest(&server); + QTRY_COMPARE(requestSpy.count(), 2); + std::unique_ptr<HttpReqRep> favIconRR(results.takeFirst()); QVERIFY(favIconRR); + favIconRR->setResponseStatus(404); + favIconRR->sendResponse(); QTRY_VERIFY(view.focusWidget()); QWidget *renderWidget = view.focusWidget(); QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 10)); QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 30)); - auto file1RR = waitForRequest(&server); + QTRY_VERIFY(requestSpy.count() >= 3); + std::unique_ptr<HttpReqRep> file1RR(results.takeFirst()); QVERIFY(file1RR); QCOMPARE(file1RR->requestMethod(), QByteArrayLiteral("GET")); QCOMPARE(file1RR->requestPath(), QByteArrayLiteral("/file1")); - auto file2RR = waitForRequest(&server); + QTRY_COMPARE(requestSpy.count(), 4); + std::unique_ptr<HttpReqRep> file2RR(results.takeFirst()); QVERIFY(file2RR); QCOMPARE(file2RR->requestMethod(), QByteArrayLiteral("GET")); QCOMPARE(file2RR->requestPath(), QByteArrayLiteral("/file2")); diff --git a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp index 710561cce..6ae4c41e6 100644 --- a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp +++ b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp @@ -60,6 +60,7 @@ private Q_SLOTS: void downloadIconsDisabled(); void downloadTouchIconsEnabled_data(); void downloadTouchIconsEnabled(); + void dynamicFavicon(); private: QWebEngineView *m_view; @@ -473,6 +474,35 @@ void tst_QWebEngineFaviconManager::downloadTouchIconsEnabled() QVERIFY(icon.availableSizes().contains(expectedIconSize)); } +void tst_QWebEngineFaviconManager::dynamicFavicon() +{ + QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool))); + QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl))); + QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon))); + + QMap<Qt::GlobalColor, QString> colors; + colors.insert(Qt::red, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==")); + colors.insert(Qt::green, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==")); + colors.insert(Qt::blue, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==")); + + m_page->setHtml("<html>" + "<link rel='icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='/>" + "</html>"); + QTRY_COMPARE(loadFinishedSpy.count(), 1); + QTRY_COMPARE(iconUrlChangedSpy.count(), 1); + QTRY_COMPARE(iconChangedSpy.count(), 1); + + QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(Qt::black)); + + for (Qt::GlobalColor color : colors.keys()) { + iconChangedSpy.clear(); + evaluateJavaScriptSync(m_page, "document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[color] + "';"); + QTRY_COMPARE(iconChangedSpy.count(), 1); + QTRY_COMPARE(m_page->iconUrl().toString(), QString("data:image/png;base64," + colors[color])); + QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(color)); + } +} + QTEST_MAIN(tst_QWebEngineFaviconManager) #include "tst_qwebenginefaviconmanager.moc" diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index f0ab74d6c..a6f09e4fc 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -29,6 +29,7 @@ #include <QMainWindow> #include <QMenu> #include <QMimeDatabase> +#include <QNetworkProxy> #include <QOpenGLWidget> #include <QPaintEngine> #include <QPushButton> @@ -217,6 +218,7 @@ private Q_SLOTS: void viewSource(); void viewSourceURL_data(); void viewSourceURL(); + void proxyConfigWithUnexpectedHostPortPair(); private: static QPoint elementCenter(QWebEnginePage *page, const QString &id); @@ -4570,6 +4572,23 @@ void tst_QWebEnginePage::viewSourceURL() QVERIFY(!page.action(QWebEnginePage::ViewSource)->isEnabled()); } +Q_DECLARE_METATYPE(QNetworkProxy::ProxyType); + +void tst_QWebEnginePage::proxyConfigWithUnexpectedHostPortPair() +{ + // Chromium expects a proxy of type NoProxy to not have a host or port set. + + QNetworkProxy proxy; + proxy.setType(QNetworkProxy::NoProxy); + proxy.setHostName(QStringLiteral("127.0.0.1")); + proxy.setPort(244); + QNetworkProxy::setApplicationProxy(proxy); + + QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool))); + m_page->load(QStringLiteral("http://127.0.0.1:245/")); + QTRY_COMPARE(loadFinishedSpy.count(), 1); +} + static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")}; W_QTEST_MAIN(tst_QWebEnginePage, params) diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index 294cc52b1..6961f3b6d 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -163,20 +163,25 @@ public: class ReplyingUrlSchemeHandler : public QWebEngineUrlSchemeHandler { - QBuffer m_buffer; - QByteArray m_bufferData; public: ReplyingUrlSchemeHandler(QObject *parent = nullptr) : QWebEngineUrlSchemeHandler(parent) { - m_buffer.setBuffer(&m_bufferData); + } + ~ReplyingUrlSchemeHandler() + { } void requestStarted(QWebEngineUrlRequestJob *job) { - m_bufferData = job->requestUrl().toString().toUtf8(); - job->reply("text/plain;charset=utf-8", &m_buffer); + QBuffer *buffer = new QBuffer; + buffer->setData(job->requestUrl().toString().toUtf8()); + connect(buffer, &QIODevice::aboutToClose, buffer, &QObject::deleteLater); + m_buffers.append(buffer); + job->reply("text/plain;charset=utf-8", buffer); } + + QList<QPointer<QBuffer>> m_buffers; }; class StreamingIODevice : public QIODevice { @@ -309,6 +314,11 @@ void tst_QWebEngineProfile::urlSchemeHandlers() url = QUrl(QStringLiteral("aviancarrier:inspector.mortensen@politistyrke.dk")); QVERIFY(loadSync(&view, url)); QCOMPARE(toPlainTextSync(view.page()), url.toString()); + + // Check that all buffers got deleted + QCOMPARE(gopherHandler.m_buffers.count(), 2); + for (int i = 0; i < gopherHandler.m_buffers.count(); ++i) + QVERIFY(gopherHandler.m_buffers.at(i).isNull()); } class FailingUrlSchemeHandler : public QWebEngineUrlSchemeHandler diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp index e614c74d8..d852ca902 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp @@ -81,15 +81,12 @@ void tst_QWebEngineScript::injectionPoint() s.setInjectionPoint(static_cast<QWebEngineScript::InjectionPoint>(injectionPoint)); s.setWorldId(QWebEngineScript::MainWorld); QWebEnginePage page; - page.scripts().insert(s); - page.setHtml(QStringLiteral("<html><head><script> var contents;") + testScript - + QStringLiteral("document.addEventListener(\"load\", setTimeout(function(event) {\ - document.body.innerText = contents;\ - }, 550));\ - </script></head><body></body></html>")); QSignalSpy spyFinished(&page, &QWebEnginePage::loadFinished); + page.scripts().insert(s); + page.setHtml(QStringLiteral("<html><head><script>") + testScript + QStringLiteral("</script></head><body></body></html>")); QVERIFY(spyFinished.wait()); - QTRY_COMPARE(evaluateJavaScriptSync(&page, "document.body.innerText"), QVariant::fromValue(QStringLiteral("SUCCESS"))); + const QVariant expected(QVariant::fromValue(QStringLiteral("SUCCESS"))); + QTRY_COMPARE(evaluateJavaScriptSync(&page, "document.myContents"), expected); } void tst_QWebEngineScript::injectionPoint_data() @@ -97,17 +94,21 @@ void tst_QWebEngineScript::injectionPoint_data() QTest::addColumn<int>("injectionPoint"); QTest::addColumn<QString>("testScript"); QTest::newRow("DocumentCreation") << static_cast<int>(QWebEngineScript::DocumentCreation) - << QStringLiteral("var contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";"); + << QStringLiteral("document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";"); QTest::newRow("DocumentReady") << static_cast<int>(QWebEngineScript::DocumentReady) // use a zero timeout to make sure the user script got a chance to run as the order is undefined. << QStringLiteral("document.addEventListener(\"DOMContentLoaded\", function() {\ - setTimeout(function() {\ - contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ - }, 0)});"); - QTest::newRow("Deferred") << static_cast<int>(QWebEngineScript::Deferred) - << QStringLiteral("document.addEventListener(\"load\", setTimeout(function(event) {\ - contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ - }, 500));"); + setTimeout(function() {\ + document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ + }, 0)});"); + QTest::newRow("Deferred") << static_cast<int>(QWebEngineScript::DocumentReady) + << QStringLiteral("document.onreadystatechange = function() { \ + if (document.readyState == \"complete\") { \ + setTimeout(function() {\ + document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\ + }, 0);\ + } \ + };"); } void tst_QWebEngineScript::scriptWorld() diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST index 0da1000a8..bf7292c86 100644 --- a/tests/auto/widgets/qwebengineview/BLACKLIST +++ b/tests/auto/widgets/qwebengineview/BLACKLIST @@ -5,4 +5,4 @@ windows * [textSelectionOutOfInputField] -windows +* |