diff options
Diffstat (limited to 'tests/auto/quick/qmltests')
83 files changed, 3652 insertions, 2432 deletions
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST index 083c15984..fc8f9f0d8 100644 --- a/tests/auto/quick/qmltests/BLACKLIST +++ b/tests/auto/quick/qmltests/BLACKLIST @@ -1,11 +1,12 @@ -[WebEngineViewSingleFileUpload::test_acceptDirectory] -* +[NewWindowRequest::test_loadNewWindowRequest] +macos -[WebEngineViewSingleFileUpload::test_acceptMultipleFilesSelection] -* +[WebEngineViewContextMenu::test_contextMenuLinkAndSelectedText] +macos -[WebEngineViewSingleFileUpload::test_acceptSingleFileSelection] +[CertificateError::test_fatalError] * -[WebEngineViewSource::test_viewSourceURL] +[CertificateError::test_error] * + diff --git a/tests/auto/quick/qmltests/CMakeLists.txt b/tests/auto/quick/qmltests/CMakeLists.txt new file mode 100644 index 000000000..daae6d60d --- /dev/null +++ b/tests/auto/quick/qmltests/CMakeLists.txt @@ -0,0 +1,94 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +include(../../httpserver/httpserver.cmake) +include(../../util/util.cmake) + +qt_internal_add_test(tst_qmltests + SOURCES + tst_qmltests.cpp + LIBRARIES + Qt::GuiPrivate + Qt::QuickTest + Qt::TestPrivate + Qt::WebEngineQuick + Test::HttpServer + Test::Util +) + +set(testList + tst_action.qml + tst_activeFocusOnPress.qml + tst_audioMuted.qml + tst_contextMenu.qml + tst_basicProfiles.qml + tst_datalist.qml + tst_desktopBehaviorLoadHtml.qml + tst_download.qml + tst_dragHandlerUnderView.qml + tst_favicon.qml + tst_faviconDatabase.qml + tst_filePicker.qml + tst_filesystem.qml + tst_findText.qml + tst_focusOnNavigation.qml + tst_fullScreenRequest.qml + tst_getUserMedia.qml + tst_inputMethod.qml + tst_inputTextDirection.qml + tst_javaScriptDialogs.qml + tst_keyboardEvents.qml + tst_keyboardModifierMapping.qml + tst_linkHovered.qml + tst_loadFail.qml + tst_loadHtml.qml + tst_loadProgress.qml + tst_loadRecursionCrash.qml + tst_loadUrl.qml + tst_mouseClick.qml + tst_mouseMove.qml + tst_navigationHistory.qml + tst_navigationRequested.qml + tst_newViewRequest.qml + tst_notification.qml + tst_properties.qml + tst_runJavaScript.qml + tst_scrollPosition.qml + tst_settings.qml + tst_titleChanged.qml + tst_unhandledKeyEventPropagation.qml + tst_userScripts.qml + tst_userScriptCollection.qml + tst_viewSource.qml + tst_save.qml +) + +if(QT_FEATURE_webengine_webchannel) + list(APPEND testList tst_webchannel.qml) +endif() + +if(QT_FEATURE_ssl) + list(APPEND testList tst_certificateError.qml) +endif() + +if (NOT APPLE) + list(APPEND testList tst_geopermission.qml) +endif() + +set(content "") +foreach(test ${testList}) + set(contents "${contents}${CMAKE_CURRENT_LIST_DIR}/data/${test}\n") +endforeach() +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/webengine.qmltests ${contents}) + +set(tst_qmltests_resource_files + "resources/server.pem" + "resources/server.key" +) + +qt_internal_add_resource(tst_qmltests "tst_qmltests" + PREFIX + "/" + FILES + ${tst_qmltests_resource_files} +) diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml index f5e83c5d2..415985471 100644 --- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml +++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml @@ -1,53 +1,38 @@ -/**************************************************************************** -** -** 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: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.1 -import QtWebEngine 1.7 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine WebEngineView { property var loadStatus: null property bool windowCloseRequestedSignalEmitted: false settings.focusOnNavigationEnabled: true + function loadSucceeded() { return loadStatus == WebEngineView.LoadSucceededStatus } + function loadFailed() { return loadStatus == WebEngineView.LoadFailedStatus } + function loadStopped() { return loadStatus == WebEngineView.LoadStoppedStatus } + + function waitForLoadResult(timeout) { + loadStatus = null + var r = _waitFor(function() { return loadStatus != null && loadStatus != WebEngineView.LoadStartedStatus }, timeout) + return r + } + function waitForLoadSucceeded(timeout) { - var success = _waitFor(function() { return loadStatus == WebEngineView.LoadSucceededStatus }, timeout) loadStatus = null + var success = _waitFor(function() { return loadStatus == WebEngineView.LoadSucceededStatus }, timeout) return success } function waitForLoadFailed(timeout) { - var failure = _waitFor(function() { return loadStatus == WebEngineView.LoadFailedStatus }, timeout) loadStatus = null + var failure = _waitFor(function() { return loadStatus == WebEngineView.LoadFailedStatus }, timeout) return failure } function waitForLoadStopped(timeout) { - var stop = _waitFor(function() { return loadStatus == WebEngineView.LoadStoppedStatus }, timeout) loadStatus = null + var stop = _waitFor(function() { return loadStatus == WebEngineView.LoadStoppedStatus }, timeout) return stop } function waitForWindowCloseRequested() { @@ -55,7 +40,7 @@ WebEngineView { } function _waitFor(predicate, timeout) { if (timeout === undefined) - timeout = 12000; + timeout = 30000; var i = 0 while (i < timeout && !predicate()) { testResult.wait(50) @@ -85,12 +70,14 @@ WebEngineView { function getElementCenter(element) { var center; - runJavaScript("(function() {" + + testCase.tryVerify(function() { + 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 !== undefined; + }); return center; } @@ -101,15 +88,69 @@ WebEngineView { return textSelection; } + function getElementValue(element) { + var elementValue; + runJavaScript("document.getElementById('" + element + "').value", function(result) { + elementValue = result; + }); + testCase.tryVerify(function() { return elementValue != undefined; }); + return elementValue; + } + + function compareElementValue(element, expected) { + testCase.tryVerify(function() { return expected == getElementValue(element); }, 5000, + "Value of element \"" + element + "\" is \"" + expected + "\""); + } + + TestResult { id: testResult } - TestCase { id: testCase } - onLoadingChanged: { - loadStatus = loadRequest.status + onLoadingChanged: function(load) { + loadStatus = load.status } onWindowCloseRequested: { windowCloseRequestedSignalEmitted = true; } + + function getBodyText() { + let text + runJavaScript('document.body.innerText', function(t) { text = t }) + testCase.tryVerify(function() { return text !== undefined }) + return text + } + + function getItemPixel(item) { + var grabImage = Qt.createQmlObject(" + import QtQuick\n + Image { }", testCase) + var itemCanvas = Qt.createQmlObject(" + import QtQuick\n + Canvas { }", testCase) + + // Mark QML images with objectName: "image" to be able to check if the image is loaded. + if (item.objectName === "image") { + testCase.tryVerify(function() { return item.status === Image.Ready }); + } + + item.grabToImage(function(result) { + grabImage.source = result.url + }); + testCase.tryVerify(function() { return grabImage.status === Image.Ready }); + + itemCanvas.width = item.width; + itemCanvas.height = item.height; + var ctx = itemCanvas.getContext("2d"); + ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height); + var imageData = ctx.getImageData(Math.round(itemCanvas.width/2), + Math.round(itemCanvas.height/2), + itemCanvas.width, + itemCanvas.height); + + grabImage.destroy(); + itemCanvas.destroy(); + + return imageData.data; + } } diff --git a/tests/auto/quick/qmltests/data/accepttypes.html b/tests/auto/quick/qmltests/data/accepttypes.html new file mode 100644 index 000000000..aff39f96e --- /dev/null +++ b/tests/auto/quick/qmltests/data/accepttypes.html @@ -0,0 +1,21 @@ +<html> +<head> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<title>Default title</title> +</head> + +<body> +<input type="file" name="file" id="upfile" accept=""> + +<script> +window.onload = function() { + document.getElementById("upfile").focus(); +} + +function setAcceptType(acceptType) { + document.getElementById("upfile").accept = acceptType; + document.title = acceptType; +} +</script> +</body> +</html> diff --git a/tests/auto/quick/qmltests/data/favicon-misc.html b/tests/auto/quick/qmltests/data/favicon-misc.html index 9e788bdf4..03d1086ff 100644 --- a/tests/auto/quick/qmltests/data/favicon-misc.html +++ b/tests/auto/quick/qmltests/data/favicon-misc.html @@ -1,8 +1,8 @@ <html> <head> <title>Favicon Test</title> - <link rel="shortcut icon" href="icons/qt32.ico" /> - <link rel="apple-touch-icon" href="icons/qt144.png" /> + <link rel="shortcut icon" href="icons/qt32.ico" sizes="32x32" /> + <link rel="apple-touch-icon" href="icons/qt144.png" sizes="144x144"/> <link rel="shortcut icon" href="icons/unavailable.ico" /> </head> <body> diff --git a/tests/auto/quick/qmltests/data/filesystemapi.html b/tests/auto/quick/qmltests/data/filesystemapi.html new file mode 100644 index 000000000..ab1a33e4d --- /dev/null +++ b/tests/auto/quick/qmltests/data/filesystemapi.html @@ -0,0 +1,66 @@ +<html> +<head> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<title> Failed to Upload </title> +</script> +</head> + +<body> +<button>Request File Picker</button> +<script> + async function handleDirectoryEntry( dirHandle, out ) { + for await (const entry of dirHandle.values()) { + if (entry.kind === "file"){ + const file = await entry.getFile(); + out[ file.name ] = file; + } + if (entry.kind === "directory") { + const newHandle = await dirHandle.getDirectoryHandle( entry.name, { create: false } ); + const newOut = out[ entry.name ] = {}; + await handleDirectoryEntry( newHandle, newOut ); + } + } + } + const button = document.querySelector('button'); + button.addEventListener('click', async function() { + switch(window.dialogType) { + case "savePicker": + const saveFileHandle = await window.showSaveFilePicker(); + const writable = await saveFileHandle.createWritable(); + await writable.write(new Blob(['TEST_CONTENT'])); + await writable.close(); + console.log("TEST:DONE") + break; + case "filePicker": + let [openFileHandle] = await window.showOpenFilePicker(); + const options = {}; + options.mode = 'readwrite' + await openFileHandle.requestPermission(options) + const file = await openFileHandle.getFile(); + const contents = await file.text(); + console.log("TEST:" + contents) + console.log("TEST:DONE") + break; + case "directoryPicker": + console.log("start") + const dirHandle = await window.showDirectoryPicker(); + for await (const entry of dirHandle.values()) { + if (entry.kind === "file"){ + continue + } + if (entry.kind === "directory") { + console.log("TEST:" + entry.name) + } + } + console.log("TEST:DONE") + break; + default: + } + }); + window.onload = function() { + window.dialogType = window.location.href.split('=')[1]; + document.querySelector('button').focus() + } +</script> +</body> +</html> diff --git a/tests/auto/quick/qmltests/data/geolocation.html b/tests/auto/quick/qmltests/data/geolocation.html index 8b116c8ee..e8c54bc58 100644 --- a/tests/auto/quick/qmltests/data/geolocation.html +++ b/tests/auto/quick/qmltests/data/geolocation.html @@ -3,16 +3,21 @@ <title>Geolocation Permission API Test</title> <script> +var errorMessage; +var handled = false; + function successHandler(location) { var message = document.getElementById("message"); message.innerHTML = "Latitude: " + location.coords.latitude + "<br>Longitude: " + location.coords.longitude; - console.error("Success"); + errorMessage = ""; + handled = true; } function errorHandler(error) { - console.error(error.message); + errorMessage = error.message; + handled = true; } <!-- One shot example --> diff --git a/tests/auto/quick/qmltests/data/multifileupload.html b/tests/auto/quick/qmltests/data/multifileupload.html index 1f788a377..d41ea15c0 100644 --- a/tests/auto/quick/qmltests/data/multifileupload.html +++ b/tests/auto/quick/qmltests/data/multifileupload.html @@ -1,7 +1,7 @@ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> -<title> Mutli-file Upload </title> +<title> Failed to Upload </title> <script src = "./titleupdate.js"> </script> </head> diff --git a/tests/auto/quick/qmltests/data/singlefileupload.html b/tests/auto/quick/qmltests/data/singlefileupload.html index 6cfef7ade..ac91c2c0d 100644 --- a/tests/auto/quick/qmltests/data/singlefileupload.html +++ b/tests/auto/quick/qmltests/data/singlefileupload.html @@ -1,7 +1,7 @@ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> -<title> Single File Upload </title> +<title> Failed to Upload </title> <script src = "./titleupdate.js"> </script> </head> diff --git a/tests/auto/quick/qmltests/data/test2.html b/tests/auto/quick/qmltests/data/test2.html index 629c2a063..06b1c40cb 100644 --- a/tests/auto/quick/qmltests/data/test2.html +++ b/tests/auto/quick/qmltests/data/test2.html @@ -1,6 +1,6 @@ <html> <head><title>Test page with huge link area</title></head> <body> -<a title="A title" href="test1.html"><img width=200 height=200></a> +<a id="link" title="A title" href="test1.html"><div style="width:200px; height:200px; background-color:red"></div></a> </body> </html> diff --git a/tests/auto/quick/qmltests/data/test4.html b/tests/auto/quick/qmltests/data/test4.html index afda71bc5..82830668a 100644 --- a/tests/auto/quick/qmltests/data/test4.html +++ b/tests/auto/quick/qmltests/data/test4.html @@ -9,7 +9,6 @@ font-size: 50px; } </style> - <meta name="viewport" content="initial-scale=2.0"/> </head> <body> <button onclick="scrollWin()" id="scroll">Click me to scroll!</button><br><br> @@ -24,106 +23,107 @@ } </script> <div id="content"> - bla00<br/> - bla01<br/> - bla02<br/> - bla03<br/> - bla04<br/> - bla05<br/> - bla06<br/> - bla07<br/> - bla08<br/> - bla09<br/> - bla10<br/> - bla11<br/> - bla12<br/> - bla13<br/> - bla14<br/> - bla15<br/> - bla16<br/> - bla17<br/> - bla18<br/> - bla19<br/> - bla20<br/> - bla21<br/> - bla22<br/> - bla23<br/> - bla24<br/> - bla25<br/> - bla26<br/> - bla27<br/> - bla28<br/> - bla29<br/> - bla30<br/> - bla31<br/> - bla32<br/> - bla33<br/> - bla34<br/> - bla35<br/> - bla36<br/> - bla37<br/> - bla38<br/> - bla39<br/> - bla40<br/> - bla41<br/> - bla42<br/> - bla43<br/> - bla44<br/> - bla45<br/> - bla46<br/> - bla47<br/> - bla48<br/> - bla49<br/> - bla50<br/> - bla51<br/> - bla52<br/> - bla53<br/> - bla54<br/> - bla55<br/> - bla56<br/> - bla57<br/> - bla58<br/> - bla59<br/> - bla60<br/> - bla61<br/> - bla62<br/> - bla63<br/> - bla64<br/> - bla65<br/> - bla66<br/> - bla67<br/> - bla68<br/> - bla69<br/> - bla70<br/> - bla71<br/> - bla72<br/> - bla73<br/> - bla74<br/> - bla75<br/> - bla76<br/> - bla77<br/> - bla78<br/> - bla79<br/> - bla80<br/> - bla81<br/> - bla82<br/> - bla83<br/> - bla84<br/> - bla85<br/> - bla86<br/> - bla87<br/> - bla88<br/> - bla89<br/> - bla90<br/> - bla91<br/> - bla92<br/> - bla93<br/> - bla94<br/> - bla95<br/> - bla96<br/> - bla97<br/> - bla98<br/> - bla99<br/> + <p><a id='anchor' href='#anchor'>anchor</a> + <p>bla00 + <p>bla01 + <p>bla02 + <p>bla03 + <p>bla04 + <p>bla05 + <p>bla06 + <p>bla07 + <p>bla08 + <p>bla09 + <p>bla10 + <p>bla11 + <p>bla12 + <p>bla13 + <p>bla14 + <p>bla15 + <p>bla16 + <p>bla17 + <p>bla18 + <p>bla19 + <p>bla20 + <p>bla21 + <p>bla22 + <p>bla23 + <p>bla24 + <p>bla25 + <p>bla26 + <p>bla27 + <p>bla28 + <p>bla29 + <p>bla30 + <p>bla31 + <p>bla32 + <p>bla33 + <p>bla34 + <p>bla35 + <p>bla36 + <p>bla37 + <p>bla38 + <p>bla39 + <p>bla40 + <p>bla41 + <p>bla42 + <p>bla43 + <p>bla44 + <p>bla45 + <p>bla46 + <p>bla47 + <p>bla48 + <p>bla49 + <p>bla50 + <p>bla51 + <p>bla52 + <p>bla53 + <p>bla54 + <p>bla55 + <p>bla56 + <p>bla57 + <p>bla58 + <p>bla59 + <p>bla60 + <p>bla61 + <p>bla62 + <p>bla63 + <p>bla64 + <p>bla65 + <p>bla66 + <p>bla67 + <p>bla68 + <p>bla69 + <p>bla70 + <p>bla71 + <p>bla72 + <p>bla73 + <p>bla74 + <p>bla75 + <p>bla76 + <p>bla77 + <p>bla78 + <p>bla79 + <p>bla80 + <p>bla81 + <p>bla82 + <p>bla83 + <p>bla84 + <p>bla85 + <p>bla86 + <p>bla87 + <p>bla88 + <p>bla89 + <p>bla90 + <p>bla91 + <p>bla92 + <p>bla93 + <p>bla94 + <p>bla95 + <p>bla96 + <p>bla97 + <p>bla98 + <p>bla99 </div> </body> </html> diff --git a/tests/auto/quick/qmltests/data/titleupdate.js b/tests/auto/quick/qmltests/data/titleupdate.js index c86139c13..720e83676 100644 --- a/tests/auto/quick/qmltests/data/titleupdate.js +++ b/tests/auto/quick/qmltests/data/titleupdate.js @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 function updateTitle() { diff --git a/tests/auto/quick/qmltests/data/tst_action.qml b/tests/auto/quick/qmltests/data/tst_action.qml index 56a91d8d0..9e49c2dbf 100644 --- a/tests/auto/quick/qmltests/data/tst_action.qml +++ b/tests/auto/quick/qmltests/data/tst_action.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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.2 -import QtTest 1.0 -import QtWebEngine 1.8 +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -41,7 +16,7 @@ TestWebEngineView { } TestCase { - id: actionTests + id: testCase name: "WebEngineAction" when: windowShown @@ -51,8 +26,8 @@ TestWebEngineView { { webAction: WebEngineView.Forward, text: "Forward", iconName: "go-next", enabled: false }, { webAction: WebEngineView.Stop, text: "Stop", iconName: "", enabled: false }, { webAction: WebEngineView.Reload, text: "Reload", iconName: "view-refresh", enabled: true }, - { webAction: WebEngineView.Cut, text: "Cut", iconName: "Cut", enabled: true }, - { webAction: WebEngineView.Copy, text: "Copy", iconName: "", enabled: true }, + { webAction: WebEngineView.Cut, text: "Cut", iconName: "Cut", enabled: false }, + { webAction: WebEngineView.Copy, text: "Copy", iconName: "", enabled: false }, { webAction: WebEngineView.Paste, text: "Paste", iconName: "", enabled: true }, { webAction: WebEngineView.Undo, text: "Undo", iconName: "", enabled: true }, { webAction: WebEngineView.Redo, text: "Redo", iconName: "", enabled: true }, @@ -76,7 +51,7 @@ TestWebEngineView { { webAction: WebEngineView.InspectElement, text: "Inspect", iconName: "", enabled: true }, { webAction: WebEngineView.ExitFullScreen, text: "Exit full screen", iconName: "", enabled: true }, { webAction: WebEngineView.RequestClose, text: "Close Page", iconName: "", enabled: true }, - { webAction: WebEngineView.Unselect, text: "Unselect", iconName: "", enabled: true }, + { webAction: WebEngineView.Unselect, text: "Unselect", iconName: "", enabled: false }, { webAction: WebEngineView.SavePage, text: "Save page", iconName: "", enabled: true }, { webAction: WebEngineView.ViewSource, text: "View page source", iconName: "view-source", enabled: true }, { webAction: WebEngineView.ToggleBold, text: "&Bold", iconName: "", enabled: true }, @@ -90,7 +65,9 @@ TestWebEngineView { { webAction: WebEngineView.Indent, text: "&Indent", iconName: "", enabled: true }, { webAction: WebEngineView.Outdent, text: "&Outdent", iconName: "", enabled: true }, { webAction: WebEngineView.InsertOrderedList, text: "Insert &Ordered List", iconName: "", enabled: true }, - { webAction: WebEngineView.InsertUnorderedList, text: "Insert &Unordered List", iconName: "", enabled: true } + { webAction: WebEngineView.InsertUnorderedList, text: "Insert &Unordered List", iconName: "", enabled: true }, + { webAction: WebEngineView.ChangeTextDirectionLTR, text: "Change text direction left to right", iconName: "", enabled: true }, + { webAction: WebEngineView.ChangeTextDirectionRTL, text: "Change text direction right to left", iconName: "", enabled: true } ]; } @@ -110,17 +87,17 @@ TestWebEngineView { webEngineView.url = Qt.resolvedUrl("test1.html"); verify(webEngineView.waitForLoadSucceeded()); - var copyAction = webEngineView.action(WebEngineView.Copy); - verify(copyAction); + var selectAction = webEngineView.action(WebEngineView.SelectAll); + verify(selectAction); var stopAction = webEngineView.action(WebEngineView.Stop); verify(stopAction); - var triggerSpy = createTemporaryObject(signalSpy, actionTests, {target: copyAction, signalName: "triggered"}); - var stopTriggerSpy = createTemporaryObject(signalSpy, actionTests, {target: stopAction, signalName: "triggered"}); + var triggerSpy = createTemporaryObject(signalSpy, testCase, {target: selectAction, signalName: "triggered"}); + var stopTriggerSpy = createTemporaryObject(signalSpy, testCase, {target: stopAction, signalName: "triggered"}); - verify(copyAction.enabled); - copyAction.trigger(); + verify(selectAction.enabled); + selectAction.trigger(); compare(triggerSpy.count, 1); verify(!stopAction.enabled); @@ -148,7 +125,7 @@ TestWebEngineView { compare(enabledSpy.count, 0); selectAllAction.trigger(); compare(triggerSpy.count, 0); - compare(getTextSelection(), ""); + compare(webEngineView.getTextSelection(), ""); // Focus content by focusing window from JavaScript. Edit actions should be enabled and functional. webView.runJavaScript("window.focus();"); @@ -157,6 +134,7 @@ TestWebEngineView { selectAllAction.trigger(); compare(triggerSpy.count, 1); tryVerify(function() { return webView.getTextSelection() === "foo bar" }); + webView.destroy(); } function test_editActionsWithInitialFocus() { @@ -180,6 +158,7 @@ TestWebEngineView { selectAllAction.trigger(); compare(triggerSpy.count, 1); tryVerify(function() { return webView.getTextSelection() === "foo bar" }); + webView.destroy(); } } } diff --git a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml index c360a1da2..77968f6b6 100644 --- a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml +++ b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.5 -import QtTest 1.0 +import QtQuick +import QtTest Item { id: root @@ -55,6 +30,7 @@ Item { } TestCase { + id: testCase name: "ActiveFocusOnPress" when:windowShown diff --git a/tests/auto/quick/qmltests/data/tst_audioMuted.qml b/tests/auto/quick/qmltests/data/tst_audioMuted.qml new file mode 100644 index 000000000..85f813f0c --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_audioMuted.qml @@ -0,0 +1,38 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +TestWebEngineView { + id: view + width: 400 + height: 400 + + SignalSpy { + id: spy + target: view + signalName: "audioMutedChanged" + } + + TestCase { + id: testCase + name: "WebEngineViewAudioMuted" + + function test_audioMuted() { + compare(view.audioMuted, false); + view.audioMuted = true; + view.url = "about:blank"; + verify(view.waitForLoadSucceeded()); + compare(view.audioMuted, true); + compare(spy.count, 1); + compare(spy.signalArguments[0][0], true); + view.audioMuted = false; + compare(view.audioMuted, false); + compare(spy.count, 2); + compare(spy.signalArguments[1][0], false); + } + } +} + diff --git a/tests/auto/quick/qmltests/data/tst_basicProfiles.qml b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml new file mode 100644 index 000000000..97a25cdd8 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_basicProfiles.qml @@ -0,0 +1,90 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Qt.labs.platform + +Item { + WebEngineProfile { id: otrProfile; /* MEMO implicit offTheRecord: true */ } + WebEngineProfile { id: nonOtrProfile; offTheRecord: false } + + function getPath(path, offset = 1) { return path.substr(path.indexOf(':') + offset, path.length) } + property string appDataLocation: getPath(getPath(StandardPaths.writableLocation(StandardPaths.AppDataLocation).toString(), 3)) + property string cacheLocation: getPath(getPath(StandardPaths.writableLocation(StandardPaths.CacheLocation).toString(), 3)) + property string downloadLocation: getPath(getPath(StandardPaths.writableLocation(StandardPaths.DownloadLocation).toString(), 3)) + + TestCase { + name: "BasicProfiles" + + function test_defaultProfile() { + let p = WebEngine.defaultProfile + verify(p.offTheRecord) + + compare(p.storageName, '') + compare(p.cachePath, '') + compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/OffTheRecord') + compare(p.httpCacheType, WebEngineProfile.MemoryHttpCache) + compare(p.httpCacheMaximumSize, 0) + compare(p.persistentCookiesPolicy, WebEngineProfile.NoPersistentCookies) + + compare(getPath(p.downloadPath), downloadLocation) + compare(p.httpAcceptLanguage, '') + verify(p.httpUserAgent !== '') + compare(p.spellCheckEnabled, false) + compare(p.spellCheckLanguages, []) + + compare(p.userScripts.collection, []) + } + + function test_otrProfile() { + let p = otrProfile + verify(p.offTheRecord) + + compare(p.storageName, '') + compare(p.cachePath, '') + compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/OffTheRecord') + compare(p.httpCacheType, WebEngineProfile.MemoryHttpCache) + compare(p.httpCacheMaximumSize, 0) + compare(p.persistentCookiesPolicy, WebEngineProfile.NoPersistentCookies) + + compare(getPath(p.downloadPath), downloadLocation) + compare(p.httpAcceptLanguage, '') + verify(p.httpUserAgent !== '') + compare(p.spellCheckEnabled, false) + compare(p.spellCheckLanguages, []) + + compare(p.userScripts.collection, []) + } + + function test_nonOtrProfile() { + let p = nonOtrProfile + verify(!p.offTheRecord) + + compare(p.storageName, '') + compare(p.cachePath, '') + compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/UnknownProfile') + compare(p.httpCacheType, WebEngineProfile.MemoryHttpCache) + compare(p.httpCacheMaximumSize, 0) + compare(p.persistentCookiesPolicy, WebEngineProfile.NoPersistentCookies) + + compare(getPath(p.downloadPath), downloadLocation) + compare(p.httpAcceptLanguage, '') + verify(p.httpUserAgent !== '') + compare(p.spellCheckEnabled, false) + compare(p.spellCheckLanguages, []) + + compare(p.userScripts.collection, []) + + p.storageName = 'Test' + compare(p.storageName, 'Test') + compare(getPath(p.cachePath), cacheLocation + '/QtWebEngine/' + p.storageName) + compare(getPath(p.persistentStoragePath), appDataLocation + '/QtWebEngine/' + p.storageName) + + compare(p.httpCacheType, WebEngineProfile.DiskHttpCache) + compare(p.httpCacheMaximumSize, 0) + compare(p.persistentCookiesPolicy, WebEngineProfile.AllowPersistentCookies) + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_certificateError.qml b/tests/auto/quick/qmltests/data/tst_certificateError.qml new file mode 100644 index 000000000..220ef9ac8 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_certificateError.qml @@ -0,0 +1,122 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +import Test.Shared as Shared + +TestWebEngineView { + id: view; width: 320; height: 320 + + property bool deferError: false + property bool acceptCertificate: false + + SignalSpy { + id: spyError + target: view + signalName: 'certificateError' + } + + TestCase { + id: testCase + name: 'CertificateError' + when: windowShown + + function initTestCase() { + Shared.HttpsServer.setExpectError(true) + Shared.HttpsServer.newRequest.connect(function (request) { + request.setResponseBody('<html><body>Test</body></html>') + request.sendResponse() + }) + view.settings.errorPageEnabled = false + } + + function init() { + verify(Shared.HttpsServer.start()) + } + + function cleanup() { + Shared.HttpsServer.stop() + view.deferError = false + view.acceptCertificate = false + spyError.clear() + } + + function test_error_data() { + return [ + { tag: 'reject', deferError: false, acceptCertificate: false, expectedContent: '' }, + { tag: 'defer_reject', deferError: true, acceptCertificate: false, expectedContent: '' }, + { tag: 'defer_accept', deferError: true, acceptCertificate: true, expectedContent: 'Test' }, + ] + } + + function test_error(data) { + view.deferError = data.deferError + view.acceptCertificate = data.acceptCertificate + var handleCertificateError = function(error) { + if (deferError) + error.defer() + else if (acceptCertificate) + error.acceptCertificate() + else + error.rejectCertificate() + } + view.certificateError.connect(handleCertificateError) + + const server_url = Shared.HttpsServer.url() + view.url = server_url + + if (data.deferError) { + spyError.wait() + compare(spyError.count, 1) + compare('', view.getBodyText()) + + let error = spyError.signalArguments[0][0] + if (data.acceptCertificate) + error.acceptCertificate() + else + error.rejectCertificate() + } + + if (data.acceptCertificate) + verify(view.waitForLoadSucceeded()) + else + verify(view.waitForLoadFailed()) + + compare(spyError.count, 1) + compare(data.expectedContent, view.getBodyText()) + + view.certificateError.disconnect(handleCertificateError) + + let error = spyError.signalArguments[0][0] + compare(error.url, server_url) + verify(error.description.length > 0) + verify(error.overridable) + compare(error.type, WebEngineCertificateError.CertificateAuthorityInvalid) + } + + function test_fatalError() { + let error = undefined + var handleCertificateError = function(e) { error = e; } + view.certificateError.connect(handleCertificateError); + + view.url = Qt.resolvedUrl('https://revoked.badssl.com'); + if (!view.waitForLoadResult()) { + verify(!error, "There shouldn't be any certificate error if not loaded due to missing internet access!"); + skip("Couldn't load page from network, skipping test."); + } + view.certificateError.disconnect(handleCertificateError); + + // revoked certificate might not be reported as invalid by chromium and the load will silently succeed + const failed = view.loadStatus == WebEngineView.LoadFailedStatus, hasError = Boolean(error) + compare(hasError, failed) + if (failed) { + verify(!error.overridable); + // Fatal certificate errors are implicitly rejected. But second call should not cause crash. + error.rejectCertificate(); + } + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml index 99450a159..58e27b8ba 100644 --- a/tests/auto/quick/qmltests/data/tst_contextMenu.qml +++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** 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 +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import "../mock-delegates/TestParams" TestWebEngineView { id: webEngineView @@ -40,7 +15,7 @@ TestWebEngineView { property var mediaType: null property string selectedText: "" - onContextMenuRequested: { + onContextMenuRequested: function (request) { linkText = request.linkText; mediaType = request.mediaType; selectedText = request.selectedText; @@ -52,38 +27,20 @@ TestWebEngineView { 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 + id: testCase name: "WebEngineViewContextMenu" when: windowShown function init() { - var contextMenus = getContextMenus(); - compare(contextMenus.length, 0); + MenuParams.isMenuOpened = false; } function cleanup() { contextMenuRequestedSpy.clear(); } - function test_contextMenu_data() { + function test_contextMenuRequest_data() { return [ { tag: "defaultContextMenu", userHandled: false, accepted: false }, { tag: "defaultContextMenuWithConnect", userHandled: true, accepted: false }, @@ -91,11 +48,7 @@ TestWebEngineView { ]; } - 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 test_contextMenuRequest(row) { function contextMenuHandler(request) { request.accepted = row.accepted; } @@ -109,22 +62,12 @@ TestWebEngineView { mouseClick(webEngineView, 20, 20, Qt.RightButton); contextMenuRequestedSpy.wait(); compare(contextMenuRequestedSpy.count, 1); + tryCompare(MenuParams, "isMenuOpened", !row.accepted); - // 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>" + @@ -137,9 +80,6 @@ TestWebEngineView { 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, ""); @@ -150,8 +90,6 @@ TestWebEngineView { verify(webEngineView.action(WebEngineView.CopyLinkToClipboard).enabled); 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); @@ -161,16 +99,11 @@ TestWebEngineView { 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"); @@ -178,22 +111,12 @@ TestWebEngineView { 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 @@ -202,30 +125,19 @@ TestWebEngineView { 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_datalist.qml b/tests/auto/quick/qmltests/data/tst_datalist.qml new file mode 100644 index 000000000..f739639b2 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_datalist.qml @@ -0,0 +1,180 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Controls +import QtTest +import QtWebEngine + +TestWebEngineView { + id: webEngineView + width: 200 + height: 400 + + property string html: "<html><body>" + + "<input id='browserInput' list='browserDatalist'>" + + "<datalist id='browserDatalist'>" + + " <option value='Internet Explorer'>" + + " <option value='Firefox'>" + + " <option value='Chrome'>" + + " <option value='Opera'>" + + " <option value='Safari'>" + + "</datalist>" + + "</body></html>" + + function listView() { + if (webEngineView.parent.visibleChildren.length == 1) { + // No popup case. + return null; + } + + let overlay = null; + for (let i = 0; i < webEngineView.parent.visibleChildren.length; ++i) { + let child = webEngineView.parent.visibleChildren[i]; + if (child instanceof Overlay) { + overlay = child; + break; + } + } + + if (!overlay) + return null; + + let popupItem = null; + for (let i = 0; i < overlay.visibleChildren[0].visibleChildren.length; ++i) { + let child = overlay.visibleChildren[0].visibleChildren[i]; + if (child.objectName == "QQuickPopupItem") { + popupItem = child; + } + } + + if (!popupItem) + return null; + + for (let i = 0; i < popupItem.visibleChildren.length; ++i) { + let child = popupItem.visibleChildren[i]; + if (child instanceof ListView) + return child; + } + + return null; + } + + TestCase { + id: testCase + name: "WebEngineDatalist" + when: windowShown + + function test_showAndHide() { + webEngineView.loadHtml(webEngineView.html); + verify(webEngineView.waitForLoadSucceeded()); + + var values = ""; + webEngineView.runJavaScript( + "(function() {" + + " var browserDatalist = document.getElementById('browserDatalist');" + + " var options = browserDatalist.options;" + + " var result = [];" + + " for (let i = 0; i < options.length; ++i) {" + + " result.push(options[i].value);" + + " }" + + " return result;" + + "})();", function(result) { values = result; }); + tryVerify(function() { return values.length != 0; }); + compare(values, ["Internet Explorer", "Firefox", "Chrome", "Opera", "Safari"]); + compareElementValue("browserInput", ""); + + // Make sure there is no open popup yet. + verify(!listView()); + // Click in the input field. + var browserInputCenter = getElementCenter("browserInput"); + mouseClick(webEngineView, browserInputCenter.x, browserInputCenter.y, Qt.LeftButton); + // Wait for the popup. + tryVerify(function() { return listView() != null; }); + + // No suggestion is selected. + verify(!listView().currentItem); + compare(listView().count, 5); + + // Accepting suggestion does nothing. + keyClick(Qt.Key_Enter); + tryVerify(function() { return listView() != null; }); + verify(!listView().currentItem); + + // Escape should close popup. + keyClick(Qt.Key_Escape); + tryVerify(function() { return listView() == null; }); + + // Key Down should open the popup and select the first suggestion. + keyClick(Qt.Key_Down); + tryVerify(function() { return listView() != null; }); + compare(listView().currentIndex, 0); + verify(listView().currentItem); + } + + function test_keyboardNavigationAndAccept() { + webEngineView.loadHtml(html); + verify(webEngineView.waitForLoadSucceeded()); + setFocusToElement("browserInput"); + + // Make sure there is no open popup yet. + verify(!listView()); + + // Key Down should open the popup and select the first suggestion. + keyClick(Qt.Key_Down); + tryVerify(function() { return listView() != null; }); + compare(listView().currentIndex, 0); + + // Test keyboard navigation in list. + keyClick(Qt.Key_Up); + compare(listView().currentIndex, 4); + keyClick(Qt.Key_Up); + compare(listView().currentIndex, 3); + keyClick(Qt.Key_PageDown); + compare(listView().currentIndex, 4); + keyClick(Qt.Key_PageUp); + compare(listView().currentIndex, 0); + keyClick(Qt.Key_Down); + compare(listView().currentIndex, 1); + keyClick(Qt.Key_Down); + compare(listView().currentIndex, 2); + + // Test accepting suggestion. + compare(listView().currentItem.text, "Chrome"); + keyClick(Qt.Key_Enter); + compareElementValue("browserInput", "Chrome"); + // Accept closes popup. + tryVerify(function() { return listView() == null; }); + + // Clear input field, should not trigger popup. + webEngineView.runJavaScript("document.getElementById('browserInput').value = ''"); + compareElementValue("browserInput", ""); + verify(listView() == null); + } + + function test_filterSuggestion() { + webEngineView.loadHtml(html); + verify(webEngineView.waitForLoadSucceeded()); + setFocusToElement("browserInput"); + + // Make sure there is no open popup yet. + verify(!listView()); + + // Filter suggestions. + keyClick(Qt.Key_F); + tryVerify(function() { return listView() != null; }); + compare(listView().count, 2); + verify(!listView().currentItem); + compare(listView().itemAtIndex(0).text, "Firefox"); + compare(listView().itemAtIndex(1).text, "Safari"); + keyClick(Qt.Key_I); + tryVerify(function() { return listView().count == 1; }); + verify(!listView().currentItem); + compare(listView().itemAtIndex(0).text, "Firefox"); + keyClick(Qt.Key_L); + // Mismatch should close popup. + tryVerify(function() { return listView() == null; }); + compareElementValue("browserInput", "fil"); + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml index 780294348..6cb2841ec 100644 --- a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml +++ b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -44,7 +19,7 @@ TestWebEngineView { signalName: "linkHovered" } - onLinkHovered: { + onLinkHovered: function(hoveredUrl) { webEngineView.lastUrl = hoveredUrl } diff --git a/tests/auto/quick/qmltests/data/tst_download.qml b/tests/auto/quick/qmltests/data/tst_download.qml index 019ebd9dc..61a363c39 100644 --- a/tests/auto/quick/qmltests/data/tst_download.qml +++ b/tests/auto/quick/qmltests/data/tst_download.qml @@ -1,34 +1,11 @@ -/**************************************************************************** -** -** 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.5 +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Qt.labs.platform +import Test.util TestWebEngineView { id: webEngineView @@ -41,6 +18,26 @@ TestWebEngineView { property bool cancelDownload: false property var downloadState: [] property var downloadInterruptReason: null + property url downloadUrl: "" + property string suggestedFileName: "" + property string downloadDirectory: "" + property string downloadFileName: "" + property string downloadedPath: "" + property string downloadedSetPath: "" + property int downloadDirectoryChanged: 0 + property int downloadFileNameChanged: 0 + property bool setDirectoryFirst: false + + TempDir { id: tempDir } + + function urlToPath(url) { + var path = url.toString() + if (Qt.platform.os !== "windows") + path = path.replace(/^(file:\/{2})/, "") + else + path = path.replace(/^(file:\/{3})/, "") + return path + } SignalSpy { id: downLoadRequestedSpy @@ -57,25 +54,54 @@ TestWebEngineView { Connections { id: downloadItemConnections ignoreUnknownSignals: true - onStateChanged: downloadState.push(target.state) - onInterruptReasonChanged: downloadInterruptReason = target.interruptReason + function onStateChanged() { + downloadState.push(target.state); + } + function onInterruptReasonChanged() { + downloadInterruptReason = target.interruptReason; + } + function onDownloadDirectoryChanged() { + downloadDirectoryChanged++; + } + function onDownloadFileNameChanged() { + downloadFileNameChanged++; + } } WebEngineProfile { id: testDownloadProfile - onDownloadRequested: { + onDownloadRequested: function(download) { + testDownloadProfile.downloadPath = tempDir.path() downloadState.push(download.state) downloadItemConnections.target = download if (cancelDownload) { download.cancel() } else { totalBytes = download.totalBytes - download.path = "testfile.zip" + + if (downloadedSetPath.length != 0) { + download.path = testDownloadProfile.downloadPath + downloadedSetPath + downloadedPath = download.path + } else { + if (setDirectoryFirst && downloadDirectory.length != 0) + download.downloadDirectory = testDownloadProfile.downloadPath + downloadDirectory + + if (downloadFileName.length != 0) + download.downloadFileName = downloadFileName + + if (!setDirectoryFirst && downloadDirectory.length != 0) + download.downloadDirectory = testDownloadProfile.downloadPath + downloadDirectory + + downloadedPath = download.downloadDirectory + download.downloadFileName + } + download.accept() } + downloadUrl = download.url + suggestedFileName = download.suggestedFileName } - onDownloadFinished: { + onDownloadFinished: function(download) { receivedBytes = download.receivedBytes; } } @@ -92,36 +118,52 @@ TestWebEngineView { downloadItemConnections.target = null downloadState = [] downloadInterruptReason = null + downloadDirectoryChanged = 0 + downloadFileNameChanged = 0 + downloadDirectory = "" + downloadFileName = "" + downloadedPath = "" + downloadedSetPath = "" + setDirectoryFirst = false } function test_downloadRequest() { compare(downLoadRequestedSpy.count, 0) + downloadDirectory = "/test_downloadRequest/"; webEngineView.url = Qt.resolvedUrl("download.zip") downLoadRequestedSpy.wait() compare(downLoadRequestedSpy.count, 1) - compare(downloadState[0], WebEngineDownloadItem.DownloadRequested) + compare(downloadUrl, webEngineView.url) + compare(suggestedFileName, "download.zip") + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested) verify(!downloadInterruptReason) } function test_totalFileLength() { compare(downLoadRequestedSpy.count, 0) + downloadDirectory = "/test_totalFileLength/"; webEngineView.url = Qt.resolvedUrl("download.zip") downLoadRequestedSpy.wait() compare(downLoadRequestedSpy.count, 1) + compare(downloadUrl, webEngineView.url) + compare(suggestedFileName, "download.zip") compare(totalBytes, 325) verify(!downloadInterruptReason) } function test_downloadSucceeded() { compare(downLoadRequestedSpy.count, 0) + downloadDirectory = "/test_downloadSucceeded/"; webEngineView.url = Qt.resolvedUrl("download.zip") downLoadRequestedSpy.wait() compare(downLoadRequestedSpy.count, 1) - compare(downloadState[0], WebEngineDownloadItem.DownloadRequested) - tryCompare(downloadState, "1", WebEngineDownloadItem.DownloadInProgress) + compare(downloadUrl, webEngineView.url) + compare(suggestedFileName, "download.zip") + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested) + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadInProgress) downloadFinishedSpy.wait() compare(totalBytes, receivedBytes) - tryCompare(downloadState, "2", WebEngineDownloadItem.DownloadCompleted) + tryCompare(downloadState, "2", WebEngineDownloadRequest.DownloadCompleted) verify(!downloadInterruptReason) } @@ -131,9 +173,118 @@ TestWebEngineView { webEngineView.url = Qt.resolvedUrl("download.zip") downLoadRequestedSpy.wait() compare(downLoadRequestedSpy.count, 1) + compare(downloadUrl, webEngineView.url) + compare(suggestedFileName, "download.zip") compare(downloadFinishedSpy.count, 1) - tryCompare(downloadState, "1", WebEngineDownloadItem.DownloadCancelled) - tryCompare(webEngineView, "downloadInterruptReason", WebEngineDownloadItem.UserCanceled) + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadCancelled) + tryCompare(webEngineView, "downloadInterruptReason", WebEngineDownloadRequest.UserCanceled) + } + + function test_downloadLocation() { + var tmpPath = urlToPath(StandardPaths.writableLocation(StandardPaths.TempLocation)); + var downloadPath = urlToPath(StandardPaths.writableLocation(StandardPaths.DownloadLocation)); + + testDownloadProfile.downloadPath = tmpPath; + compare(testDownloadProfile.downloadPath, tmpPath); + + testDownloadProfile.downloadPath = downloadPath; + compare(testDownloadProfile.downloadPath, downloadPath); + } + + function test_downloadToDirectoryWithFileName_data() { + return [ + { tag: "setDirectoryFirst", setDirectoryFirst: true }, + { tag: "setFileNameFirst", setDirectoryFirst: false }, + ]; + } + + function test_downloadToDirectoryWithFileName(row) { + compare(downLoadRequestedSpy.count, 0); + compare(downloadDirectoryChanged, 0); + compare(downloadFileNameChanged, 0); + setDirectoryFirst = row.setDirectoryFirst; + downloadDirectory = "/test_downloadToDirectoryWithFileName/"; + downloadFileName = "test.zip"; + webEngineView.url = Qt.resolvedUrl("download.zip"); + downLoadRequestedSpy.wait(); + compare(downLoadRequestedSpy.count, 1); + compare(downloadUrl, webEngineView.url); + compare(suggestedFileName, "download.zip"); + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested); + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadInProgress); + compare(downloadedPath, testDownloadProfile.downloadPath + downloadDirectory + downloadFileName); + compare(downloadDirectoryChanged, 1); + compare(downloadFileNameChanged, 1); + downloadFinishedSpy.wait(); + compare(totalBytes, receivedBytes); + tryCompare(downloadState, "2", WebEngineDownloadRequest.DownloadCompleted); + verify(!downloadInterruptReason); + } + + function test_downloadToDirectoryWithSuggestedFileName() { + // Download file to a custom download directory with suggested file name. + compare(downLoadRequestedSpy.count, 0); + compare(downloadDirectoryChanged, 0); + compare(downloadFileNameChanged, 0); + downloadDirectory = "/test_downloadToDirectoryWithSuggestedFileName/"; + webEngineView.url = Qt.resolvedUrl("download.zip"); + downLoadRequestedSpy.wait(); + compare(downLoadRequestedSpy.count, 1); + compare(downloadUrl, webEngineView.url); + compare(suggestedFileName, "download.zip"); + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested); + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadInProgress); + compare(downloadedPath, testDownloadProfile.downloadPath + downloadDirectory + "download.zip"); + compare(downloadDirectoryChanged, 1); + compare(downloadFileNameChanged, 0); + downloadFinishedSpy.wait(); + compare(totalBytes, receivedBytes); + tryCompare(downloadState, "2", WebEngineDownloadRequest.DownloadCompleted); + verify(!downloadInterruptReason); + + // Download the same file to another directory with suggested file name. + // The downloadFileNameChanged signal should not be emitted. + downLoadRequestedSpy.clear(); + compare(downLoadRequestedSpy.count, 0); + downloadDirectoryChanged = 0; + downloadFileNameChanged = 0; + downloadDirectory = "/test_downloadToDirectoryWithSuggestedFileName1/"; + webEngineView.url = Qt.resolvedUrl("download.zip"); + downLoadRequestedSpy.wait(); + compare(downLoadRequestedSpy.count, 1); + compare(downloadUrl, webEngineView.url); + compare(suggestedFileName, "download.zip"); + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested); + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadInProgress); + compare(downloadedPath, testDownloadProfile.downloadPath + downloadDirectory + "download.zip"); + compare(downloadDirectoryChanged, 1); + compare(downloadFileNameChanged, 0); + downloadFinishedSpy.wait(); + compare(totalBytes, receivedBytes); + tryCompare(downloadState, "2", WebEngineDownloadRequest.DownloadCompleted); + verify(!downloadInterruptReason); + + // Download same file to same directory second time -> file name should be unified. + // The downloadFileNameChanged signal should be emitted. + downLoadRequestedSpy.clear(); + compare(downLoadRequestedSpy.count, 0); + downloadDirectoryChanged = 0; + downloadFileNameChanged = 0; + downloadDirectory = "/test_downloadToDirectoryWithSuggestedFileName1/"; + webEngineView.url = Qt.resolvedUrl("download.zip"); + downLoadRequestedSpy.wait(); + compare(downLoadRequestedSpy.count, 1); + compare(downloadUrl, webEngineView.url); + compare(suggestedFileName, "download.zip"); + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested); + tryCompare(downloadState, "1", WebEngineDownloadRequest.DownloadInProgress); + compare(downloadedPath, testDownloadProfile.downloadPath + downloadDirectory + "download (1).zip"); + compare(downloadDirectoryChanged, 1); + compare(downloadFileNameChanged, 1); + downloadFinishedSpy.wait(); + compare(totalBytes, receivedBytes); + tryCompare(downloadState, "2", WebEngineDownloadRequest.DownloadCompleted); + verify(!downloadInterruptReason); } } } diff --git a/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml new file mode 100644 index 000000000..c22bd44c2 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml @@ -0,0 +1,67 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +Item { + id: parentItem + width: 400 + height: 300 + + Rectangle { + id: draggableDownUnder + color: "wheat" + width: 350 + height: 250 + + DragHandler { id: dragHandler } + } + + TestWebEngineView { + id: webEngineView + width: 300 + height: 250 + + property var testUrl: Qt.resolvedUrl("test4.html") + + SignalSpy { + id: scrollPositionSpy + target: webEngineView + signalName: "onScrollPositionChanged" + } + + SignalSpy { + id: dragActiveSpy + target: dragHandler + signalName: "activeChanged" + } + + TestCase { + id: testCase + name: "KeepMouseGrabDuringScrolling" + when: windowShown + + function test_scroll() { + webEngineView.url = Qt.resolvedUrl("test4.html"); + verify(webEngineView.waitForLoadSucceeded()); + + mousePress(webEngineView, 295, 20); + mouseMove(webEngineView, 295, 200); + mouseRelease(webEngineView, 295, 200); + + // WebEngineView scrolled if the scrollbar was visible. + // But on macOS, the scrollbar is hidden, so text gets selected. + tryVerify(function() { + return (scrollPositionSpy.count === 1 && webEngineView.scrollPosition.y > 100) + || webEngineView.getTextSelection().length > 0; + }); + + // DragHandler didn't take over and drag + compare(dragActiveSpy.count, 0); + compare(draggableDownUnder.y, 0); + } + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index 50a412384..15f116e5d 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -1,89 +1,32 @@ -/**************************************************************************** -** -** 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: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.3 -import QtWebEngine.testsupport 1.0 -import QtQuick.Window 2.0 +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Test.util +import "../../qmltests/data" TestWebEngineView { id: webEngineView width: 200 height: 400 - testSupport: WebEngineTestSupport { - property var errorPageLoadStatus: null + TempDir { id: tempDir } - function waitForErrorPageLoadSucceeded() { - var success = _waitFor(function() { return testSupport.errorPageLoadStatus == WebEngineView.LoadSucceededStatus }) - testSupport.errorPageLoadStatus = null - return success - } + property QtObject defaultProfile: WebEngineProfile { + offTheRecord: true + } - errorPage.onLoadingChanged: { - errorPageLoadStatus = loadRequest.status - } + property QtObject nonOTRProfile: WebEngineProfile { + persistentStoragePath: tempDir.path() + '/WebEngineFavicon' + offTheRecord: false } function removeFaviconProviderPrefix(url) { 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 @@ -96,19 +39,29 @@ TestWebEngineView { } TestCase { - id: test + id: testCase name: "WebEngineFavicon" when: windowShown function init() { // It is worth to restore the initial state with loading a blank page before all test functions. - webEngineView.url = 'about:blank' - verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.clear() + webEngineView.url = 'about:blank'; + verify(webEngineView.waitForLoadSucceeded()); + iconChangedSpy.clear(); + webEngineView.settings.touchIconsEnabled = false; + webEngineView.settings.autoLoadIconsForPage = true; } - function test_faviconLoad() { + function test_faviconLoad_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_faviconLoad(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("favicon.html") @@ -118,11 +71,20 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) - compare(favicon.width, 48) - compare(favicon.height, 48) + tryCompare(favicon, "status", Image.Ready) + compare(favicon.width, 32) + compare(favicon.height, 32) + } + + function test_faviconLoadEncodedUrl_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; } - function test_faviconLoadEncodedUrl() { + function test_faviconLoadEncodedUrl(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("favicon2.html?favicon=load should work with#whitespace!") @@ -132,11 +94,94 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) - compare(favicon.width, 16) - compare(favicon.height, 16) + tryCompare(favicon, "status", Image.Ready) + compare(favicon.width, 32) + compare(favicon.height, 32) + } + + function test_faviconLoadAfterHistoryNavigation_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_faviconLoadAfterHistoryNavigation(row) { + webEngineView.profile = row.profile + compare(iconChangedSpy.count, 0) + + var iconUrl + + webEngineView.url = Qt.resolvedUrl("favicon.html") + verify(webEngineView.waitForLoadSucceeded()) + tryCompare(iconChangedSpy, "count", 1) + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, Qt.resolvedUrl("icons/favicon.png")) + + iconChangedSpy.clear() + webEngineView.url = Qt.resolvedUrl("favicon-shortcut.html") + verify(webEngineView.waitForLoadSucceeded()) + tryCompare(iconChangedSpy, "count", 2) + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, Qt.resolvedUrl("icons/qt32.ico")) + + iconChangedSpy.clear() + webEngineView.goBack(); + verify(webEngineView.waitForLoadSucceeded()) + tryCompare(iconChangedSpy, "count", 2) + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, Qt.resolvedUrl("icons/favicon.png")) + + iconChangedSpy.clear() + webEngineView.goForward(); + verify(webEngineView.waitForLoadSucceeded()) + tryCompare(iconChangedSpy, "count", 2) + iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, Qt.resolvedUrl("icons/qt32.ico")) + } + + function test_faviconLoadPushState_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_faviconLoadPushState(row) { + webEngineView.profile = row.profile; + compare(iconChangedSpy.count, 0); + + var iconUrl; + + webEngineView.url = Qt.resolvedUrl("favicon.html"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(iconChangedSpy, "count", 1); + iconUrl = removeFaviconProviderPrefix(webEngineView.icon); + compare(iconUrl, Qt.resolvedUrl("icons/favicon.png")); + + iconChangedSpy.clear(); + + // pushState() is a same document navigation and should not reset or + // update favicon. + compare(webEngineView.history.items.rowCount(), 1); + runJavaScript("history.pushState('', '')"); + tryVerify(function() { return webEngineView.history.items.rowCount() === 2; }); + + // Favicon change is not expected. + compare(iconChangedSpy.count, 0); + iconUrl = removeFaviconProviderPrefix(webEngineView.icon); + compare(iconUrl, Qt.resolvedUrl("icons/favicon.png")); + } + + function test_noFavicon_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; } - function test_noFavicon() { + function test_noFavicon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("test1.html") @@ -149,7 +194,15 @@ TestWebEngineView { compare(iconUrl, Qt.resolvedUrl("")) } - function test_aboutBlank() { + function test_aboutBlank_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_aboutBlank(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("about:blank") @@ -162,7 +215,15 @@ TestWebEngineView { compare(iconUrl, Qt.resolvedUrl("")) } - function test_unavailableFavicon() { + function test_unavailableFavicon_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_unavailableFavicon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("favicon-unavailable.html") @@ -175,15 +236,22 @@ TestWebEngineView { compare(iconUrl, Qt.resolvedUrl("")) } - function test_errorPageEnabled() { - WebEngine.settings.errorPageEnabled = true + function test_errorPageEnabled_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_errorPageEnabled(row) { + webEngineView.profile = row.profile + webEngineView.settings.errorPageEnabled = true compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("http://url.invalid") webEngineView.url = url verify(webEngineView.waitForLoadFailed(20000)) - verify(webEngineView.testSupport.waitForErrorPageLoadSucceeded()) compare(iconChangedSpy.count, 0) @@ -191,8 +259,16 @@ TestWebEngineView { compare(iconUrl, Qt.resolvedUrl("")) } - function test_errorPageDisabled() { - WebEngine.settings.errorPageEnabled = false + function test_errorPageDisabled_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_errorPageDisabled(row) { + webEngineView.profile = row.profile + webEngineView.settings.errorPageEnabled = false compare(iconChangedSpy.count, 0) @@ -206,7 +282,15 @@ TestWebEngineView { compare(iconUrl, Qt.resolvedUrl("")) } - function test_bestFavicon() { + function test_bestFavicon_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_bestFavicon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url, iconUrl @@ -220,6 +304,7 @@ TestWebEngineView { iconUrl = removeFaviconProviderPrefix(webEngineView.icon) // Touch icon is ignored compare(iconUrl, Qt.resolvedUrl("icons/qt32.ico")) + tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 32) compare(favicon.height, 32) @@ -229,23 +314,25 @@ TestWebEngineView { webEngineView.url = url verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - verify(iconChangedSpy.count >= 1) + tryCompare(iconChangedSpy, "count", 2) iconUrl = removeFaviconProviderPrefix(webEngineView.icon) - // If the icon URL is empty we have to wait for - // the second iconChanged signal that propagates the expected URL - if (iconUrl == Qt.resolvedUrl("")) { - tryCompare(iconChangedSpy, "count", 2) - iconUrl = removeFaviconProviderPrefix(webEngineView.icon) - } + // If touch icon is disabled, FaviconHandler propagates the icon closest to size 16x16 + compare(iconUrl, Qt.resolvedUrl("icons/qt32.ico")) + tryCompare(favicon, "status", Image.Ready) + compare(favicon.width, 32) + compare(favicon.height, 32) + } - compare(iconUrl, Qt.resolvedUrl("icons/qt144.png")) - compare(favicon.width, 144) - compare(favicon.height, 144) + function test_touchIcon_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; } - function test_touchIcon() { + function test_touchIcon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("favicon-touch.html") @@ -259,7 +346,7 @@ TestWebEngineView { compare(favicon.width, 0) compare(favicon.height, 0) - WebEngine.settings.touchIconsEnabled = true + webEngineView.settings.touchIconsEnabled = true url = Qt.resolvedUrl("favicon-touch.html") webEngineView.url = url @@ -269,11 +356,20 @@ TestWebEngineView { iconUrl = removeFaviconProviderPrefix(webEngineView.icon) compare(iconUrl, Qt.resolvedUrl("icons/qt144.png")) compare(iconChangedSpy.count, 1) + tryCompare(favicon, "status", Image.Ready) compare(favicon.width, 144) compare(favicon.height, 144) } - function test_multiIcon() { + function test_multiIcon_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_multiIcon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) var url = Qt.resolvedUrl("favicon-multi.html") @@ -282,62 +378,25 @@ TestWebEngineView { iconChangedSpy.wait() compare(iconChangedSpy.count, 1) - compare(favicon.width, 64) - compare(favicon.height, 64) + tryCompare(favicon, "status", Image.Ready) + compare(favicon.width, 32) + compare(favicon.height, 32) } - function test_faviconProvider_data() { + function test_dynamicFavicon_data() { return [ - { tag: "multi 8x8", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 8, value: 16 }, - { tag: "multi 16x16", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 16, value: 16 }, - { tag: "multi 17x17", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 17, value: 32 }, - { tag: "multi 31x31", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 31, value: 32 }, - { tag: "multi 32x32", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 32, value: 32 }, - { tag: "multi 33x33", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 33, value: 64 }, - { tag: "multi 64x64", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 64, value: 64 }, - { tag: "multi 128x128", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 128, value: 128 }, - { tag: "multi 255x255", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 255, value: 255 }, - { tag: "multi 256x256", url: Qt.resolvedUrl("favicon-multi-gray.html"), size: 256, value: 255 }, - { tag: "candidate 8x8", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 8, value: 16 }, - { tag: "candidate 16x16", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 16, value: 16 }, - { tag: "candidate 17x17", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 17, value: 32 }, - { tag: "candidate 31x31", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 31, value: 32 }, - { tag: "candidate 32x32", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 32, value: 32 }, - { tag: "candidate 33x33", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 33, value: 64 }, - { tag: "candidate 64x64", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 64, value: 64 }, - { tag: "candidate 128x128", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 128, value: 128 }, - { tag: "candidate 255x255", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 255, value: 255 }, - { tag: "candidate 256x256", url: Qt.resolvedUrl("favicon-candidates-gray.html"), size: 256, value: 255 }, + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, ]; } - function test_faviconProvider(row) { - var faviconImage = Qt.createQmlObject(" - import QtQuick 2.5\n - Image { sourceSize: Qt.size(width, height) }", test) - + function test_dynamicFavicon(row) { + webEngineView.profile = row.profile compare(iconChangedSpy.count, 0) - webEngineView.url = row.url - verify(webEngineView.waitForLoadSucceeded()) - - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) - - faviconImage.width = row.size / Screen.devicePixelRatio - faviconImage.height = row.size / Screen.devicePixelRatio - faviconImage.source = webEngineView.icon - - var pixel = getFaviconPixel(faviconImage); - compare(pixel[0], row.value) - - faviconImage.destroy() - } - - function test_dynamicFavicon() { var faviconImage = Qt.createQmlObject(" - import QtQuick 2.5\n - Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", test) + import QtQuick\n + Image { width: 16; height: 16; sourceSize: Qt.size(width, height); objectName: 'image' }", testCase) faviconImage.source = Qt.binding(function() { return webEngineView.icon; }); var colors = [ @@ -356,7 +415,7 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); tryCompare(iconChangedSpy, "count", 1); - pixel = getFaviconPixel(faviconImage); + pixel = getItemPixel(faviconImage); compare(pixel[0], 0); compare(pixel[1], 0); compare(pixel[2], 0); @@ -367,7 +426,7 @@ TestWebEngineView { tryCompare(faviconImage, "source", "image://favicon/data:image/png;base64," + colors[i]["url"]); compare(iconChangedSpy.count, 1); - pixel = getFaviconPixel(faviconImage); + pixel = getItemPixel(faviconImage); compare(pixel[0], colors[i]["r"]); compare(pixel[1], colors[i]["g"]); compare(pixel[2], colors[i]["b"]); @@ -376,9 +435,17 @@ TestWebEngineView { faviconImage.destroy() } - function test_touchIconWithSameURL() + function test_touchIconWithSameURL_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_touchIconWithSameURL(row) { - WebEngine.settings.touchIconsEnabled = false; + webEngineView.profile = row.profile; + compare(iconChangedSpy.count, 0); var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="; @@ -408,5 +475,53 @@ TestWebEngineView { tryCompare(iconChangedSpy, "count", 1); verify(!webEngineView.icon.toString().replace(/^image:\/\/favicon\//, '')); } + + function test_iconsDisabled_data() { + return [ + { tag: "misc", url: Qt.resolvedUrl("favicon-misc.html") }, + { tag: "shortcut", url: Qt.resolvedUrl("favicon-shortcut.html") }, + { tag: "single", url: Qt.resolvedUrl("favicon-single.html") }, + { tag: "touch", url: Qt.resolvedUrl("favicon-touch.html") }, + { tag: "unavailable", url: Qt.resolvedUrl("favicon-unavailable.html") }, + ]; + } + + function test_iconsDisabled(row) { + webEngineView.settings.autoLoadIconsForPage = false + webEngineView.profile = defaultProfile + compare(iconChangedSpy.count, 0) + + webEngineView.url = row.url + verify(webEngineView.waitForLoadSucceeded()) + + compare(iconChangedSpy.count, 0) + + var iconUrl = webEngineView.icon + compare(iconUrl, Qt.resolvedUrl("")) + } + + function test_touchIconsEnabled_data() { + return [ + { tag: "misc", url: Qt.resolvedUrl("favicon-misc.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, + { tag: "shortcut", url: Qt.resolvedUrl("favicon-shortcut.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, + { tag: "single", url: Qt.resolvedUrl("favicon-single.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt32.ico") }, + { tag: "touch", url: Qt.resolvedUrl("favicon-touch.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, + ]; + } + + function test_touchIconsEnabled(row) { + webEngineView.settings.touchIconsEnabled = true + webEngineView.profile = defaultProfile + compare(iconChangedSpy.count, 0) + + webEngineView.url = row.url + verify(webEngineView.waitForLoadSucceeded()) + + iconChangedSpy.wait() + compare(iconChangedSpy.count, 1) + + var iconUrl = removeFaviconProviderPrefix(webEngineView.icon) + compare(iconUrl, row.expectedIconUrl) + } } } diff --git a/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml new file mode 100644 index 000000000..284390619 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_faviconDatabase.qml @@ -0,0 +1,216 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Test.util +import "../../qmltests/data" + +TestWebEngineView { + id: webEngineView + width: 200 + height: 400 + + TempDir { id: tempDir } + + property QtObject defaultProfile: WebEngineProfile { + offTheRecord: true + } + + property QtObject nonOTRProfile: WebEngineProfile { + persistentStoragePath: tempDir.path() + '/WebEngineFavicon' + offTheRecord: false + } + + function getFaviconPixel(faviconImage) { + var grabImage = Qt.createQmlObject(" + import QtQuick\n + Image { }", testCase) + var faviconCanvas = Qt.createQmlObject(" + import QtQuick\n + Canvas { }", testCase) + + testCase.tryVerify(function() { return faviconImage.status == Image.Ready }); + faviconImage.grabToImage(function(result) { + grabImage.source = result.url + }); + testCase.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 + signalName: "iconChanged" + } + + TestCase { + id: testCase + name: "WebEngineFaviconDatabase" + when: windowShown + + function init() { + // It is worth to restore the initial state with loading a blank page before all test functions. + webEngineView.url = 'about:blank'; + verify(webEngineView.waitForLoadSucceeded()); + iconChangedSpy.clear(); + webEngineView.settings.touchIconsEnabled = false; + webEngineView.settings.autoLoadIconsForPage = true; + } + + function cleanupTestCase() { + tempDir.removeRecursive(nonOTRProfile.persistentStoragePath); + } + + function test_iconDatabase_data() { + return [ + { tag: "OTR", profile: defaultProfile }, + { tag: "non-OTR", profile: nonOTRProfile }, + ]; + } + + function test_iconDatabase(row) + { + if (Screen.devicePixelRatio !== 1.0) + skip("This test is not supported on High DPI screens."); + + webEngineView.profile = row.profile; + compare(iconChangedSpy.count, 0); + + var faviconImage = Qt.createQmlObject(" + import QtQuick\n + Image { width: 16; height: 16; sourceSize: Qt.size(width, height); cache: false; }", testCase); + + var pixel; + compare(iconChangedSpy.count, 0); + + webEngineView.url = Qt.resolvedUrl("favicon.html"); // favicon.png -> 165 + verify(webEngineView.waitForLoadSucceeded()); + + iconChangedSpy.wait(); + compare(iconChangedSpy.count, 1); + + var previousIcon = webEngineView.icon; + iconChangedSpy.clear(); + + webEngineView.url = Qt.resolvedUrl("favicon-shortcut.html"); // qt32.ico -> 251 + verify(webEngineView.waitForLoadSucceeded()); + + tryCompare(iconChangedSpy, "count", 2); + + // Icon database is not accessible with OTR profile. + faviconImage.source = previousIcon; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], webEngineView.profile.offTheRecord ? 0 : 165); + + // This should pass with OTR too because icon is requested for the current page. + faviconImage.source = "image://favicon/" + Qt.resolvedUrl("favicon-shortcut.html"); + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 251); + + faviconImage.source = "image://favicon/" + Qt.resolvedUrl("favicon.html"); + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], webEngineView.profile.offTheRecord ? 0 : 165); + + faviconImage.destroy(); + webEngineView.profile = defaultProfile; + } + + function test_iconDatabaseMultiView() + { + if (Screen.devicePixelRatio !== 1.0) + skip("This test is not supported on High DPI screens."); + + var pixel; + + var faviconImage = Qt.createQmlObject(" + import QtQuick\n + Image { width: 16; height: 16; sourceSize: Qt.size(width, height); cache: false; }", testCase); + + var webEngineView1 = Qt.createQmlObject(" + import QtWebEngine\n + import Test.util\n + import '../../qmltests/data'\n + TestWebEngineView {\n + TempDir { id: tempDir } + profile: WebEngineProfile {\n + persistentStoragePath: tempDir.path() + '/WebEngineFavicon1'\n + offTheRecord: false\n + }\n + }", testCase); + + var webEngineView2 = Qt.createQmlObject(" + import QtWebEngine\n + import Test.util\n + import '../../qmltests/data'\n + TestWebEngineView {\n + TempDir { id: tempDir } + profile: WebEngineProfile {\n + persistentStoragePath: tempDir.path() + '/WebEngineFavicon2'\n + offTheRecord: false\n + }\n + }", testCase); + + // Moke sure the icons have not been stored in the database yet. + var icon1 = "image://favicon/" + Qt.resolvedUrl("icons/favicon.png"); + faviconImage.source = icon1; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 0); + + var icon2 = "image://favicon/" + Qt.resolvedUrl("icons/qt32.ico"); + faviconImage.source = icon2; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 0); + + webEngineView1.url = Qt.resolvedUrl("favicon.html"); // favicon.png -> 165 + verify(webEngineView1.waitForLoadSucceeded()); + tryCompare(webEngineView1, "icon", icon1); + webEngineView1.url = "about:blank"; + verify(webEngineView1.waitForLoadSucceeded()); + + webEngineView2.url = Qt.resolvedUrl("favicon-shortcut.html"); // qt32.ico -> 251 + verify(webEngineView2.waitForLoadSucceeded()); + tryCompare(webEngineView2, "icon", icon2); + webEngineView2.url = "about:blank"; + verify(webEngineView2.waitForLoadSucceeded()); + + faviconImage.source = ""; + compare(webEngineView1.icon, ""); + compare(webEngineView2.icon, ""); + + faviconImage.source = icon1; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 165); + + faviconImage.source = icon2; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 251); + + faviconImage.source = "image://favicon/file:///does.not.exist.ico"; + pixel = getFaviconPixel(faviconImage); + compare(pixel[0], 0); + + webEngineView1.destroy(); + webEngineView2.destroy(); + faviconImage.destroy(); + + tempDir.removeRecursive(webEngineView1.profile.persistentStoragePath) + tempDir.removeRecursive(webEngineView2.profile.persistentStoragePath) + } + } +} + diff --git a/tests/auto/quick/qmltests/data/tst_faviconDownload.qml b/tests/auto/quick/qmltests/data/tst_faviconDownload.qml deleted file mode 100644 index 406dfa3ea..000000000 --- a/tests/auto/quick/qmltests/data/tst_faviconDownload.qml +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** 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: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.3 - -TestWebEngineView { - id: webEngineView - width: 200 - height: 400 - - function removeFaviconProviderPrefix(url) { - return url.toString().substring(16) - } - - SignalSpy { - id: iconChangedSpy - target: webEngineView - signalName: "iconChanged" - } - - TestCase { - id: test - name: "WebEngineFaviconDownload" - - function init() { - WebEngine.settings.autoLoadIconsForPage = true - WebEngine.settings.touchIconsEnabled = false - - if (webEngineView.icon != '') { - // If this is not the first test, then load a blank page without favicon, restoring the initial state. - webEngineView.url = 'about:blank' - verify(webEngineView.waitForLoadSucceeded()) - iconChangedSpy.wait() - } - - iconChangedSpy.clear() - } - - function cleanupTestCase() { - WebEngine.settings.autoLoadIconsForPage = true - WebEngine.settings.touchIconsEnabled = false - } - - function test_downloadIconsDisabled_data() { - return [ - { tag: "misc", url: Qt.resolvedUrl("favicon-misc.html") }, - { tag: "shortcut", url: Qt.resolvedUrl("favicon-shortcut.html") }, - { tag: "single", url: Qt.resolvedUrl("favicon-single.html") }, - { tag: "touch", url: Qt.resolvedUrl("favicon-touch.html") }, - { tag: "unavailable", url: Qt.resolvedUrl("favicon-unavailable.html") }, - ]; - } - - function test_downloadIconsDisabled(row) { - WebEngine.settings.autoLoadIconsForPage = false - - compare(iconChangedSpy.count, 0) - - webEngineView.url = row.url - verify(webEngineView.waitForLoadSucceeded()) - - compare(iconChangedSpy.count, 0) - - var iconUrl = webEngineView.icon - compare(iconUrl, Qt.resolvedUrl("")) - } - - function test_downloadTouchIconsEnabled_data() { - return [ - { tag: "misc", url: Qt.resolvedUrl("favicon-misc.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, - { tag: "shortcut", url: Qt.resolvedUrl("favicon-shortcut.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, - { tag: "single", url: Qt.resolvedUrl("favicon-single.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt32.ico") }, - { tag: "touch", url: Qt.resolvedUrl("favicon-touch.html"), expectedIconUrl: Qt.resolvedUrl("icons/qt144.png") }, - ]; - } - - function test_downloadTouchIconsEnabled(row) { - WebEngine.settings.touchIconsEnabled = true - - compare(iconChangedSpy.count, 0) - - webEngineView.url = row.url - verify(webEngineView.waitForLoadSucceeded()) - - iconChangedSpy.wait() - compare(iconChangedSpy.count, 1) - - var iconUrl = removeFaviconProviderPrefix(webEngineView.icon) - compare(iconUrl, row.expectedIconUrl) - } - } -} - diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml index 655789bb3..a7b59b2e9 100644 --- a/tests/auto/quick/qmltests/data/tst_filePicker.qml +++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml @@ -1,41 +1,23 @@ -/**************************************************************************** -** -** 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: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.2 -import "../mock-delegates/TestParams" 1.0 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import "../../qmltests/data" +import "../mock-delegates/TestParams" TestWebEngineView { id: webEngineView width: 400 height: 300 + function driveLetter() { + if (Qt.platform.os !== "windows") + return ""; + return "C:/"; + } + SignalSpy { id: titleSpy target: webEngineView @@ -48,6 +30,7 @@ TestWebEngineView { } TestCase { + id: testCase name: "WebEngineViewSingleFileUpload" when: windowShown @@ -55,13 +38,14 @@ TestWebEngineView { FilePickerParams.filePickerOpened = false FilePickerParams.selectFiles = false FilePickerParams.selectedFilesUrl = [] + FilePickerParams.nameFilters = [] titleSpy.clear() terminationSpy.clear() } function cleanup() { // Test that the render process doesn't crash, and make sure if it does it does so now. - wait(1000) + wait(100) verify(terminationSpy.count == 0, "Render process didn't self terminate") // FIXME: Almost every second url loading progress does get stuck at about 90 percent, so the loadFinished signal won't arrive. @@ -70,16 +54,61 @@ TestWebEngineView { webEngineView.waitForLoadSucceeded() } - function test_acceptSingleFileSelection() { - webEngineView.url = Qt.resolvedUrl("singlefileupload.html") - verify(webEngineView.waitForLoadSucceeded()) + function test_acceptSingleFileSelection_data() { + return [ + { tag: "test.txt", input: "test.txt", expected: "Failed to Upload" }, + { tag: driveLetter() + "/test.txt", input: driveLetter() + "/test.txt", expected: "test.txt" }, + { tag: driveLetter() + "/tést.txt", input: driveLetter() + "/tést.txt", expected: "tést.txt" }, + { tag: driveLetter() + "/t%65st.txt", input: driveLetter() + "/t%65st.txt", expected: "t%65st.txt" }, + { tag: "file:///" + driveLetter() + "test.txt", input: "file:///" + driveLetter() + "test.txt", expected: "test.txt" }, + { tag: "file:///" + driveLetter() + "tést.txt", input: "file:///" + driveLetter() + "tést.txt", expected: "tést.txt" }, + { tag: "file:///" + driveLetter() + "t%65st.txt", input: "file:///" + driveLetter() + "t%65st.txt", expected: "t%65st.txt" }, + { tag: "file://" + driveLetter() + "test.txt", input: "file://" + driveLetter() + "test.txt", expected: "Failed to Upload" }, + { tag: "file:/" + driveLetter() + "test.txt", input: "file:/" + driveLetter() + "test.txt", expected: "test.txt"}, + { tag: "file:test//test.txt", input: "file:test//test.txt", expected: "Failed to Upload" }, + { tag: "http://test.txt", input: "http://test.txt", expected: "Failed to Upload" }, + { tag: "qrc:/test.txt", input: "qrc:/test.txt", expected: "Failed to Upload" }, + ]; + } - FilePickerParams.selectFiles = true - FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("test1.html")) + function test_acceptSingleFileSelection(row) { + var expectedFileName; - keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog. - tryCompare(FilePickerParams, "filePickerOpened", true) - tryCompare(webEngineView, "title", "test1.html") + // Default dialog + webEngineView.url = Qt.resolvedUrl("singlefileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl.push(row.input); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + + + // Custom dialog + var finished = false; + + function acceptedFileHandler(request) { + request.accepted = true; + request.dialogAccept([row.input]); + finished = true; + } + + webEngineView.fileDialogRequested.connect(acceptedFileHandler); + webEngineView.url = Qt.resolvedUrl("singlefileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryVerify(function() { return finished; }); + tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + webEngineView.fileDialogRequested.disconnect(acceptedFileHandler); } function test_acceptMultipleFilesSelection() { @@ -99,12 +128,28 @@ TestWebEngineView { webEngineView.url = Qt.resolvedUrl("directoryupload.html") verify(webEngineView.waitForLoadSucceeded()) + webEngineView.runJavaScript( + "let relativePathCount = 0;" + + "document.getElementById('upfile').addEventListener('change', function(event) {" + + " let files = event.target.files;" + + " for (let i = 0; i < files.length; i++) {" + + " if (files[i].webkitRelativePath != '')" + + " relativePathCount++;" + + " }" + + "}, false);") + FilePickerParams.selectFiles = true FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("../data")) - keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog. - tryCompare(FilePickerParams, "filePickerOpened", true) - tryCompare(webEngineView, "title", "data") + keyClick(Qt.Key_Enter) // Focus is on the button. Open FileDialog. + tryCompare(FilePickerParams, "directoryPickerOpened", true) + // Check that the title is a file list (eg. "test1.html,test2.html") + tryVerify(function() { return webEngineView.title.match("^([^,]+,)+[^,]+$"); }) + + var relativePathCount = 0; + runJavaScript("relativePathCount", function(result) { relativePathCount = result; }); + // The number of files in data directory may vary + tryVerify(function() { return relativePathCount > 0; }); } function test_reject() { @@ -116,5 +161,137 @@ TestWebEngineView { wait(100) compare(titleSpy.count, 0) } + + function test_acceptMultipleFilesWithCustomDialog_data() { + return [ + { tag: "path", input: [driveLetter() + "/test1.txt", driveLetter() + "/test2.txt"], expectedValue: "test1.txt,test2.txt" }, + { tag: "file", input: ["file:///" + driveLetter() + "test1.txt", "file:/" + driveLetter() + "test2.txt"], expectedValue: "test1.txt,test2.txt" }, + { tag: "mixed", input: ["file:///" + driveLetter() + "test1.txt", driveLetter() + "/test2.txt"], expectedValue: "test1.txt,test2.txt" }, + ]; + } + + function test_acceptMultipleFilesWithCustomDialog(row) { + // Default dialog + webEngineView.url = Qt.resolvedUrl("multifileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl = row.input; + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + tryCompare(webEngineView, "title", row.expectedValue); + + + // Custom dialog + var finished = false; + + function acceptedFileHandler(request) { + request.accepted = true; + request.dialogAccept(row.input); + finished = true; + } + + webEngineView.fileDialogRequested.connect(acceptedFileHandler); + webEngineView.url = Qt.resolvedUrl("multifileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryVerify(function() { return finished; }); + tryCompare(webEngineView, "title", row.expectedValue); + webEngineView.fileDialogRequested.disconnect(acceptedFileHandler); + } + + function test_acceptFileOnWindows_data() { + return [ + { tag: "C:test.txt", input: "C:test.txt", expected: "Failed to Upload"}, + { tag: "C:test:txt", input: "C:test:txt", expected: "Failed to Upload"}, + { tag: "C:/test.txt", input: "C:/test.txt", expected: "test.txt"}, + { tag: "C:\\test.txt", input: "C:\\test.txt", expected: "test.txt"}, + { tag: "C:\\Documents and Settings\\test\\test.txt", input: "C:\\Documents and Settings\\test\\test.txt", expected: "test.txt"}, + { tag: "\\\\applib\\products\\a%2Db\\ abc%5F9\\t.est\\test.txt", input: "\\\\applib\\products\\a%2Db\\ abc%5F9\\t.est\\test.txt", expected: "test.txt"}, + { tag: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", input: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", expected: "test.txt"}, + { tag: "file://applib/products/a-b/abc_1/t.est/test.txt", input: "file://applib/products/a-b/abc_1/t.est/test.txt", expected: "test.txt"}, + { tag: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", input: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", expected: "test.txt"}, + { tag: "file:C:/test.txt", input: "file:C:/test.txt", expected: "test.txt"}, + { tag: "file:/C:/test.txt", input: "file:/C:/test.txt", expected: "test.txt"}, + { tag: "file://C:/test.txt", input: "file://C:/test.txt", expected: "Failed to Upload"}, + { tag: "file:///C:test.txt", input: "file:///C:test.txt", expected: "Failed to Upload"}, + { tag: "file:///C:/test.txt", input: "file:///C:/test.txt", expected: "test.txt"}, + { tag: "file:///C:\\test.txt", input: "file:///C:\\test.txt", expected: "test.txt"}, + { tag: "file:\\//C:/test.txt", input: "file:\\//C:/test.txt", expected: "test.txt"}, + { tag: "file:\\\\/C:\\test.txt", input: "file:\\\\/C:\\test.txt", expected: "test.txt"}, + { tag: "\\\\?\\C:/test.txt", input: "\\\\?\\C:/test.txt", expected: "test.txt"}, + ]; + } + + function test_acceptFileOnWindows(row) { + if (Qt.platform.os !== "windows") + skip("Windows-only test"); + + // Default dialog + webEngineView.url = Qt.resolvedUrl("singlefileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl.push(row.input); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + + + // Custom dialog + var finished = false; + + function acceptedFileHandler(request) { + request.accepted = true; + request.dialogAccept([row.input]); + finished = true; + } + + webEngineView.fileDialogRequested.connect(acceptedFileHandler); + webEngineView.url = Qt.resolvedUrl("singlefileupload.html"); + verify(webEngineView.waitForLoadSucceeded()); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryVerify(function() { return finished; }); + tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + webEngineView.fileDialogRequested.disconnect(acceptedFileHandler); + } + + function test_acceptFileTypes_data() { + return [ + { tag: "CustomSuffix", input: ".pug", expected: ".pug", exactMatch: false}, + { tag: "CustomMime", input: "dog/pug", expected: "Accepted types ()", exactMatch: true}, + { tag: "CustomGlob", input: "dog/*", expected: "Accepted types ()", exactMatch: true}, + { tag: "Invalid", input: "---", expected: undefined, exactMatch: true}, + { tag: "Jpeg", input: "image/jpeg", expected: ".jpeg", exactMatch: false} + ]; + } + + function test_acceptFileTypes(row) { + var expectedFileName; + + webEngineView.url = Qt.resolvedUrl("accepttypes.html"); + verify(webEngineView.waitForLoadSucceeded()); + + webEngineView.runJavaScript("setAcceptType('" + row.input + "');"); + tryCompare(webEngineView, "title", row.input); + + keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + + if (row.exactMatch) + compare(FilePickerParams.nameFilters[0], row.expected); + else + verify(FilePickerParams.nameFilters[0].includes(row.expected)); + } } } diff --git a/tests/auto/quick/qmltests/data/tst_filesystem.qml b/tests/auto/quick/qmltests/data/tst_filesystem.qml new file mode 100644 index 000000000..fa0da4457 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_filesystem.qml @@ -0,0 +1,124 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Test.util +import "../../qmltests/data" +import "../mock-delegates/TestParams" + + +TestWebEngineView { + id: webEngineView + width: 400 + height: 300 + property var logs: [] + property bool accessRequested: false + property url file: tempDir.pathUrl('file.txt') + + onJavaScriptConsoleMessage: function(level, message, lineNumber, source) { + var pair = message.split(':'); + if (pair.length == 2 && pair[0] == "TEST") + logs.push(pair[1]); + } + + TempDir { id: tempDir } + + TestCase { + id: testCase + name: "FileSystemAPI" + when: windowShown + + function init() { + clearLog() + FilePickerParams.filePickerOpened = false + FilePickerParams.selectFiles = false + FilePickerParams.selectedFilesUrl = [] + FilePickerParams.nameFilters = [] + accessRequested = false; + } + + function cleanup() { + clearLog() + } + + function clearLog() { + logs = [] + } + + function logContainsDoneMarker() { + if (logs.indexOf("DONE") > -1) + return true + else + return false + } + + function result() { + return logs[0] + } + + function fileAccessRequest(request) { + testCase.verify(!accessRequested) + accessRequested = true + testCase.verify(request.filePath == file) + testCase.verify(request.accessFlags == WebEngineFileSystemAccessRequest.Write | WebEngineFileSystemAccessRequest.Read) + request.accept() + } + + function directoryAccessRequest(request) { + testCase.verify(!accessRequested) + accessRequested = true + testCase.verify(request.filePath == tempDir.pathUrl()) + testCase.verify(request.accessFlags == WebEngineFileSystemAccessRequest.Read) + request.accept() + } + + function test_saveFile() { + webEngineView.fileSystemAccessRequested.connect(fileAccessRequest); + webEngineView.url = Qt.resolvedUrl("filesystemapi.html?dialog=savePicker"); + verify(webEngineView.waitForLoadSucceeded()); + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl.push(file); + keyClick(Qt.Key_Enter); // Open SaveDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + tryVerify(logContainsDoneMarker,2000) + // write access for save dialogs is automatically granted + verify(!accessRequested) + webEngineView.fileSystemAccessRequested.disconnect(fileAccessRequest); + } + + function test_openFile() { + // first save the file before open + test_saveFile() + init() + webEngineView.fileSystemAccessRequested.connect(fileAccessRequest); + webEngineView.url = Qt.resolvedUrl("filesystemapi.html?dialog=filePicker"); + verify(webEngineView.waitForLoadSucceeded()); + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl.push(file); + keyClick(Qt.Key_Enter); // Open FileDialog. + tryCompare(FilePickerParams, "filePickerOpened", true); + tryVerify(logContainsDoneMarker,2000) + verify(logs.indexOf("TEST_CONTENT") > -1) + verify(accessRequested) + webEngineView.fileSystemAccessRequested.disconnect(fileAccessRequest); + } + + function test_selectDirectory() { + tempDir.createDirectory("TEST_DIR") + webEngineView.fileSystemAccessRequested.connect(directoryAccessRequest); + webEngineView.url = Qt.resolvedUrl("filesystemapi.html?dialog=directoryPicker"); + verify(webEngineView.waitForLoadSucceeded()) + FilePickerParams.selectFiles = true; + FilePickerParams.selectedFilesUrl.push(tempDir.pathUrl()); + keyClick(Qt.Key_Enter); // Open showDirectoryDialog. + tryCompare(FilePickerParams, "directoryPickerOpened", true); + tryVerify(logContainsDoneMarker,2000) + verify(logs.indexOf("TEST_DIR") > -1) + verify(accessRequested) + webEngineView.fileSystemAccessRequested.disconnect(directoryAccessRequest); + } + + } +} diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml index 93aa48365..597cff73e 100644 --- a/tests/auto/quick/qmltests/data/tst_findText.qml +++ b/tests/auto/quick/qmltests/data/tst_findText.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -38,9 +13,16 @@ TestWebEngineView { property int matchCount: 0 property bool findFailed: false + SignalSpy { + id: findTextSpy + target: webEngineView + signalName: "findTextFinished" + } + function clear() { findFailed = false matchCount = -1 + findTextSpy.clear() } function findCallbackCalled() { return matchCount != -1 } @@ -49,7 +31,7 @@ TestWebEngineView { // If this starts to fail then either clear was not called before findText // or unexpected callback was triggered from some search. // On c++ side callback id can be checked to verify - testcase.verify(!findCallbackCalled(), 'Unexpected callback call or uncleared state before findText call!') + testCase.verify(!findCallbackCalled(), 'Unexpected callback call or uncleared state before findText call!') webEngineView.matchCount = matchCount findFailed = matchCount == 0 @@ -57,7 +39,7 @@ TestWebEngineView { TestCase { - id: testcase + id: testCase name: "WebViewFindText" function getBodyInnerHTML() { @@ -104,6 +86,9 @@ TestWebEngineView { webEngineView.findText("Hello", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 1) verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } function test_findTextCaseInsensitive() { @@ -115,6 +100,9 @@ TestWebEngineView { webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 1) verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } function test_findTextManyMatches() { @@ -124,8 +112,11 @@ TestWebEngineView { webEngineView.clear() webEngineView.findText("bla", findFlags, webEngineView.findTextCallback) - tryCompare(webEngineView, "matchCount", 100) + tryCompare(webEngineView, "matchCount", 100, 20000) verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 100) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } @@ -138,6 +129,9 @@ TestWebEngineView { webEngineView.findText("heLLo", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 0) verify(findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0) + compare(findTextSpy.signalArguments[0][0].activeMatch, 0) } function test_findTextNotFound() { @@ -149,6 +143,9 @@ TestWebEngineView { webEngineView.findText("string-that-is-not-threre", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 0) verify(findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0) + compare(findTextSpy.signalArguments[0][0].activeMatch, 0) } function test_findTextAfterNotFound() { @@ -160,6 +157,9 @@ TestWebEngineView { webEngineView.findText("hello", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 0) verify(findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0) + compare(findTextSpy.signalArguments[0][0].activeMatch, 0) webEngineView.url = Qt.resolvedUrl("test1.html") verify(webEngineView.waitForLoadSucceeded()) @@ -168,6 +168,9 @@ TestWebEngineView { webEngineView.findText("hello", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 1) verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } function test_findTextInModifiedDOMAfterNotFound() { @@ -180,8 +183,11 @@ TestWebEngineView { webEngineView.clear() webEngineView.findText("hello", findFlags, webEngineView.findTextCallback) - tryCompare(webEngineView, "matchCount", 0) + tryCompare(webEngineView, "matchCount", 0, 20000) verify(findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0) + compare(findTextSpy.signalArguments[0][0].activeMatch, 0) runJavaScript("document.body.innerHTML = 'blahellobla'"); tryVerify(function() { return getBodyInnerHTML() == "blahellobla"; }, 20000); @@ -190,6 +196,9 @@ TestWebEngineView { webEngineView.findText("hello", findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, "matchCount", 1) verify(!findFailed) + tryCompare(findTextSpy, "count", 1) + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 1) + compare(findTextSpy.signalArguments[0][0].activeMatch, 1) } function test_findTextInterruptedByLoad() { @@ -197,8 +206,7 @@ TestWebEngineView { var listItemText = ''; for (var i = 0; i < 100000; ++i) - listItemText += "bla "; - listItemText = listItemText.trim(); + listItemText += "bla"; webEngineView.loadHtml( "<html><body>" + @@ -227,5 +235,55 @@ TestWebEngineView { webEngineView.findText('New page', findFlags, webEngineView.findTextCallback) tryCompare(webEngineView, 'matchCount', 1) } + + function test_findTextActiveMatchOrdinal() { + webEngineView.loadHtml( + "<html><body>" + + "foo bar foo bar foo" + + "</body></html>"); + verify(webEngineView.waitForLoadSucceeded()); + + // Iterate over all "foo" matches. + webEngineView.clear(); + for (var i = 1; i <= 3; ++i) { + webEngineView.findText("foo"); + findTextSpy.wait(); + compare(findTextSpy.count, i); + compare(findTextSpy.signalArguments[i-1][0].numberOfMatches, 3); + compare(findTextSpy.signalArguments[i-1][0].activeMatch, i); + } + + // The last match is followed by the fist one. + webEngineView.clear(); + webEngineView.findText("foo"); + findTextSpy.wait(); + compare(findTextSpy.count, 1); + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 3); + compare(findTextSpy.signalArguments[0][0].activeMatch, 1); + + // The first match is preceded by the last one. + webEngineView.clear(); + webEngineView.findText("foo", WebEngineView.FindBackward); + findTextSpy.wait(); + compare(findTextSpy.count, 1); + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 3); + compare(findTextSpy.signalArguments[0][0].activeMatch, 3); + + // Finding another word resets the activeMatch. + webEngineView.clear(); + webEngineView.findText("bar"); + findTextSpy.wait(); + compare(findTextSpy.count, 1); + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 2); + compare(findTextSpy.signalArguments[0][0].activeMatch, 1); + + // If no match activeMatch is 0. + webEngineView.clear(); + webEngineView.findText("bla"); + findTextSpy.wait(); + compare(findTextSpy.count, 1); + compare(findTextSpy.signalArguments[0][0].numberOfMatches, 0); + compare(findTextSpy.signalArguments[0][0].activeMatch, 0); + } } } diff --git a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml index 93410a727..f070e4bc5 100644 --- a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml +++ b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.5 -import QtTest 1.0 -import QtWebEngine 1.4 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine Item { id: container @@ -65,6 +40,7 @@ Item { } TestCase { + id: testCase name: "WebEngineViewFocusOnNavigation" when: windowShown diff --git a/tests/auto/quick/qmltests/data/tst_fullScreenRequest.qml b/tests/auto/quick/qmltests/data/tst_fullScreenRequest.qml new file mode 100644 index 000000000..c7996a11e --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_fullScreenRequest.qml @@ -0,0 +1,82 @@ +import QtQuick +import QtTest +import QtWebEngine + +TestWebEngineView { + id: view + width: 320 + height: 320 + + property bool acceptRequest: false + + onFullScreenRequested: function(request) { + view.acceptRequest ? request.accept() : request.reject() + } + + SignalSpy { + id: spyRequest + target: view + signalName: 'fullScreenRequested' + } + + TestCase { + name: 'FullScreenRequest' + when: windowShown + + function init() { + spyRequest.clear() + } + + function test_request_data() { + return [ + { tag: 'accept', accept: true }, + { tag: 'reject', accept: false }, + ] + } + + function test_request(data) { + view.acceptRequest = data.accept + view.settings.fullscreenSupportEnabled = true + + // full screen request is only allowed by user gesture, so emulate key press + view.loadHtml( + '<html><body onkeypress="onKeyPress()"><a id="a">WRYYYY</a><script>' + + 'function onKeyPress() {' + + ' document.webkitIsFullScreen'+ + ' ? document.webkitExitFullscreen()' + + ' : document.documentElement.webkitRequestFullScreen()' + + '} </script></body></html>') + view.waitForLoadSucceeded() + verify(!view.isFullScreen) + + let result = null + view.runJavaScript('document.webkitFullscreenEnabled', function(r) { result = r }) + tryVerify(function() { return result === true }) + + result = null + view.runJavaScript('document.webkitIsFullScreen', function(r) { result = r }) + tryVerify(function() { return result === false }) + + // will trigger full screen request through key press + keyClick(Qt.Key_Space) + spyRequest.wait() + compare(spyRequest.count, 1) + verify(spyRequest.signalArguments[0][0].toggleOn) + compare(data.accept, view.isFullScreen) + + view.runJavaScript('document.webkitIsFullScreen', function(r) { result = r }) + tryVerify(function() { return result === data.accept }) + + if (data.accept) { + // expected to toggle from current state + keyClick(Qt.Key_Space) + spyRequest.wait() + compare(spyRequest.count, 2) + verify(!spyRequest.signalArguments[1][0].toggleOn) + view.runJavaScript('document.webkitIsFullScreen', function(r) { result = r }) + tryVerify(function() { return result === false }) + verify(!view.isFullScreen) + } + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_geopermission.qml b/tests/auto/quick/qmltests/data/tst_geopermission.qml index c935ac0b4..b99e50acc 100644 --- a/tests/auto/quick/qmltests/data/tst_geopermission.qml +++ b/tests/auto/quick/qmltests/data/tst_geopermission.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.2 -import QtTest 1.0 -import QtWebEngine 1.1 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -37,7 +12,6 @@ TestWebEngineView { property bool deniedGeolocation: false property bool geoPermissionRequested: false - signal consoleErrorMessage(string message) SignalSpy { id: featurePermissionSpy @@ -45,13 +19,7 @@ TestWebEngineView { signalName: "featurePermissionRequested" } - SignalSpy { - id: consoleErrorMessageSpy - target: webEngineView - signalName: "consoleErrorMessage" - } - - onFeaturePermissionRequested: { + onFeaturePermissionRequested: function(securityOrigin, feature) { if (feature === WebEngineView.Geolocation) { geoPermissionRequested = true if (deniedGeolocation) { @@ -63,19 +31,31 @@ TestWebEngineView { } } - onJavaScriptConsoleMessage: { - if (level === WebEngineView.ErrorMessageLevel) - consoleErrorMessage(message) - } - TestCase { name: "WebViewGeopermission" when: windowShown + function isHandled() { + var handled; + runJavaScript("handled", function(result) { + handled = result; + }); + tryVerify(function() { return handled != undefined; }, 5000); + return handled; + } + + function getErrorMessage() { + var errorMessage; + runJavaScript("errorMessage", function(result) { + errorMessage = result; + }); + tryVerify(function() { return errorMessage != undefined; }, 5000); + return errorMessage; + } + function init() { deniedGeolocation = false featurePermissionSpy.clear() - consoleErrorMessageSpy.clear() } function test_geoPermissionRequest() { @@ -84,17 +64,16 @@ TestWebEngineView { featurePermissionSpy.wait() verify(geoPermissionRequested) compare(featurePermissionSpy.count, 1) - consoleErrorMessageSpy.wait() - verify(consoleErrorMessageSpy.signalArguments[0][0] === "Success" || - consoleErrorMessageSpy.signalArguments[0][0] === "") + tryVerify(isHandled, 5000) + verify(getErrorMessage() === "") } function test_deniedGeolocationByUser() { deniedGeolocation = true webEngineView.url = Qt.resolvedUrl("geolocation.html") featurePermissionSpy.wait() - consoleErrorMessageSpy.wait() - compare(consoleErrorMessageSpy.signalArguments[0][0], "User denied Geolocation") + tryVerify(isHandled, 5000) + compare(getErrorMessage(), "User denied Geolocation") } } } diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml index d1c894699..3b33b7abe 100644 --- a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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.2 -import QtTest 1.0 -import QtWebEngine 1.6 +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -126,8 +101,8 @@ TestWebEngineView { signalName: "loadFinished" } - onLoadingChanged: { - if (loadRequest.status == WebEngineLoadRequest.LoadSucceededStatus) { + onLoadingChanged: function(load) { + if (load.status == WebEngineView.LoadSucceededStatus) { loadFinished() } } @@ -143,7 +118,7 @@ TestWebEngineView { property variant requestedFeature property variant requestedSecurityOrigin - onFeaturePermissionRequested: { + onFeaturePermissionRequested: function(securityOrigin, feature) { requestedFeature = feature requestedSecurityOrigin = securityOrigin } diff --git a/tests/auto/quick/qmltests/data/tst_inputMethod.qml b/tests/auto/quick/qmltests/data/tst_inputMethod.qml index c09a8bdd9..cf79e8a4d 100644 --- a/tests/auto/quick/qmltests/data/tst_inputMethod.qml +++ b/tests/auto/quick/qmltests/data/tst_inputMethod.qml @@ -1,53 +1,30 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.4 -import QtWebEngine.testsupport 1.0 +import QtQuick +import QtTest +import QtWebEngine +import Test.util +import "../../qmltests/data" TestWebEngineView { id: webEngineView width: 200 height: 400 - testSupport: WebEngineTestSupport { } + TestInputContext { id: testInputContext } TestCase { + id: testCase name: "WebEngineViewInputMethod" when: windowShown function init() { - testSupport.testInputContext.create(); + testInputContext.create(); } function cleanup() { - testSupport.testInputContext.release(); + testInputContext.release(); } function test_softwareInputPanel() { diff --git a/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml b/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml new file mode 100644 index 000000000..2141db4c8 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_inputTextDirection.qml @@ -0,0 +1,43 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +TestWebEngineView { + id: webEngineView + width: 400 + height: 400 + + TestCase { + id: testCase + name: "WebEngineInputTextDirection" + when: windowShown + + function getInputTextDirection(element) { + var dir; + runJavaScript("document.getElementById('" + element + "').dir", function(result) { + dir = result; + }); + tryVerify(function() { return dir != undefined; }); + return dir; + } + + function test_changeInputTextDirection() { + webEngineView.loadHtml("<html><body><input type='text' id='textfield' value='some text'></body></html>"); + verify(webEngineView.waitForLoadSucceeded()); + setFocusToElement("textfield"); + + var rtlAction = webEngineView.action(WebEngineView.ChangeTextDirectionRTL); + verify(rtlAction); + rtlAction.trigger(); + compare(getInputTextDirection("textfield"), "rtl"); + + var ltrAction = webEngineView.action(WebEngineView.ChangeTextDirectionLTR); + verify(ltrAction); + ltrAction.trigger(); + compare(getInputTextDirection("textfield"), "ltr"); + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml index 07236c3be..6e91b2e77 100644 --- a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml +++ b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml @@ -1,53 +1,21 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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.2 -import QtWebEngine.testsupport 1.0 -import "../mock-delegates/TestParams" 1.0 +// Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import "../../qmltests/data" +import "../mock-delegates/TestParams" TestWebEngineView { id: webEngineView anchors.fill: parent - testSupport: WebEngineTestSupport { - property bool windowCloseRejectedSignalEmitted: false - - function waitForWindowCloseRejected() { - return _waitFor(function () { - return testSupport.windowCloseRejectedSignalEmitted; - }); - } + property bool windowCloseRejectedCalled: false - onWindowCloseRejected: { - windowCloseRejectedSignalEmitted = true; - } + // Called by QQuickWebEngineViewPrivate::windowCloseRejected() + function windowCloseRejected() { + windowCloseRejectedCalled = true; } TestCase { @@ -111,17 +79,32 @@ TestWebEngineView { simulateUserGesture() webEngineView.triggerWebAction(WebEngineView.RequestClose); verify(webEngineView.waitForWindowCloseRequested()); + + // Navigate away from page with onbeforeunload handler, + // otherwise it would trigger an extra dialog request when + // navigating in the subsequent test. + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + compare(JSDialogParams.dialogCount, 2) } function test_rejectClose() { webEngineView.url = Qt.resolvedUrl("confirmclose.html"); verify(webEngineView.waitForLoadSucceeded()); - webEngineView.testSupport.windowCloseRejectedSignalEmitted = false; + webEngineView.windowCloseRejectedCalled = false; JSDialogParams.shouldAcceptDialog = false; simulateUserGesture() webEngineView.triggerWebAction(WebEngineView.RequestClose); - verify(webEngineView.testSupport.waitForWindowCloseRejected()); + tryVerify(function() { return webEngineView.windowCloseRejectedCalled; }); + + // Navigate away from page with onbeforeunload handler, + // otherwise it would trigger an extra dialog request when + // navigating in the subsequent test. + JSDialogParams.shouldAcceptDialog = true; + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + compare(JSDialogParams.dialogCount, 2) } function test_prompt() { diff --git a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml index 2536f319b..0f69a7e81 100644 --- a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml +++ b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -36,6 +11,7 @@ TestWebEngineView { height: 480 TestCase { + id: testCase name: "WebEngineViewKeyboardEvents" when: windowShown @@ -53,20 +29,6 @@ TestWebEngineView { "Element \"" + element + "\" is " + (expected ? "" : "not") + " checked"); } - function getElementValue(element) { - var elementValue; - runJavaScript("document.getElementById('" + element + "').value", function(result) { - elementValue = result; - }); - tryVerify(function() { return elementValue != undefined; }); - return elementValue; - } - - function compareElementValue(element, expected) { - tryVerify(function() { return expected == getElementValue(element); }, 5000, - "Value of element \"" + element + "\" is \"" + expected + "\""); - } - function test_keyboardEvents() { webEngineView.url = Qt.resolvedUrl("keyboardEvents.html"); verify(webEngineView.waitForLoadSucceeded()); diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml index e0a8c0a41..d0bc75619 100644 --- a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml +++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView diff --git a/tests/auto/quick/qmltests/data/tst_linkHovered.qml b/tests/auto/quick/qmltests/data/tst_linkHovered.qml index d632452fe..a11bd2450 100644 --- a/tests/auto/quick/qmltests/data/tst_linkHovered.qml +++ b/tests/auto/quick/qmltests/data/tst_linkHovered.qml @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** 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: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.2 -import QtWebEngine.testsupport 1.0 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import "../../qmltests/data" TestWebEngineView { id: webEngineView @@ -39,25 +14,29 @@ TestWebEngineView { property string lastUrl - testSupport: WebEngineTestSupport { } - - SignalSpy { - id: loadVisuallyCommittedSpy - target: webEngineView.testSupport - signalName: "loadVisuallyCommitted" - } - SignalSpy { id: linkHoveredSpy target: webEngineView signalName: "linkHovered" } - onLinkHovered: { + onLinkHovered: function(hoveredUrl) { webEngineView.lastUrl = hoveredUrl } + function isViewRendered() { + var pixel = getItemPixel(webEngineView); + + // The center pixel is expected to be red. + if (pixel[0] !== 255) return false; + if (pixel[1] !== 0) return false; + if (pixel[2] !== 0) return false; + + return true; + } + TestCase { + id: testCase name: "DesktopWebEngineViewLinkHovered" // Delayed windowShown to workaround problems with Qt5 in debug mode. @@ -71,7 +50,6 @@ TestWebEngineView { function init() { webEngineView.lastUrl = ""; - loadVisuallyCommittedSpy.clear(); linkHoveredSpy.clear(); } @@ -87,7 +65,7 @@ TestWebEngineView { compare(webEngineView.lastUrl, "") // Wait for the page to be rendered before trying to test based on input events - loadVisuallyCommittedSpy.wait(); + tryVerify(isViewRendered); mouseMove(webEngineView, 100, 100) linkHoveredSpy.wait(12000); @@ -110,7 +88,7 @@ TestWebEngineView { compare(webEngineView.lastUrl, "") // Wait for the page to be rendered before trying to test based on input events - loadVisuallyCommittedSpy.wait(); + tryVerify(isViewRendered); for (var i = 0; i < 100; i += 10) mouseMove(webEngineView, 100, 100 + i) diff --git a/tests/auto/quick/qmltests/data/tst_loadFail.qml b/tests/auto/quick/qmltests/data/tst_loadFail.qml index 7b51009a1..8e9224bbf 100644 --- a/tests/auto/quick/qmltests/data/tst_loadFail.qml +++ b/tests/auto/quick/qmltests/data/tst_loadFail.qml @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 -import QtWebEngine.testsupport 1.0 +import QtQuick +import QtTest +import QtWebEngine +import "../../qmltests/data" TestWebEngineView { id: webEngineView @@ -37,47 +12,21 @@ TestWebEngineView { height: 300 property var unavailableUrl: Qt.resolvedUrl("file_that_does_not_exist.html") - property var loadRequestArray: [] - testSupport: WebEngineTestSupport { - property var errorPageLoadStatus: null - - function waitForErrorPageLoadSucceeded() { - var success = _waitFor(function() { return testSupport.errorPageLoadStatus == WebEngineView.LoadSucceededStatus }) - testSupport.errorPageLoadStatus = null - return success - } - - errorPage.onLoadingChanged: { - errorPageLoadStatus = loadRequest.status - - loadRequestArray.push({ - "status": loadRequest.status, - "url": loadRequest.url.toString(), - "errorDomain": loadRequest.errorDomain, - "isErrorPage": true - }) - } - } - - onLoadingChanged: { - if (loadRequest.status == WebEngineView.LoadFailedStatus) { - test.compare(loadRequest.url, unavailableUrl) - test.compare(loadRequest.errorDomain, WebEngineView.InternalErrorDomain) - } - - loadRequestArray.push({ - "status": loadRequest.status, - "url": loadRequest.url.toString(), - "errorDomain": loadRequest.errorDomain, - "isErrorPage": false - }) + SignalSpy { + id: loadSpy + target: webEngineView + signalName: 'loadingChanged' } TestCase { id: test name: "WebEngineViewLoadFail" + function cleanup() { + loadSpy.clear() + } + function test_fail() { WebEngine.settings.errorPageEnabled = false webEngineView.url = unavailableUrl @@ -105,38 +54,23 @@ TestWebEngineView { webEngineView.url = unavailableUrl // Loading of the error page must be successful - verify(webEngineView.testSupport.waitForErrorPageLoadSucceeded()) - - var loadRequest = null - compare(loadRequestArray.length, 4) + verify(webEngineView.waitForLoadFailed()) // Start to load unavailableUrl - loadRequest = loadRequestArray[0] - compare(loadRequest.status, WebEngineView.LoadStartedStatus) - compare(loadRequest.errorDomain, WebEngineView.NoErrorDomain) - compare(loadRequest.url, unavailableUrl) - verify(!loadRequest.isErrorPage) + let loadStart = loadSpy.signalArguments[0][0] + compare(loadStart.status, WebEngineView.LoadStartedStatus) + compare(loadStart.errorDomain, WebEngineView.NoErrorDomain) + compare(loadStart.errorDomain, WebEngineLoadingInfo.NoErrorDomain) + compare(loadStart.url, unavailableUrl) + verify(!loadStart.isErrorPage) // Loading of the unavailableUrl must fail - loadRequest = loadRequestArray[1] - compare(loadRequest.status, WebEngineView.LoadFailedStatus) - compare(loadRequest.errorDomain, WebEngineView.InternalErrorDomain) - compare(loadRequest.url, unavailableUrl) - verify(!loadRequest.isErrorPage) - - // Start to load error page - loadRequest = loadRequestArray[2] - compare(loadRequest.status, WebEngineView.LoadStartedStatus) - compare(loadRequest.errorDomain, WebEngineView.NoErrorDomain) - compare(loadRequest.url, "chrome-error://chromewebdata/") - verify(loadRequest.isErrorPage) - - // Loading of the error page must be successful - loadRequest = loadRequestArray[3] - compare(loadRequest.status, WebEngineView.LoadSucceededStatus) - compare(loadRequest.errorDomain, WebEngineView.NoErrorDomain) - compare(loadRequest.url, "chrome-error://chromewebdata/") - verify(loadRequest.isErrorPage) + let loadFail = loadSpy.signalArguments[1][0] + compare(loadFail.status, WebEngineView.LoadFailedStatus) + compare(loadFail.errorDomain, WebEngineView.InternalErrorDomain) + compare(loadFail.errorDomain, WebEngineLoadingInfo.InternalErrorDomain) + compare(loadFail.url, unavailableUrl) + verify(loadFail.isErrorPage) compare(webEngineView.url, unavailableUrl) compare(webEngineView.title, unavailableUrl) diff --git a/tests/auto/quick/qmltests/data/tst_loadHtml.qml b/tests/auto/quick/qmltests/data/tst_loadHtml.qml index ed1de41fd..8f94cd4a2 100644 --- a/tests/auto/quick/qmltests/data/tst_loadHtml.qml +++ b/tests/auto/quick/qmltests/data/tst_loadHtml.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -42,6 +17,7 @@ TestWebEngineView { } TestCase { + id: testCase name: "WebEngineViewLoadHtml" when: windowShown diff --git a/tests/auto/quick/qmltests/data/tst_loadProgress.qml b/tests/auto/quick/qmltests/data/tst_loadProgress.qml index 15058cb8f..2c06a0207 100644 --- a/tests/auto/quick/qmltests/data/tst_loadProgress.qml +++ b/tests/auto/quick/qmltests/data/tst_loadProgress.qml @@ -1,34 +1,11 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine + +import Test.Shared as Shared TestWebEngineView { id: webEngineView @@ -55,10 +32,14 @@ TestWebEngineView { compare(spyProgress.count, 0) loadProgressArray = [] - webEngineView.url = Qt.resolvedUrl("test1.html") + verify(Shared.HttpServer.start()) + Shared.HttpServer.newRequest.connect(request => { + wait(250) // just add delay to trigger some progress for every sub resource + }) + webEngineView.url = Shared.HttpServer.url('/loadprogress/main.html') // Wait for the first loadProgressChanged signal, which have to be non-negative spyProgress.wait() - verify(loadProgressArray[0] >= 0) + compare(loadProgressArray[0], 0) verify(webEngineView.loadProgress >= 0) // Wait for the last loadProgressChanged signal, which have to be 100% @@ -67,13 +48,13 @@ TestWebEngineView { compare(loadProgressArray[loadProgressArray.length - 1], 100) compare(webEngineView.loadProgress, 100) - // Test whether the chromium emits progress numbers in ascending order - var loadProgressMin = 0 - for (var i in loadProgressArray) { - var loadProgress = loadProgressArray[i] - if (loadProgressMin > loadProgress) + // Test whether the chromium emits progress numbers in strict monotonic ascending order + let progress = 0 + for (let i = 1; i < loadProgressArray.length; ++i) { + let nextProgress = loadProgressArray[i] + if (nextProgress <= progress) fail("Invalid sequence of progress-values: " + loadProgressArray) - loadProgressMin = loadProgress + progress = nextProgress } } } diff --git a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml index 81a0f0904..c0eb5932b 100644 --- a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml +++ b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.3 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine Item { width: 300 diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index ec5c965ea..25a62c878 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -37,10 +12,10 @@ TestWebEngineView { property var loadRequestArray: [] - onLoadingChanged: { + onLoadingChanged: function(load) { loadRequestArray.push({ - "status": loadRequest.status, - "url": loadRequest.url, + "status": load.status, + "url": load.url, "activeUrl": webEngineView.url }); } @@ -52,6 +27,7 @@ TestWebEngineView { } TestCase { + id: testCase name: "WebEngineViewLoadUrl" when: windowShown @@ -79,8 +55,8 @@ TestWebEngineView { var aboutBlank = "about:blank"; webEngineView.url = aboutBlank; verify(webEngineView.waitForLoadSucceeded()); - compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus); - compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus); + compare(loadRequestArray[0].status, WebEngineLoadingInfo.LoadStartedStatus); + compare(loadRequestArray[1].status, WebEngineLoadingInfo.LoadSucceededStatus); compare(loadRequestArray.length, 2); compare(webEngineView.url, aboutBlank); webEngineView.clear(); @@ -133,6 +109,7 @@ TestWebEngineView { compare(loadRequest.activeUrl, bogusSite); loadRequest = loadRequestArray[1]; compare(loadRequest.status, WebEngineView.LoadFailedStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadFailedStatus); compare(loadRequest.activeUrl, url); webEngineView.clear(); @@ -148,10 +125,10 @@ TestWebEngineView { compare(loadRequest.status, WebEngineView.LoadSucceededStatus); compare(loadRequest.activeUrl, redirectUrl); loadRequest = loadRequestArray[2]; - compare(loadRequest.status, WebEngineView.LoadStartedStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadStartedStatus); compare(loadRequest.activeUrl, redirectUrl); loadRequest = loadRequestArray[3]; - compare(loadRequest.status, WebEngineView.LoadSucceededStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadSucceededStatus); compare(loadRequest.activeUrl, url); webEngineView.clear(); @@ -173,11 +150,11 @@ TestWebEngineView { tryCompare(loadRequestArray, "length", 2); loadRequest = loadRequestArray[0]; - compare(loadRequest.status, WebEngineView.LoadStartedStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadStartedStatus); compare(loadRequest.url, url); compare(loadRequest.activeUrl, lastUrl); loadRequest = loadRequestArray[1]; - compare(loadRequest.status, WebEngineView.LoadSucceededStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadSucceededStatus); compare(loadRequest.url, url); compare(loadRequest.activeUrl, url); webEngineView.clear(); @@ -225,15 +202,16 @@ TestWebEngineView { compare(loadRequest.activeUrl, bogusSite); loadRequest = loadRequestArray[1]; compare(loadRequest.status, WebEngineView.LoadFailedStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadFailedStatus); // Since the load did not succeed the active url is the // URL of the previous successful load. compare(loadRequest.activeUrl, aboutBlank); loadRequest = loadRequestArray[2]; - compare(loadRequest.status, WebEngineView.LoadStartedStatus); - compare(loadRequest.activeUrl, aboutBlank); + compare(loadRequest.status, WebEngineLoadingInfo.LoadStartedStatus); + compare(loadRequest.activeUrl, bogusSite); compare(loadRequest.url, "data:text/html;charset=UTF-8,load failed") loadRequest = loadRequestArray[3]; - compare(loadRequest.status, WebEngineView.LoadSucceededStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadSucceededStatus); compare(loadRequest.activeUrl, bogusSite); compare(loadRequest.url, bogusSite) webEngineView.clear(); @@ -285,6 +263,7 @@ TestWebEngineView { compare(loadRequest.activeUrl, stoppedUrl); loadRequest = loadRequestArray[1]; compare(loadRequest.status, WebEngineView.LoadStoppedStatus); + compare(loadRequest.status, WebEngineLoadingInfo.LoadStoppedStatus); compare(loadRequest.url, stoppedUrl); compare(loadRequest.activeUrl, initialUrl); webEngineView.clear(); @@ -298,20 +277,19 @@ TestWebEngineView { compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus); compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus); - // In-page navigation. - webEngineView.url = Qt.resolvedUrl("test4.html#content"); - // In-page navigation doesn't trigger load succeeded, wait for load progress instead. - tryCompare(webEngineView, "loadProgress", 100); - compare(loadRequestArray.length, 3); - compare(loadRequestArray[2].status, WebEngineView.LoadStartedStatus); + // In-page navigation shouldn't trigger load + let anchorUrl = Qt.resolvedUrl("test4.html#anchor"); + let c = webEngineView.getElementCenter('anchor') + mouseClick(webEngineView, c.x, c.y) + tryCompare(webEngineView, 'url', anchorUrl) // Load after in-page navigation. webEngineView.url = Qt.resolvedUrl("test4.html"); verify(webEngineView.waitForLoadSucceeded()); compare(webEngineView.loadProgress, 100); - compare(loadRequestArray.length, 5); - compare(loadRequestArray[3].status, WebEngineView.LoadStartedStatus); - compare(loadRequestArray[4].status, WebEngineView.LoadSucceededStatus); + compare(loadRequestArray.length, 4); + compare(loadRequestArray[2].status, WebEngineView.LoadStartedStatus); + compare(loadRequestArray[3].status, WebEngineView.LoadSucceededStatus); webEngineView.clear(); } diff --git a/tests/auto/quick/qmltests/data/tst_mouseClick.qml b/tests/auto/quick/qmltests/data/tst_mouseClick.qml index d81e690fd..c0c6a6967 100644 --- a/tests/auto/quick/qmltests/data/tst_mouseClick.qml +++ b/tests/auto/quick/qmltests/data/tst_mouseClick.qml @@ -1,44 +1,21 @@ -/**************************************************************************** -** -** 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 - -import QtWebEngine.testsupport 1.0 +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Test.util +import "../../qmltests/data" TestWebEngineView { id: webEngineView width: 200 height: 200 - testSupport: WebEngineTestSupport { - function mouseMultiClick(item, x, y, clickCount) { + TestInputEvent { + id: testInputEvent + + function __mouseMultiClick(item, x, y, clickCount) { if (!item) qtest_fail("No item given to mouseMultiClick", 1); @@ -46,25 +23,26 @@ TestWebEngineView { x = item.width / 2; if (y === undefined) y = item.height / 2; - if (!testEvent.mouseMultiClick(item, x, y, clickCount)) + if (!mouseMultiClick(item, x, y, clickCount)) qtest_fail("window not shown", 2); } function mouseDoubleClick(item, x, y) { - mouseMultiClick(item, x, y, 2); + __mouseMultiClick(item, x, y, 2); } function mouseTripleClick(item, x, y) { - mouseMultiClick(item, x, y, 3); + __mouseMultiClick(item, x, y, 3); } function mouseQuadraClick(item, x, y) { - mouseMultiClick(item, x, y, 4); + __mouseMultiClick(item, x, y, 4); } } TestCase { + id: testCase name: "WebEngineViewMouseClick" when: windowShown @@ -90,7 +68,7 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); var center = getElementCenter("input"); - webEngineView.testSupport.mouseDoubleClick(webEngineView, center.x, center.y); + testInputEvent.mouseDoubleClick(webEngineView, center.x, center.y); verifyElementHasFocus("input"); tryVerify(function() { return getTextSelection() == "Company" }); @@ -106,7 +84,7 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); var center = getElementCenter("input"); - webEngineView.testSupport.mouseTripleClick(webEngineView, center.x, center.y); + testInputEvent.mouseTripleClick(webEngineView, center.x, center.y); verifyElementHasFocus("input"); tryVerify(function() { return getTextSelection() == "The Qt Company" }); @@ -122,7 +100,7 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); var center = getElementCenter("input"); - webEngineView.testSupport.mouseQuadraClick(webEngineView, center.x, center.y); + testInputEvent.mouseQuadraClick(webEngineView, center.x, center.y); verifyElementHasFocus("input"); tryVerify(function() { return getTextSelection() == "" }); } diff --git a/tests/auto/quick/qmltests/data/tst_mouseMove.qml b/tests/auto/quick/qmltests/data/tst_mouseMove.qml index adfa3941c..5ded24c57 100644 --- a/tests/auto/quick/qmltests/data/tst_mouseMove.qml +++ b/tests/auto/quick/qmltests/data/tst_mouseMove.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.4 +import QtQuick +import QtTest +import QtWebEngine Rectangle { id: root diff --git a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml index 77664e645..2ea76c387 100644 --- a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml +++ b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -38,7 +13,7 @@ TestWebEngineView { ListView { id: backItemsList anchors.fill: parent - model: webEngineView.navigationHistory.backItems + model: webEngineView.history.backItems currentIndex: count - 1 delegate: Text { @@ -50,7 +25,7 @@ TestWebEngineView { ListView { id: forwardItemsList anchors.fill: parent - model: webEngineView.navigationHistory.forwardItems + model: webEngineView.history.forwardItems currentIndex: 0 delegate: Text { @@ -59,11 +34,23 @@ TestWebEngineView { } } + Item { // simple button-like interface to not depend on controls + id: backButton + enabled: webEngineView.canGoBack + function clicked() { if (enabled) webEngineView.goBack() } + } + + Item { // simple button-like interface to not depend on controls + id: forwardButton + enabled: webEngineView.canGoForward + function clicked() { if (enabled) webEngineView.goForward() } + } + TestCase { - name: "WebEngineViewNavigationHistory" + name: "NavigationHistory" function test_navigationHistory() { - compare(webEngineView.loadProgress, 0) + webEngineView.history.clear() webEngineView.url = Qt.resolvedUrl("test1.html") verify(webEngineView.waitForLoadSucceeded()) @@ -134,6 +121,59 @@ TestWebEngineView { compare(forwardItemsList.count, 1) compare(backItemsList.currentItem.text, Qt.resolvedUrl("test1.html")) compare(forwardItemsList.currentItem.text, Qt.resolvedUrl("javascript.html")) + + webEngineView.history.clear() + compare(webEngineView.url, Qt.resolvedUrl("test2.html")) + compare(webEngineView.canGoBack, false) + compare(webEngineView.canGoForward, false) + compare(backItemsList.count, 0) + compare(forwardItemsList.count, 0) + } + + function test_navigationButtons() { + webEngineView.history.clear() + + const url1 = Qt.resolvedUrl("test1.html") + webEngineView.url = url1 + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, false) + compare(forwardButton.enabled, false) + + const url2 = Qt.resolvedUrl("test2.html") + webEngineView.url = url2 + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, true) + compare(forwardButton.enabled, false) + + const url3 = Qt.resolvedUrl("test3.html") + webEngineView.url = url3 + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, true) + compare(forwardButton.enabled, false) + + backButton.clicked() + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, true) + compare(forwardButton.enabled, true) + compare(webEngineView.url, url2) + + backButton.clicked() + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, false) + compare(forwardButton.enabled, true) + compare(webEngineView.url, url1) + + forwardButton.clicked() + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, true) + compare(forwardButton.enabled, true) + compare(webEngineView.url, url2) + + webEngineView.url = url1 + verify(webEngineView.waitForLoadSucceeded()) + compare(backButton.enabled, true) + compare(forwardButton.enabled, false) + compare(webEngineView.url, url1) } } } diff --git a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml index 96128574e..31c0cf44e 100644 --- a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml +++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -59,26 +34,27 @@ TestWebEngineView { signalName: "navigationRequested" } - onNavigationRequested: { + onNavigationRequested: function(request) { if (request.isMainFrame) { attributes.mainUrl = request.url } else { attributes.iframeUrl = request.url if (shouldIgnoreSubFrameRequests) { - request.action = WebEngineView.IgnoreRequest + request.reject() } } - if (request.navigationType === WebEngineView.LinkClickedNavigation) { + if (request.navigationType === WebEngineNavigationRequest.LinkClickedNavigation) { attributes.linkClickedNavigationRequested = true if (shouldIgnoreLinkClicks) { - request.action = WebEngineView.IgnoreRequest + request.reject() attributes.linkClickedNavigationIgnored = true } } } TestCase { + id: testCase name: "WebEngineViewNavigationRequested" when: windowShown @@ -93,19 +69,17 @@ TestWebEngineView { // Test if we get notified about main frame and iframe loads compare(navigationSpy.count, 0) webEngineView.url = Qt.resolvedUrl("test-iframe.html") - navigationSpy.wait() + verify(webEngineView.waitForLoadSucceeded()) compare(attributes.mainUrl, Qt.resolvedUrl("test-iframe.html")) - navigationSpy.wait() compare(attributes.iframeUrl, Qt.resolvedUrl("test1.html")) compare(navigationSpy.count, 2) - verify(webEngineView.waitForLoadSucceeded()) // Test if we get notified about clicked links mouseClick(webEngineView, 100, 100) - tryCompare(navigationSpy, "count", 3) + verify(webEngineView.waitForLoadSucceeded()) compare(attributes.mainUrl, Qt.resolvedUrl("test1.html")) verify(attributes.linkClickedNavigationRequested) - verify(webEngineView.waitForLoadSucceeded()) + compare(navigationSpy.count, 3) } function test_ignoreLinkClickedRequest() { @@ -116,26 +90,28 @@ TestWebEngineView { shouldIgnoreLinkClicks = true mouseClick(webEngineView, 100, 100) - tryCompare(navigationSpy, "count", 3) - compare(attributes.mainUrl, Qt.resolvedUrl("test1.html")) - verify(attributes.linkClickedNavigationRequested) - verify(attributes.linkClickedNavigationIgnored) // We ignored the main frame request, so we should // get notified that the load has been stopped. verify(webEngineView.waitForLoadStopped()) verify(!webEngineView.loading) + + compare(navigationSpy.count, 3) + compare(attributes.mainUrl, Qt.resolvedUrl("test1.html")) + verify(attributes.linkClickedNavigationRequested) + verify(attributes.linkClickedNavigationIgnored) } function test_ignoreSubFrameRequest() { // Test if we can ignore sub frame requests shouldIgnoreSubFrameRequests = true webEngineView.url = Qt.resolvedUrl("test-iframe.html") - tryCompare(navigationSpy, "count", 2) - compare(attributes.mainUrl, Qt.resolvedUrl("test-iframe.html")) - compare(attributes.iframeUrl, Qt.resolvedUrl("test1.html")) // We ignored the sub frame request, so // the main frame load should still succeed. verify(webEngineView.waitForLoadSucceeded()) + + compare(navigationSpy.count, 2) + compare(attributes.mainUrl, Qt.resolvedUrl("test-iframe.html")) + compare(attributes.iframeUrl, Qt.resolvedUrl("test1.html")) } } } diff --git a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml index 4becbb620..68350d107 100644 --- a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml +++ b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.5 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -37,14 +12,22 @@ TestWebEngineView { property var newViewRequest: null property var dialog: null + property string viewType: "" + property var loadRequestArray: [] + + onLoadingChanged: function(load) { + loadRequestArray.push({ + "status": load.status, + }); + } SignalSpy { id: newViewRequestedSpy target: webEngineView - signalName: "newViewRequested" + signalName: "newWindowRequested" } - onNewViewRequested: { + onNewWindowRequested: function(request) { newViewRequest = { "destination": request.destination, "userInitiated": request.userInitiated, @@ -52,7 +35,7 @@ TestWebEngineView { }; dialog = Qt.createQmlObject( - "import QtQuick.Window 2.0\n" + + "import QtQuick.Window\n" + "Window {\n" + " width: 100; height: 100\n" + " visible: true; flags: Qt.Dialog\n" + @@ -60,12 +43,17 @@ TestWebEngineView { " TestWebEngineView { id: webView; anchors.fill: parent }\n" + "}", webEngineView); - request.openIn(dialog.webEngineView); + if (viewType === "dialog") + request.openIn(dialog.webEngineView); + else if (viewType === "null") + request.openIn(0); + else if (viewType === "webEngineView") + request.openIn(webEngineView); } TestCase { - id: test - name: "NewViewRequest" + id: testCase + name: "NewWindowRequest" when: windowShown function init() { @@ -74,6 +62,8 @@ TestWebEngineView { newViewRequestedSpy.clear(); newViewRequest = null; + viewType = ""; + loadRequestArray = []; } function cleanup() { @@ -81,7 +71,17 @@ TestWebEngineView { dialog.destroy(); } - function test_jsWindowOpen() { + function test_loadNewWindowRequest_data() { + return [ + { tag: "dialog", viewType: "dialog" }, + { tag: "invalid", viewType: "null" }, + { tag: "unhandled", viewType: "" }, + { tag: "webEngineView", viewType: "webEngineView" }, + ]; + } + + function test_loadNewWindowRequest(row) { + viewType = row.viewType; var url = 'data:text/html,%3Chtml%3E%3Cbody%3ETest+Page%3C%2Fbody%3E%3C%2Fhtml%3E'; // Open an empty page in a new tab @@ -93,14 +93,16 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); tryCompare(newViewRequestedSpy, "count", 1); - compare(newViewRequest.destination, WebEngineView.NewViewInTab); + compare(newViewRequest.destination, WebEngineNewWindowRequest.InNewTab); verify(!newViewRequest.userInitiated); - verify(dialog.webEngineView.waitForLoadSucceeded()); - compare(dialog.webEngineView.url, ""); + if (viewType === "dialog") { + tryVerify(dialog.webEngineView.loadSucceeded) + compare(dialog.webEngineView.url, Qt.url("about:blank")); + dialog.destroy(); + } compare(newViewRequest.requestedUrl, 'about:blank'); newViewRequestedSpy.clear(); - dialog.destroy(); // Open a page in a new dialog webEngineView.loadHtml( @@ -111,33 +113,55 @@ TestWebEngineView { verify(webEngineView.waitForLoadSucceeded()); tryCompare(newViewRequestedSpy, "count", 1); - compare(newViewRequest.destination, WebEngineView.NewViewInDialog); + compare(newViewRequest.destination, WebEngineNewWindowRequest.InNewDialog); compare(newViewRequest.requestedUrl, url); verify(!newViewRequest.userInitiated); - verify(dialog.webEngineView.waitForLoadSucceeded()); + if (viewType === "dialog") { + tryVerify(dialog.webEngineView.loadSucceeded) + dialog.destroy(); + } newViewRequestedSpy.clear(); - dialog.destroy(); - // Open a page in a new dialog by user - webEngineView.loadHtml( - "<html><head><script>" + - " function popup() { window.open('" + url + "', '_blank', 'width=200,height=100'); }" + - "</script></head>" + - "<body onload=\"document.getElementById('popupButton').focus();\">" + - " <button id='popupButton' onclick='popup()'>Pop Up!</button>" + - "</body></html>"); + if (viewType !== "webEngineView") { + // Open a page in a new dialog by user + webEngineView.loadHtml( + "<html><head><script>" + + " function popup() { window.open('" + url + "', '_blank', 'width=200,height=100'); }" + + "</script></head>" + + "<body onload=\"document.getElementById('popupButton').focus();\">" + + " <button id='popupButton' onclick='popup()'>Pop Up!</button>" + + "</body></html>"); + verify(webEngineView.waitForLoadSucceeded()); + webEngineView.verifyElementHasFocus("popupButton"); + keyPress(Qt.Key_Enter); + tryCompare(newViewRequestedSpy, "count", 1); + compare(newViewRequest.requestedUrl, url); + + compare(newViewRequest.destination, WebEngineNewWindowRequest.InNewDialog); + verify(newViewRequest.userInitiated); + if (viewType === "dialog") { + tryVerify(dialog.webEngineView.loadSucceeded) + dialog.destroy(); + } + newViewRequestedSpy.clear(); + } + + loadRequestArray = []; + compare(loadRequestArray.length, 0); + webEngineView.url = Qt.resolvedUrl("test2.html"); verify(webEngineView.waitForLoadSucceeded()); - verifyElementHasFocus("popupButton"); - keyPress(Qt.Key_Enter); - compare(newViewRequest.requestedUrl, url); + var center = webEngineView.getElementCenter("link"); + mouseClick(webEngineView, center.x, center.y, Qt.LeftButton, Qt.ControlModifier); tryCompare(newViewRequestedSpy, "count", 1); - - compare(newViewRequest.destination, WebEngineView.NewViewInDialog); + compare(newViewRequest.requestedUrl, Qt.resolvedUrl("test1.html")); + compare(newViewRequest.destination, WebEngineNewWindowRequest.InNewBackgroundTab); verify(newViewRequest.userInitiated); - verify(dialog.webEngineView.waitForLoadSucceeded()); + if (viewType === "" || viewType === "null") { + compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus); + compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus); + compare(loadRequestArray.length, 2); + } newViewRequestedSpy.clear(); - dialog.destroy(); } } } - diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml new file mode 100644 index 000000000..5d55e1201 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_notification.qml @@ -0,0 +1,99 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine +import Test.Shared as Shared + +TestWebEngineView { + id: view + width: 320 + height: 320 + + property bool permissionRequested: false + property bool grantPermission: false + property url securityOrigin: '' + + signal consoleMessage(string message) + + SignalSpy { + id: spyRequest + target: view + signalName: 'featurePermissionRequested' + } + + onFeaturePermissionRequested: function(securityOrigin, feature) { + if (feature === WebEngineView.Notifications) { + view.permissionRequested = true + view.securityOrigin = securityOrigin + view.grantFeaturePermission(securityOrigin, feature, grantPermission) + } + } + + TestCase { + name: 'WebEngineNotification' + when: windowShown + + function resolverUrl(html) { + console.log(Shared.HttpServer.sharedDataDir()) + return Qt.resolvedUrl(Shared.HttpServer.sharedDataDir() + "/" + html) + } + + function init() { + permissionRequested = false + spyRequest.clear() + } + + function test_request_data() { + return [ + { tag: 'grant', grant: true, permission: 'granted' }, + { tag: 'deny', grant: false, permission: 'denied' }, + ] + } + + function test_request(data) { + grantPermission = data.grant + + view.url = resolverUrl('notification.html') + verify(view.waitForLoadSucceeded()) + + view.runJavaScript('resetPermission()') + let result = {} + + view.runJavaScript('getPermission()', function (permission) { result.permission = permission }) + tryCompare(result, 'permission', 'default') + + view.runJavaScript('requestPermission()') + spyRequest.wait() + verify(permissionRequested) + compare(spyRequest.count, 1) + + view.runJavaScript('getPermission()', function (permission) { result.permission = permission }) + tryCompare(result, 'permission', data.permission) + } + + function test_notification() { + grantPermission = true + + view.url = resolverUrl('notification.html') + view.waitForLoadSucceeded() + + view.runJavaScript('requestPermission()') + spyRequest.wait() + verify(permissionRequested) + + let title = 'Title', message = 'Message', notification = null + view.profile.presentNotification.connect(function (n) { notification = n }) + + view.runJavaScript('sendNotification("' + title + '", "' + message + '")') + tryVerify(function () { return notification !== null }) + compare(notification.title, title) + compare(notification.message, message) + compare(notification.direction, Qt.RightToLeft) + compare(notification.origin, securityOrigin) + compare(notification.tag, 'tst') + compare(notification.language, 'de') + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_properties.qml b/tests/auto/quick/qmltests/data/tst_properties.qml index 89f8af9b8..13d40ed11 100644 --- a/tests/auto/quick/qmltests/data/tst_properties.qml +++ b/tests/auto/quick/qmltests/data/tst_properties.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView diff --git a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml index beeebc049..f16cd9c41 100644 --- a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml +++ b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -59,8 +34,7 @@ TestWebEngineView { compare(result, testTitle2); callbackCalled = true; }); - wait(100); - verify(callbackCalled); + tryVerify(function() { return callbackCalled; }); } } } diff --git a/tests/auto/quick/qmltests/data/tst_save.qml b/tests/auto/quick/qmltests/data/tst_save.qml new file mode 100644 index 000000000..3289dbd8b --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_save.qml @@ -0,0 +1,185 @@ +import QtQuick +import QtTest +import QtWebEngine +import Test.util + +TestWebEngineView { + id: webEngineView + width: 200 + height: 200 + profile: testSaveProfile + + property url downloadUrl: "" + property int totalBytes: 0 + property int receivedBytes: 0 + property string downloadDir: "" + property string downloadFileName: "" + property bool isSavePageDownload: false + property var downloadState: [] + property int savePageFormat: WebEngineDownloadRequest.MimeHtmlSaveFormat; + property bool autoCancel: false + + TempDir { + id: tempDir + } + + SignalSpy { + id: downLoadRequestedSpy + target: testSaveProfile + signalName: "downloadRequested" + } + + SignalSpy { + id: downloadFinishedSpy + target: testSaveProfile + signalName: "downloadFinished" + } + + WebEngineProfile { + id: testSaveProfile + + onDownloadRequested: function(download) { + downloadState.push(download.state) + downloadUrl = download.url + savePageFormat = download.savePageFormat + downloadDir = download.downloadDirectory; + downloadFileName = download.downloadFileName + isSavePageDownload = download.isSavePageDownload + + if (autoCancel) + download.cancel() + } + onDownloadFinished: function(download) { + receivedBytes = download.receivedBytes + totalBytes = download.totalBytes + downloadState.push(download.state) + } + } + + TestCase { + name: "WebEngineViewSave" + + function verifyData() { + var isDataValid = false + webEngineView.runJavaScript("(function() {" + + "var title = document.title.toString();" + + "var body = document.body.innerText;" + + " return title === \"Test page 1\" && body.includes(\"Hello.\")" + + "})();", function(result) { + isDataValid = result; + }); + tryVerify(function() { return isDataValid }); + return isDataValid; + } + + function init() { + downLoadRequestedSpy.clear() + downloadFinishedSpy.clear() + totalBytes = 0 + receivedBytes = 0 + downloadDir = "" + downloadFileName = "" + isSavePageDownload = false + downloadState = [] + downloadUrl = "" + autoCancel = false + } + + function test_savePage_data() { + return [ + { tag: "SingleHtmlSaveFormat", savePageFormat: WebEngineDownloadRequest.SingleHtmlSaveFormat }, + { tag: "CompleteHtmlSaveFormat", savePageFormat: WebEngineDownloadRequest.CompleteHtmlSaveFormat }, + { tag: "MimeHtmlSaveFormat", savePageFormat: WebEngineDownloadRequest.MimeHtmlSaveFormat }, + ]; + } + + function test_savePage(row) { + var saveFormat = row.savePageFormat + + var fileDir = tempDir.path() + var fileName = "saved_page.html" + var filePath = fileDir + "/"+ fileName + + // load data to view + webEngineView.url = Qt.resolvedUrl("test1.html") + verify(webEngineView.waitForLoadSucceeded()) + verify(verifyData()) + + webEngineView.save(filePath, saveFormat) + downLoadRequestedSpy.wait() + compare(downLoadRequestedSpy.count, 1) + compare(downloadUrl, webEngineView.url) + compare(savePageFormat, saveFormat) + compare(downloadDir, fileDir) + compare(downloadFileName, fileName) + compare(isSavePageDownload, true) + compare(downloadState[0], WebEngineDownloadRequest.DownloadInProgress) + downloadFinishedSpy.wait() + compare(downloadFinishedSpy.count, 1) + compare(totalBytes, receivedBytes) + compare(downloadState[1], WebEngineDownloadRequest.DownloadCompleted) + + // load some other data + webEngineView.url = Qt.resolvedUrl("about:blank") + verify(webEngineView.waitForLoadSucceeded()) + + // load save file to view + webEngineView.url = Qt.resolvedUrl(filePath) + verify(webEngineView.waitForLoadSucceeded()) + verify(verifyData()) + } + + function test_saveImage_data() { + return [ + { tag: "Auto accept", autoCancel: false }, + { tag: "Cancel", autoCancel: true }, + ]; + } + + function test_saveImage(row) { + autoCancel = row.autoCancel + + var fileDir = tempDir.path() + var fileName = "favicon.png" + var filePath = fileDir + "/"+ fileName + + // Load an image + webEngineView.url = Qt.resolvedUrl("icons/favicon.png") + verify(webEngineView.waitForLoadSucceeded()) + + webEngineView.save(filePath) + downLoadRequestedSpy.wait() + compare(downLoadRequestedSpy.count, 1) + compare(downloadUrl, webEngineView.url) + compare(downloadDir, fileDir) + compare(downloadFileName, fileName) + compare(isSavePageDownload, true) + compare(downloadState[0], WebEngineDownloadRequest.DownloadInProgress) + downloadFinishedSpy.wait() + compare(downloadFinishedSpy.count, 1) + if (autoCancel) { + compare(receivedBytes, 0) + compare(downloadState[1], WebEngineDownloadRequest.DownloadCancelled) + } else { + compare(totalBytes, receivedBytes) + compare(downloadState[1], WebEngineDownloadRequest.DownloadCompleted) + } + } + + function test_saveWebAction() { + // Load an image + webEngineView.url = Qt.resolvedUrl("icons/favicon.png") + verify(webEngineView.waitForLoadSucceeded()) + + // Saving without specifying path shouldn't be auto accepted + webEngineView.triggerWebAction(WebEngineView.SavePage) + downLoadRequestedSpy.wait() + compare(downLoadRequestedSpy.count, 1) + compare(downloadUrl, webEngineView.url) + compare(isSavePageDownload, true) + // The initial download request starts from DownloadRequested state, + // which means it wasn't automatically accepted. + compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested) + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_scrollPosition.qml b/tests/auto/quick/qmltests/data/tst_scrollPosition.qml index 24b352dde..cc7d15e4c 100644 --- a/tests/auto/quick/qmltests/data/tst_scrollPosition.qml +++ b/tests/auto/quick/qmltests/data/tst_scrollPosition.qml @@ -1,35 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.2 -import QtQuick.Window 2.0 -import QtTest 1.0 -import QtWebEngine 1.3 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -61,7 +35,7 @@ TestWebEngineView { tryCompare(scrollPositionSpy, "count", 1); compare(webEngineView.scrollPosition.x, 0); - compare(webEngineView.scrollPosition.y, 600 * Screen.devicePixelRatio); + compare(webEngineView.scrollPosition.y, 600); } function test_scrollPositionAfterReload() { @@ -74,13 +48,13 @@ TestWebEngineView { // Wait for proper scroll position change otherwise we cannot expect // the new y position after reload. tryCompare(webEngineView.scrollPosition, "x", 0); - tryCompare(webEngineView.scrollPosition, "y", 600 * Screen.devicePixelRatio); + tryCompare(webEngineView.scrollPosition, "y", 600); webEngineView.reload(); verify(webEngineView.waitForLoadSucceeded()); tryCompare(webEngineView.scrollPosition, "x", 0); - tryCompare(webEngineView.scrollPosition, "y", 600 * Screen.devicePixelRatio); + tryCompare(webEngineView.scrollPosition, "y", 600); } } } diff --git a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml index 2ff4f9c3c..f47674aa7 100644 --- a/tests/auto/quick/qmltests/data/tst_settings.qml +++ b/tests/auto/quick/qmltests/data/tst_settings.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -36,6 +11,7 @@ TestWebEngineView { height: 300 TestCase { + id: testCase name: "WebEngineViewSettings" function test_javascriptEnabled() { @@ -75,7 +51,7 @@ TestWebEngineView { } function test_settingsAffectCurrentViewOnly() { - var webEngineView2 = Qt.createQmlObject('TestWebEngineView {width: 400; height: 300;}', webEngineView); + var webEngineView2 = Qt.createQmlObject('TestWebEngineView {width: 400; height: 300;}', testCase); webEngineView.settings.javascriptEnabled = true; webEngineView2.settings.javascriptEnabled = true; @@ -102,6 +78,68 @@ TestWebEngineView { webEngineView2.destroy(); } + + function test_disableReadingFromCanvas_data() { + return [ + { tag: 'disabled', disableReadingFromCanvas: false, result: true }, + { tag: 'enabled', disableReadingFromCanvas: true, result: false }, + ] + } + + function test_disableReadingFromCanvas(data) { + webEngineView.settings.readingFromCanvasEnabled = !data.disableReadingFromCanvas; + webEngineView.loadHtml("<html><body>" + + "<canvas id='myCanvas' width='200' height='40' style='border:1px solid #000000;'></canvas>" + + "</body></html>"); + verify(webEngineView.waitForLoadSucceeded()); + verify(webEngineView.settings.readingFromCanvasEnabled === !data.disableReadingFromCanvas ) + + var jsCode = "(function(){" + + " var canvas = document.getElementById(\"myCanvas\");" + + " var ctx = canvas.getContext(\"2d\");" + + " ctx.fillStyle = \"rgb(255,0,255)\";" + + " ctx.fillRect(0, 0, 200, 40);" + + " try {" + + " src = canvas.toDataURL();" + + " }" + + " catch(err) {" + + " src = \"\";" + + " }" + + " return src.length ? true : false;" + + "})();"; + + var isDataRead = false; + runJavaScript(jsCode, function(result) { + isDataRead = result + }); + tryVerify(function() { return isDataRead === data.result }); + } + + function test_forceDarkMode() { + // based on: https://developer.chrome.com/blog/auto-dark-theme/#detecting-auto-dark-theme + webEngineView.loadHtml("<html><body>" + + "<div id=\"detection\", style=\"display: none; background-color: canvas; color-scheme: light\"</div>" + + "</body></html>"); + const script = "(() => {" + + " const detectionDiv = document.querySelector('#detection');" + + " return getComputedStyle(detectionDiv).backgroundColor != 'rgb(255, 255, 255)';" + + "})()"; + verify(webEngineView.waitForLoadSucceeded()); + + var isAutoDark = true; + runJavaScript(script, result => isAutoDark = result); + tryVerify(() => {return !isAutoDark}); + + webEngineView.settings.forceDarkMode = true; + verify(webEngineView.settings.forceDarkMode == true) + + isAutoDark = false; + // the page is not updated immediately + tryVerify(function() { + runJavaScript(script, result => isAutoDark = result); + return isAutoDark; + }); + } } } diff --git a/tests/auto/quick/qmltests/data/tst_titleChanged.qml b/tests/auto/quick/qmltests/data/tst_titleChanged.qml index 7dda5ce33..66a7c115f 100644 --- a/tests/auto/quick/qmltests/data/tst_titleChanged.qml +++ b/tests/auto/quick/qmltests/data/tst_titleChanged.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView diff --git a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml index 69aa76b77..76363fa71 100644 --- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml +++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -import QtQuick 2.0 -import QtTest 1.0 -import QtWebEngine 1.2 +import QtQuick +import QtTest +import QtWebEngine Item { id: parentItem @@ -37,8 +12,12 @@ Item { property var pressEvents: [] property var releaseEvents: [] - Keys.onPressed: pressEvents.push(event.key) - Keys.onReleased: releaseEvents.push(event.key) + Keys.onPressed: function(event) { + pressEvents.push(event.key) + } + Keys.onReleased: function(event) { + releaseEvents.push(event.key) + } TestWebEngineView { id: webEngineView @@ -46,6 +25,7 @@ Item { focus: true } TestCase { + id: testCase name: "WebEngineViewUnhandledKeyEventPropagation" when: false diff --git a/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml b/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml new file mode 100644 index 000000000..94c993771 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_userScriptCollection.qml @@ -0,0 +1,127 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +Item { + + WebEngineProfile { id: testProfile } + + TestWebEngineView { + id: webEngineView + width: 400 + height: 300 + } + + TestCase { + name: "UserScriptCollection" + + function cleanup() { + webEngineView.url = "" + webEngineView.userScripts.collection = [] + compare(webEngineView.userScripts.collection.length, 0) + } + + function test_collection() { + let scriptFoo = { name: "Foo", + sourceUrl: Qt.resolvedUrl("foo.js"), + injectionPoint: WebEngineScript.DocumentReady + } + let scriptBar = WebEngine.script() + + scriptBar.name = "Bar" + scriptBar.sourceUrl = Qt.resolvedUrl("bar.js") + scriptBar.injectionPoint = WebEngineScript.DocumentReady + + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.userScripts.collection = [ scriptFoo, scriptBar ] + compare(webEngineView.userScripts.collection.length, 2) + compare(webEngineView.userScripts.collection[0].name, scriptFoo.name) + compare(webEngineView.userScripts.collection[0].sourceUrl, scriptFoo.sourceUrl) + compare(webEngineView.userScripts.collection[1].name, scriptBar.name) + compare(webEngineView.userScripts.collection[1].sourceUrl, scriptBar.sourceUrl) + webEngineView.userScripts.collection = [] + compare(webEngineView.userScripts.collection.length, 0) + } + + function test_insert() { + let scriptFoo = WebEngine.script() + scriptFoo.name = "Foo" + scriptFoo.sourceUrl = Qt.resolvedUrl("foo.js") + scriptFoo.injectionPoint = WebEngineScript.DocumentReady + let scriptBar = WebEngine.script() + scriptBar.name = "Bar" + scriptBar.sourceUrl = Qt.resolvedUrl("bar.js") + scriptBar.injectionPoint = WebEngineScript.DocumentReady + + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.userScripts.insert(scriptFoo) + webEngineView.userScripts.insert(scriptBar) + compare(webEngineView.userScripts.collection.length, 2) + compare(webEngineView.userScripts.collection[0].name, scriptFoo.name) + compare(webEngineView.userScripts.collection[1].name, scriptBar.name) + webEngineView.userScripts.collection = [] + compare(webEngineView.userScripts.collection.length, 0) + + var list = [ scriptFoo , scriptBar] + webEngineView.userScripts.insert(list) + compare(webEngineView.userScripts.collection.length, 2) + compare(webEngineView.userScripts.collection[0].name, scriptFoo.name) + compare(webEngineView.userScripts.collection[1].name, scriptBar.name) + } + + function test_find() { + let scriptA = WebEngine.script() + scriptA.name = "A" + scriptA.sourceUrl = Qt.resolvedUrl("A.js") + let scriptB = WebEngine.script() + scriptB.name = "A" + scriptB.sourceUrl = Qt.resolvedUrl("B.js") + let scriptC = WebEngine.script() + scriptC.name = "C" + scriptC.sourceUrl = Qt.resolvedUrl("C.js") + + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.userScripts.collection = [ scriptA, scriptB, scriptC ]; + compare(webEngineView.userScripts.collection.length, 3) + let scriptsA = webEngineView.userScripts.find("A") + let scriptsB = webEngineView.userScripts.find("B") + let scriptsC = webEngineView.userScripts.find("C") + compare(scriptsA.length, 2) + compare(scriptsB.length, 0) + compare(scriptsC.length, 1) + compare(scriptsA[0].name, scriptA.name) + compare(scriptsA[0].sourceUrl, scriptA.sourceUrl) + compare(scriptsA[1].name, scriptB.name) + compare(scriptsA[1].sourceUrl, scriptB.sourceUrl) + compare(scriptsC[0].name, scriptC.name) + compare(scriptsC[0].sourceUrl, scriptC.sourceUrl) + } + + function test_contains() { + let scriptFoo = WebEngine.script() + scriptFoo.name = "Foo" + let scriptBar = WebEngine.script() + scriptBar.name = "Bar" + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.userScripts.collection = [ scriptFoo ] + compare(webEngineView.userScripts.collection.length, 1) + verify(webEngineView.userScripts.contains(scriptFoo)) + verify(!webEngineView.userScripts.contains(scriptBar)) + } + + function test_clear() { + let scriptFoo = WebEngine.script() + scriptFoo.name = "Foo" + let scriptBar = WebEngine.script() + scriptBar.name = "Bar" + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.userScripts.collection = [ scriptFoo ]; + compare(webEngineView.userScripts.collection.length, 1) + webEngineView.userScripts.clear() + compare(webEngineView.userScripts.collection.length, 0) + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml index f4fcc30ab..30704f47b 100644 --- a/tests/auto/quick/qmltests/data/tst_userScripts.qml +++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml @@ -1,64 +1,42 @@ -/**************************************************************************** -** -** 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: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.2 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine Item { - WebEngineScript { - id: changeDocumentTitleScript - sourceUrl: Qt.resolvedUrl("change-document-title.js") - injectionPoint: WebEngineScript.DocumentReady + + function changeDocumentTitleScript() { + return { name: "changeDocumentTitleScript", + sourceUrl: Qt.resolvedUrl("change-document-title.js"), + injectionPoint: WebEngineScript.DocumentReady } } - WebEngineScript { - id: appendDocumentTitleScript - sourceUrl: Qt.resolvedUrl("append-document-title.js") - injectionPoint: WebEngineScript.DocumentReady + function appendDocumentTitleScript() { + return { sourceUrl: Qt.resolvedUrl("append-document-title.js"), + injectionPoint: WebEngineScript.DocumentReady } } - WebEngineScript { - id: bigUserScript - sourceUrl: Qt.resolvedUrl("big-user-script.js") - injectionPoint: WebEngineScript.DocumentReady + function bigUserScript() { + return { sourceUrl: Qt.resolvedUrl("big-user-script.js"), + injectionPoint: WebEngineScript.DocumentReady } } - WebEngineScript { - id: scriptWithMetadata - sourceUrl: Qt.resolvedUrl("script-with-metadata.js") + function scriptWithMetadata() { + var script = WebEngine.script() + script.sourceUrl = Qt.resolvedUrl("script-with-metadata.js") + return script } - WebEngineScript { - id: scriptWithBadMatchMetadata - sourceUrl: Qt.resolvedUrl("script-with-bad-match-metadata.js") + function scriptWithBadMatchMetadata() { + var script = WebEngine.script() + script.sourceUrl = Qt.resolvedUrl("script-with-bad-match-metadata.js") + return script } + WebEngineProfile { id: testProfile } + TestWebEngineView { id: webEngineView width: 400 @@ -76,24 +54,40 @@ Item { width: 400 height: 300 - onNavigationRequested: { + onNavigationRequested: function(request) { var urlString = request.url.toString(); if (urlString.indexOf("test1.html") !== -1) - userScripts = [ changeDocumentTitleScript ]; + userScripts.collection = [ changeDocumentTitleScript() ]; else if (urlString.indexOf("test2.html") !== -1) - userScripts = [ appendDocumentTitleScript ]; + userScripts.collection = [ appendDocumentTitleScript() ]; else - userScripts = []; + userScripts.collection = []; } } TestCase { - name: "WebEngineViewUserScripts" + name: "UserScripts" - function init() { + function cleanup() { webEngineView.url = ""; - webEngineView.userScripts = []; - webEngineView.profile.userScripts = []; + webEngineView.userScripts.collection = []; + compare(webEngineView.userScripts.collection.length, 0) + webEngineView.profile.userScripts.collection = []; + compare(webEngineView.profile.userScripts.collection.length, 0) + } + + function test_profileScripts() { + // assusme it is the same type as in View + let t1 = String(testProfile.userScripts), t2 = String(webEngineView.userScripts) + compare(t1.substr(0, t1.indexOf('(')), t2.substr(0, t2.indexOf('('))) + + // ... and just test basic things like access + compare(testProfile.userScripts.collection, []) + let script = changeDocumentTitleScript() + testProfile.userScripts.collection = [ script ] + + compare(testProfile.userScripts.collection.length, 1) + compare(testProfile.userScripts.collection[0].name, script.name) } function test_oneScript() { @@ -101,7 +95,10 @@ Item { webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "Test page 1"); - webEngineView.userScripts = [ changeDocumentTitleScript ]; + let script = changeDocumentTitleScript() + webEngineView.userScripts.collection = [ script ] + compare(webEngineView.userScripts.collection.length, 1) + compare(webEngineView.userScripts.collection[0].name, script.name) compare(webEngineView.title, "Test page 1"); webEngineView.reload(); @@ -112,7 +109,8 @@ Item { webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "New title"); - webEngineView.userScripts = []; + webEngineView.userScripts.collection = []; + compare(webEngineView.userScripts.collection.length, 0) compare(webEngineView.title, "New title"); webEngineView.reload(); @@ -124,23 +122,28 @@ Item { webEngineView.url = Qt.resolvedUrl("test1.html"); webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "Test page 1"); - - webEngineView.userScripts = [ changeDocumentTitleScript, appendDocumentTitleScript ]; + var script1 = changeDocumentTitleScript(); + var script2 = appendDocumentTitleScript(); + script2.injectionPoint = WebEngineScript.Deferred; + webEngineView.userScripts.collection = [ script1, script2 ]; + compare(webEngineView.userScripts.collection.length, 2) // Make sure the scripts are loaded in order. - appendDocumentTitleScript.injectionPoint = WebEngineScript.Deferred webEngineView.reload(); webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "New title with appendix"); - appendDocumentTitleScript.injectionPoint = WebEngineScript.DocumentReady - changeDocumentTitleScript.injectionPoint = WebEngineScript.Deferred + script2.injectionPoint = WebEngineScript.DocumentReady + script1.injectionPoint = WebEngineScript.Deferred + webEngineView.userScripts.collection = [ script1, script2 ]; + compare(webEngineView.userScripts.collection.length, 2) webEngineView.reload(); webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "New title"); // Make sure we can remove scripts from the preload list. - webEngineView.userScripts = [ appendDocumentTitleScript ]; + webEngineView.userScripts.collection = [ script2 ]; + compare(webEngineView.userScripts.collection.length, 1) webEngineView.reload(); webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView, "title", "Test page 1 with appendix"); @@ -163,17 +166,21 @@ Item { } function test_bigScript() { - webEngineView.userScripts = [ bigUserScript ]; + webEngineView.userScripts.collection = [ bigUserScript() ]; + compare(webEngineView.userScripts.collection.length, 1) webEngineView.url = Qt.resolvedUrl("test1.html"); webEngineView.waitForLoadSucceeded(); tryCompare(webEngineView , "title", "Big user script changed title"); } function test_parseMetadataHeader() { - compare(scriptWithMetadata.name, "Test script"); - compare(scriptWithMetadata.injectionPoint, WebEngineScript.DocumentReady); + var script = scriptWithMetadata() + compare(script.name, "Test script"); + compare(script.injectionPoint, WebEngineScript.DocumentReady); - webEngineView.userScripts = [ scriptWithMetadata ]; + webEngineView.userScripts.collection = [ script ]; + compare(webEngineView.userScripts.collection.length, 1) + compare(webEngineView.userScripts.collection[0].name, script.name) // @include *data/test*.html webEngineView.url = Qt.resolvedUrl("test1.html"); @@ -197,10 +204,12 @@ Item { } function test_dontInjectBadUrlPatternsEverywhere() { - compare(scriptWithBadMatchMetadata.name, "Test bad match script"); - compare(scriptWithBadMatchMetadata.injectionPoint, WebEngineScript.DocumentReady); + var script = scriptWithBadMatchMetadata(); + compare(script.name, "Test bad match script"); + compare(script.injectionPoint, WebEngineScript.DocumentReady); - webEngineView.userScripts = [ scriptWithBadMatchMetadata ]; + webEngineView.userScripts.collection = [ script ]; + compare(webEngineView.userScripts.collection.length, 1) // @match some:junk webEngineView.url = Qt.resolvedUrl("test2.html"); @@ -209,7 +218,10 @@ Item { } function test_profileWideScript() { - webEngineView.profile.userScripts = [ changeDocumentTitleScript ]; + let script = changeDocumentTitleScript() + webEngineView.profile.userScripts.collection = [ script ]; + compare(webEngineView.profile.userScripts.collection.length, 1) + compare(webEngineView.profile.userScripts.collection[0].name, script.name) webEngineView.url = Qt.resolvedUrl("test1.html"); webEngineView.waitForLoadSucceeded(); diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml index 4966a052a..d4449f7de 100644 --- a/tests/auto/quick/qmltests/data/tst_viewSource.qml +++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** 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: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 +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine TestWebEngineView { id: webEngineView @@ -38,9 +13,15 @@ TestWebEngineView { property var viewRequest: null SignalSpy { + id: loadSpy + target: webEngineView + signalName: 'loadingChanged' + } + + SignalSpy { id: newViewRequestedSpy target: webEngineView - signalName: "newViewRequested" + signalName: "newWindowRequested" } SignalSpy { @@ -49,13 +30,13 @@ TestWebEngineView { signalName: "titleChanged" } - onNewViewRequested: { + onNewWindowRequested: function(request) { viewRequest = { "destination": request.destination, "userInitiated": request.userInitiated }; - request.openIn(webEngineView); + webEngineView.acceptAsNewWindow(request); } TestCase { @@ -68,6 +49,7 @@ TestWebEngineView { tryCompare(webEngineView, "loadStatus", WebEngineView.LoadSucceededStatus); webEngineView.loadStatus = null; + loadSpy.clear(); newViewRequestedSpy.clear(); titleChangedSpy.clear(); viewRequest = null; @@ -86,7 +68,7 @@ TestWebEngineView { // The first titleChanged signal is emitted by adoptWebContents() tryVerify(function() { return titleChangedSpy.count >= 2; }); - compare(viewRequest.destination, WebEngineView.NewViewInTab); + compare(viewRequest.destination, WebEngineNewWindowRequest.InNewTab); verify(viewRequest.userInitiated); verify(!webEngineView.action(WebEngineView.ViewSource).enabled); @@ -94,36 +76,6 @@ TestWebEngineView { compare(webEngineView.url, "view-source:" + Qt.resolvedUrl("test1.html")); } - function test_viewSourceURL_data() { - var testLocalUrl = "view-source:" + Qt.resolvedUrl("test1.html"); - var testLocalUrlWithoutScheme = "view-source:" + Qt.resolvedUrl("test1.html").substring(7); - - return [ - { tag: "view-source:", userInputUrl: "view-source:", loadSucceed: true, url: "view-source:", title: "view-source:" }, - { 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: "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" }, - ]; - } - - function test_viewSourceURL(row) { - WebEngine.settings.errorPageEnabled = true - webEngineView.url = row.userInputUrl; - - if (row.loadSucceed) { - tryCompare(webEngineView, "loadStatus", WebEngineView.LoadSucceededStatus); - } else { - tryCompare(webEngineView, "loadStatus", WebEngineView.LoadFailedStatus, 15000); - } - tryVerify(function() { return titleChangedSpy.count == 1; }); - - compare(webEngineView.url, row.url); - tryCompare(webEngineView, "title", row.title); - verify(!webEngineView.action(WebEngineView.ViewSource).enabled); - } - function test_viewSourceCredentials() { var url = "http://user:passwd@httpbin.org/basic-auth/user/passwd"; @@ -145,12 +97,46 @@ TestWebEngineView { // The first titleChanged signal is emitted by adoptWebContents() tryVerify(function() { return titleChangedSpy.count >= 2; }); - compare(viewRequest.destination, WebEngineView.NewViewInTab); + compare(viewRequest.destination, WebEngineNewWindowRequest.InNewTab); verify(viewRequest.userInitiated); tryCompare(webEngineView, "url", "view-source:" + url.replace("user:passwd@", "")); tryCompare(webEngineView, "title", "view-source:" + url.replace("http://user:passwd@", "")); } + + function test_viewSourceURL_data() { + var testLocalUrl = "view-source:" + Qt.resolvedUrl("test1.html"); + var testLocalUrlWithoutScheme = "view-source:" + Qt.resolvedUrl("test1.html").toString().substring(7); + + return [ + { tag: "view-source:", userInputUrl: "view-source:", loadSucceed: true, url: "view-source:", title: "view-source:" }, + { 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: "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" }, + ]; + } + + function test_viewSourceURL(row) { + WebEngine.settings.errorPageEnabled = true + webEngineView.url = row.userInputUrl; + + tryCompare(loadSpy, 'count', 2, 12000); + let load = loadSpy.signalArguments[1][0] + let expectedStatus = row.loadSucceed ? WebEngineView.LoadSucceededStatus : WebEngineView.LoadFailedStatus + compare(load.status, expectedStatus); + compare(load.isErrorPage, !row.loadSucceed); + tryVerify(function() { return titleChangedSpy.count == 1; }); + + compare(webEngineView.url, row.url); + tryCompare(webEngineView, "title", row.title); + if (row.loadSucceed) { + verify(!webEngineView.action(WebEngineView.ViewSource).enabled); + } else { + verify(webEngineView.action(WebEngineView.ViewSource).enabled); + } + } } } diff --git a/tests/auto/quick/qmltests/data/tst_webchannel.qml b/tests/auto/quick/qmltests/data/tst_webchannel.qml index 3ca3ccce1..780b55934 100644 --- a/tests/auto/quick/qmltests/data/tst_webchannel.qml +++ b/tests/auto/quick/qmltests/data/tst_webchannel.qml @@ -1,35 +1,11 @@ -/********************************************************************* -** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> -** 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.2 - -import QtWebChannel 1.0 +// Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest +import QtWebEngine + +import QtWebChannel Item { id: test @@ -81,6 +57,12 @@ Item { } function test_basic() { + webView.userScripts.collection = [ { + name: "qtwebchanneljs", + sourceUrl: Qt.resolvedUrl("qrc:/qtwebchannel/qwebchannel.js"), + injectionPoint: WebEngineScript.DocumentCreation, + worldId: WebEngineScript.MainWorld + }] webView.url = testUrl; verify(webView.waitForLoadSucceeded()); diff --git a/tests/auto/quick/qmltests/data/webchannel-test.html b/tests/auto/quick/qmltests/data/webchannel-test.html index 92966b24a..d8c3b1305 100644 --- a/tests/auto/quick/qmltests/data/webchannel-test.html +++ b/tests/auto/quick/qmltests/data/webchannel-test.html @@ -2,7 +2,6 @@ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> <script type="text/javascript"> //BEGIN SETUP var channel = new QWebChannel(qt.webChannelTransport, function(channel) { diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/AlertDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/AlertDialog.qml deleted file mode 100644 index 4ba3be4b9..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/AlertDialog.qml +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ - -// Both dialogs are basically expected to behave in the same way from an API point of view -ConfirmDialog -{ -} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/ConfirmDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/ConfirmDialog.qml deleted file mode 100644 index 9933fc2f7..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/ConfirmDialog.qml +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** 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: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 QtQml 2.0 -import QtTest 1.0 -import "../../TestParams" 1.0 - -QtObject { - property string text; - property string title; - signal accepted(); - signal rejected(); - - function open() { - JSDialogParams.dialogTitle = title; - JSDialogParams.dialogMessage = text; - JSDialogParams.dialogCount++; - if (JSDialogParams.shouldAcceptDialog) - accepted() - else - rejected() - } -} - diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/FilePicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/FilePicker.qml deleted file mode 100644 index 5d78807df..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/FilePicker.qml +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** 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: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.2 -import "../../TestParams" 1.0 - -QtObject { - property bool selectMultiple: false; - property bool selectExisting: false; - property bool selectFolder: false; - - signal filesSelected(var fileList); - signal rejected(); - - function open() { - FilePickerParams.filePickerOpened = true; - if (FilePickerParams.selectFiles) - filesSelected(FilePickerParams.selectedFilesUrl) - else - rejected() - } -} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml deleted file mode 100644 index 36efa7680..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** 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 deleted file mode 100644 index e61f4c230..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** 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/mock-delegates/QtWebEngine/Controls1Delegates/PromptDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/PromptDialog.qml deleted file mode 100644 index 7c5b16eab..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/PromptDialog.qml +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** 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: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 QtQml 2.0 -import QtTest 1.0 -import "../../TestParams" 1.0 - -QtObject { - property string text; - property string title; - signal accepted(); - signal rejected(); - signal input(string text); - signal closing(); - - function open() { - JSDialogParams.dialogTitle = title; - JSDialogParams.dialogMessage = text; - JSDialogParams.dialogCount++; - if (JSDialogParams.shouldAcceptDialog) { - input(JSDialogParams.inputForPrompt) - accepted() - } else { - rejected() - } - } -} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/qmldir b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/qmldir deleted file mode 100644 index cf8ac0512..000000000 --- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/qmldir +++ /dev/null @@ -1,5 +0,0 @@ -module QtWebEngine.UIDelegates -AlertDialog 1.0 AlertDialog.qml -ConfirmDialog 1.0 ConfirmDialog.qml -FilePicker 1.0 FilePicker.qml -PromptDialog 1.0 PromptDialog.qml diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml new file mode 100644 index 000000000..7d7efda0c --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/AlertDialog.qml @@ -0,0 +1,5 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +// Both dialogs are basically expected to behave in the same way from an API point of view +ConfirmDialog { } diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml new file mode 100644 index 000000000..6125d0b98 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/ConfirmDialog.qml @@ -0,0 +1,24 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQml +import QtTest +import "../../TestParams" + +QtObject { + property string text + property string title + signal accepted() + signal rejected() + + function open() { + JSDialogParams.dialogTitle = title; + JSDialogParams.dialogMessage = text; + JSDialogParams.dialogCount++; + if (JSDialogParams.shouldAcceptDialog) + accepted(); + else + rejected(); + } +} + diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml new file mode 100644 index 000000000..71da28843 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/DirectoryPicker.qml @@ -0,0 +1,18 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import "../../TestParams" + +QtObject { + signal folderSelected(var folder) + signal rejected() + + function open() { + FilePickerParams.directoryPickerOpened = true; + if (FilePickerParams.selectFiles) + folderSelected(FilePickerParams.selectedFilesUrl); + else + rejected(); + } +} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml new file mode 100644 index 000000000..247088bcb --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/FilePicker.qml @@ -0,0 +1,24 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import "../../TestParams" + +QtObject { + property bool selectMultiple: false + property bool selectExisting: false + property bool selectFolder: false + property var nameFilters: [] + + signal filesSelected(var fileList) + signal rejected() + + function open() { + FilePickerParams.filePickerOpened = true; + FilePickerParams.nameFilters = nameFilters; + if (FilePickerParams.selectFiles) + filesSelected(FilePickerParams.selectedFilesUrl); + else + rejected(); + } +} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml new file mode 100644 index 000000000..cd7ed4821 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/Menu.qml @@ -0,0 +1,18 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import QtQml +import "../../TestParams" + +QtObject { + id: menu + property string linkText: "" + property var mediaType: null + property string selectedText: "" + + signal done() + + function open() { + MenuParams.isMenuOpened = true; + } +} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml new file mode 100644 index 000000000..67dab1bba --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/MenuItem.qml @@ -0,0 +1,8 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import QtQml + +QtObject { + signal triggered() +} diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml new file mode 100644 index 000000000..81a63d918 --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/ControlsDelegates/PromptDialog.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQml +import QtTest +import "../../TestParams" + +QtObject { + property string text + property string title + signal accepted() + signal rejected() + signal input(string text) + signal closing() + + function open() { + JSDialogParams.dialogTitle = title; + JSDialogParams.dialogMessage = text; + JSDialogParams.dialogCount++; + if (JSDialogParams.shouldAcceptDialog) { + input(JSDialogParams.inputForPrompt) + accepted(); + } else { + rejected(); + } + } +} diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml index 83ac8a66e..67d67dc40 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml @@ -1,36 +1,13 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 pragma Singleton -import QtQuick 2.0 +import QtQuick QtObject { property var selectedFilesUrl: []; property bool selectFiles: false; property bool filePickerOpened: false; + property bool directoryPickerOpened: false; + property var nameFilters: []; } diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml index 70696803c..1033b509e 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/JSDialogParams.qml @@ -1,32 +1,7 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 pragma Singleton -import QtQml 2.0 +import QtQml QtObject { property string dialogMessage: ""; diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml new file mode 100644 index 000000000..d8a01764c --- /dev/null +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/MenuParams.qml @@ -0,0 +1,9 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +pragma Singleton +import QtQml + +QtObject { + property bool isMenuOpened: false; +} diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir b/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir index a21dd8236..2702ad30f 100644 --- a/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir +++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir @@ -2,4 +2,4 @@ module TestParams singleton FilePickerParams 1.0 FilePickerParams.qml singleton JSDialogParams 1.0 JSDialogParams.qml - +singleton MenuParams 1.0 MenuParams.qml diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro deleted file mode 100644 index a2b05e091..000000000 --- a/tests/auto/quick/qmltests/qmltests.pro +++ /dev/null @@ -1,124 +0,0 @@ -include(../tests.pri) - -QT += qmltest - -IMPORTPATH += $$PWD/data - -OTHER_FILES += \ - $$PWD/data/TestWebEngineView.qml \ - $$PWD/data/alert.html \ - $$PWD/data/append-document-title.js \ - $$PWD/data/big-user-script.js \ - $$PWD/data/change-document-title.js \ - $$PWD/data/download.zip \ - $$PWD/data/confirm.html \ - $$PWD/data/confirmclose.html \ - $$PWD/data/directoryupload.html \ - $$PWD/data/favicon.html \ - $$PWD/data/favicon2.html \ - $$PWD/data/favicon-candidates-gray.html \ - $$PWD/data/favicon-misc.html \ - $$PWD/data/favicon-multi.html \ - $$PWD/data/favicon-multi-gray.html \ - $$PWD/data/favicon-single.html \ - $$PWD/data/favicon-shortcut.html \ - $$PWD/data/favicon-touch.html \ - $$PWD/data/favicon-unavailable.html \ - $$PWD/data/forms.html \ - $$PWD/data/geolocation.html \ - $$PWD/data/javascript.html \ - $$PWD/data/link.html \ - $$PWD/data/localStorage.html \ - $$PWD/data/prompt.html \ - $$PWD/data/multifileupload.html \ - $$PWD/data/redirect.html \ - $$PWD/data/script-with-metadata.js \ - $$PWD/data/singlefileupload.html \ - $$PWD/data/test1.html \ - $$PWD/data/test2.html \ - $$PWD/data/test3.html \ - $$PWD/data/test4.html \ - $$PWD/data/test-iframe.html \ - $$PWD/data/keyboardModifierMapping.html \ - $$PWD/data/keyboardEvents.html \ - $$PWD/data/titleupdate.js \ - $$PWD/data/tst_action.qml \ - $$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 \ - $$PWD/data/tst_faviconDownload.qml \ - $$PWD/data/tst_filePicker.qml \ - $$PWD/data/tst_findText.qml \ - $$PWD/data/tst_focusOnNavigation.qml \ - $$PWD/data/tst_geopermission.qml \ - $$PWD/data/tst_getUserMedia.qml \ - $$PWD/data/tst_inputMethod.qml \ - $$PWD/data/tst_javaScriptDialogs.qml \ - $$PWD/data/tst_linkHovered.qml \ - $$PWD/data/tst_loadFail.qml \ - $$PWD/data/tst_loadHtml.qml \ - $$PWD/data/tst_loadProgress.qml \ - $$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 \ - $$PWD/data/tst_properties.qml \ - $$PWD/data/tst_runJavaScript.qml \ - $$PWD/data/tst_scrollPosition.qml \ - $$PWD/data/tst_titleChanged.qml \ - $$PWD/data/tst_unhandledKeyEventPropagation.qml \ - $$PWD/data/tst_userScripts.qml \ - $$PWD/data/tst_viewSource.qml \ - $$PWD/data/tst_webchannel.qml \ - $$PWD/data/tst_settings.qml \ - $$PWD/data/tst_keyboardModifierMapping.qml \ - $$PWD/data/tst_keyboardEvents.qml \ - $$PWD/data/webchannel-test.html \ - $$PWD/data/icons/favicon.png \ - $$PWD/data/icons/gray128.png \ - $$PWD/data/icons/gray16.png \ - $$PWD/data/icons/gray255.png \ - $$PWD/data/icons/gray32.png \ - $$PWD/data/icons/gray64.png \ - $$PWD/data/icons/grayicons.ico \ - $$PWD/data/icons/small-favicon.png \ - $$PWD/data/icons/qt144.png \ - $$PWD/data/icons/qt32.ico \ - $$PWD/data/icons/qtmulti.ico \ - $$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 \ - $$PWD/mock-delegates/TestParams/JSDialogParams.qml \ - $$PWD/mock-delegates/TestParams/qmldir \ - -load(qt_build_paths) -DEFINES += QUICK_TEST_SOURCE_DIR=\\\"$$re_escape($$PWD$${QMAKE_DIR_SEP}data)\\\" - -!qtConfig(webengine-testsupport) { - PLUGIN_EXTENSION = .so - PLUGIN_PREFIX = lib - osx: PLUGIN_PREFIX = .dylib - win32 { - PLUGIN_EXTENSION = .dll - PLUGIN_PREFIX = - } - - TESTSUPPORT_MODULE = $$shell_path($$[QT_INSTALL_QML]/QtWebEngine/testsupport/$${PLUGIN_PREFIX}qtwebenginetestsupportplugin$${PLUGIN_EXTENSION}) - BUILD_DIR = $$shell_path($$clean_path($$OUT_PWD/../../../..)) - SRC_DIR = $$shell_path($$clean_path($$PWD/../../../..)) - - warning("QML Test Support API is disabled. This means some QML tests that use Test Support API will fail.") - warning("Use the following command to build Test Support module and rebuild WebEngineView API:") - warning("cd $$BUILD_DIR && qmake -r $$shell_path($$SRC_DIR/qtwebengine.pro -- --feature-testsupport=yes) && make -C $$shell_path($$BUILD_DIR/src/webengine) clean && make") - warning("After performing the command above make sure QML module \"QtWebEngine.testsupport\" is deployed at $$TESTSUPPORT_MODULE") -} diff --git a/tests/auto/quick/qmltests/resources/server.key b/tests/auto/quick/qmltests/resources/server.key new file mode 100644 index 000000000..9bf87aee3 --- /dev/null +++ b/tests/auto/quick/qmltests/resources/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAqAygFPG5ILLb3G51D0OIN4Kpm5t3Oh1nByTnvi1kMz+sCBBd +CSugt4NnKkB6kiGtMEsrEm1/xg8Bkfbpet3v3+jAidRpjvCISqy3Z9D1cgCFM46h +iob/AvLZpqITiAgsU4fJ4auuIKhFplIGrIKMv2gK8haoBGBoRUD1RM+irwjEr6TN +XTQt2Ap+Ouxs53NLPhAOgumpfzzRR8/Umbhen+G5MhH+XTzzreiClz2V6A79ePJj +y1uQ8NJ79feOOWBDRizRDWwxsnNd24GjkpvcaTwafiK6Vdqeub+XTtiB5RPal2on +Cj0TQDcnaacecl/zmUWsIFNkNJWDcd3/vEdyOQIDAQABAoIBAQCW93icOCdim6tu +FIDu7HEjxSsPUpPCToWu4lWaAHcinxGx0NlzkpD4K4DzcSdrvfszBmQ0UtBVokd7 +1IAdU+HZmePWLk+CDM2zoAPHrO3Cs3r2PS0cIHhZMsearcG0E/uWMseHB08PoXuo +lcnPEhzVGueyYe4guGcTx+5PGeUBLf+fJcEc3rIQnT2LYulM2aqBZSQM3jRUaPYs +F0awDpCNwajW/Bt2VB14Pr+H5MJ+WSznFCqW7SolBkqDGfKckXPSHgX6xZ0y7VCI +MM8vwlVI4mPkaHvSQMSI8vS4Qh+SGQCSs/AuuNLjjPoz1YotV3Ih4YbLj6BjFP2g +CrqzT6VNAoGBANOHmsqE0nRkLzonTDrMdla5b0TjTxwtNM5DjLgJa6UBBqPe+1Lv +JFoBP9bIfYDRWZOZrxXItfMmM43nK/ST6Xqgx1IpHUCLKVr2pA9RXrP+m4oawfgn +frW212fHibeOYiLy+DaQXQ0VRFxsc/VbwKVyVlMEcNg3N93x2E67M7vjAoGBAMtg +7wDa+5gjwuyNr7LKkp5VDTmtKQhoDtg4sw6MSQSMF6fJT9Z4kGTZ23+G85/LsM/k +iXbceabGJ0CQJvGn6oW4dI2Ut2c2nCNVbQCxJ6Nyn/yW7bRLShMnwXvbGAVxVUax +5ohJPZGJ8ar2CP76A0bkvm2Nwylq2gp6Y8h7+iwzAoGBAKizwfQ6sk45iKDsrpNG +dir8gY2DbJigRTksDpLIkJ1skAspz295YpiV3oBCLjYKwVJCg6zwAo0FrqBB+oB5 +ZwByMgWI3NeZJUZy5q2Ay/Lp4MroRELR3PC3/lu6fE90szgEZ4m84TmJ+Jdtt527 +q41H/yj+pbELePb95vIDw2LZAoGBAJBZ+MmupCzUFSI5Xp+UUIS48W4ijaE92mt1 +swF8aMcleBTLOjOL11D9oGHfs0OUG6czGq6WxnGs62dT6ZBUEo1e4rsq9xH3HNOn +anq3Qt8sGIn7xjPVzHnUGeyDEYWrb0+CLZJGCcEnG7SwdKolYfYLnW281Oysvp35 +SKGf/W0pAoGAa2+sZmhb1mpGAf6Bi4z+uym/6qOJmG6CnrBSM9e/r8nujwFVkCYF +3iz48qx3GbuliO6za8aM1drX2u8KWp1uP5KzwYvtW5SfpQ1eusFblHEYQQNRcKLT +j/wZBXnU961eMKkkTe2XsPirO8rVhVmxuFLqT/aEPffcragQFFIGOEQ= +-----END RSA PRIVATE KEY----- diff --git a/tests/auto/quick/qmltests/resources/server.pem b/tests/auto/quick/qmltests/resources/server.pem new file mode 100644 index 000000000..a201ed08e --- /dev/null +++ b/tests/auto/quick/qmltests/resources/server.pem @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIUFZEIIzeR7lEA10rb14w7MfhP87MwDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy +bGluMRUwEwYDVQQKDAxUaGVRdENvbXBhbnkxEjAQBgNVBAsMCXdlYmVuZ2luZTAe +Fw0yMTA1MTAyMTM1MTJaFw0yMjA1MTAyMTM1MTJaMGAxCzAJBgNVBAYTAkRFMQ8w +DQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEVMBMGA1UECgwMVGhlUXRD +b21wYW55MRgwFgYDVQQDDA93ZWJlbmdpbmUucXQuaW8wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCoDKAU8bkgstvcbnUPQ4g3gqmbm3c6HWcHJOe+LWQz +P6wIEF0JK6C3g2cqQHqSIa0wSysSbX/GDwGR9ul63e/f6MCJ1GmO8IhKrLdn0PVy +AIUzjqGKhv8C8tmmohOICCxTh8nhq64gqEWmUgasgoy/aAryFqgEYGhFQPVEz6Kv +CMSvpM1dNC3YCn467Gznc0s+EA6C6al/PNFHz9SZuF6f4bkyEf5dPPOt6IKXPZXo +Dv148mPLW5Dw0nv19445YENGLNENbDGyc13bgaOSm9xpPBp+IrpV2p65v5dO2IHl +E9qXaicKPRNANydppx5yX/OZRawgU2Q0lYNx3f+8R3I5AgMBAAGjMzAxMBoGA1Ud +EQQTMBGCD3dlYmVuZ2luZS5xdC5pbzATBgNVHSUEDDAKBggrBgEFBQcDATANBgkq +hkiG9w0BAQsFAAOCAQEAjThKpP0sBv1vEmaqBc1wTu//7RHmFcoStTt3scADzb2C +9gjOVC4NzxBneLkv01444Z1p/Iiu/ZZ+VKu7aJElJgnBWEisYwJ09t3cdZRA0UY7 +XRvTVAqV0OlsB1Jn0afE+aTLGjWo+jSYzua0O+NK74e23p9jkdSmXxH9w0FB/oyM +FGIOFnnfP0+QR4ZVvAGk2H60tBHQKmCM6b87TiD4GQIfOghCQWH+qJYSuyGu4hkE +uis+n1KHHhed3GIJOHpm7gt1C9qtjcp1nOpv0ycQjfc9CGvr02BcQjhMeO65hX0A +TvCgKN9/XMFv5jwwjjPCL12GBhwnN2k9hM/tEYpe2A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDOzCCAiMCFDwWg4NZxCplj3qyBxAUTi1wmj4jMA0GCSqGSIb3DQEBCwUAMFox +CzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEV +MBMGA1UECgwMVGhlUXRDb21wYW55MRIwEAYDVQQLDAl3ZWJlbmdpbmUwHhcNMjEw +NTEwMjEzMTE4WhcNMjIwNTEwMjEzMTE4WjBaMQswCQYDVQQGEwJERTEPMA0GA1UE +CAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFTATBgNVBAoMDFRoZVF0Q29tcGFu +eTESMBAGA1UECwwJd2ViZW5naW5lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAuc/8xVrfSzOsI6kYul+o1QIPBh1I86eQm1PhTBDMAAPHuzyPaEMgBkn2 +XAUmvkynGpNioaJDU2ndV2fBHvsoeQCdNNmjFTe1rKYjrN6U2X5KoYSzN93TOYzK +aR38fEFx+w4qV76nnxSjYtGNe9z74GrfWFMdDQ0NJKzvaO4gaZ+OOg0OzWy4MJQ0 +aINo3UV55Y7Nt92AxFweiuHucKu+rjf3BX7n0Af/Tcs2c84f0R3HA7euReSibVvX +f33eHLRKwu2bvDjXiUzOdkxBn9GTo6Q09LyY6wDG0ZdWnyCKj3NBQKBVrq+bs3Q0 +ATsWhj/PvYlZhhZh4EOlqYOhCpwv4wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCC +pLSFGJcG0zhHW+2A6ogmpn2tA8gKUZx7f0J1nwgPEoAXQqWQv/299ZtmWfMKHUkk +ygG4u80C87wWPH42XWXo/KDrP9iYzoqAvtqbRuPG9PAxefQ/JUSnuhikA51g9+Mu +IDKKKSI+y/JW9u0Qo77fp/5n2DaFn5B+pBYvn/xLfaEa9bRdJMTEMsElGbPBzMZd +I/7X6B78X6Ow5TuRKSeZA7E1AZ/+e5A4Hj65bLAugoSKz3zaS0dV26LwAo18c2zP +TqtwHyIVj4QCoI6Z694q9KH4Pkml3fz8VSkk+MvZMWapvUhHu/DneTgqGbp9POYg +nx6oWME6idhnvN6DljxB +-----END CERTIFICATE----- diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index ba7a992db..9e928157e 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -1,35 +1,23 @@ -/**************************************************************************** -** -** 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: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$ -** -****************************************************************************/ - -#include <QtCore/QScopedPointer> +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <httpserver.h> + +#if QT_CONFIG(ssl) +#include <httpsserver.h> +#endif + +#include <QtCore/qscopedpointer.h> +#include <QtCore/qtemporarydir.h> +#include <QtGui/private/qinputmethod_p.h> +#include <QtQml/qqmlengine.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickwindow.h> #include <QtQuickTest/quicktest.h> -#include <QtWebEngine/QQuickWebEngineProfile> -#include "qt_webengine_quicktest.h" +#include <QtTest/qtest.h> +#include <QtWebEngineQuick/qquickwebengineprofile.h> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> +#include <qt_webengine_quicktest.h> #if defined(Q_OS_LINUX) && defined(QT_DEBUG) #include <fcntl.h> @@ -37,6 +25,19 @@ #include <unistd.h> #endif +class Setup : public QObject +{ + Q_OBJECT +public: + Setup() { } + +public slots: + void qmlEngineAvailable(QQmlEngine *engine) + { + engine->addImportPath(QDir(QT_TESTCASE_SOURCEDIR).canonicalPath() + "/mock-delegates"); + } +}; + #if defined(Q_OS_LINUX) && defined(QT_DEBUG) static bool debuggerPresent() { @@ -95,6 +96,134 @@ static void sigSegvHandler(int signum) } #endif +class TempDir : public QObject { + Q_OBJECT + +public: + Q_INVOKABLE QString path() { + Q_ASSERT(tempDir.isValid()); + return tempDir.isValid() ? tempDir.path() : QString(); + } + + Q_INVOKABLE QUrl pathUrl(const QString &filename = QString()) + { + Q_ASSERT(tempDir.isValid()); + return filename.isEmpty() ? QUrl::fromLocalFile(tempDir.path()) + : QUrl::fromLocalFile(tempDir.filePath(filename)); + } + + Q_INVOKABLE void removeRecursive(const QString dirname) + { + QDir dir(dirname); + QFileInfoList entries(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)); + for (int i = 0; i < entries.size(); ++i) { + if (entries[i].isDir()) + removeRecursive(entries[i].filePath()); + else + dir.remove(entries[i].fileName()); + } + QDir().rmdir(dirname); + } + + Q_INVOKABLE void createDirectory(const QString dirname) { QDir(tempDir.path()).mkdir(dirname); } + +private: + QTemporaryDir tempDir; +}; + +class TestInputContext : public QPlatformInputContext { + Q_OBJECT + +public: + TestInputContext() = default; + ~TestInputContext() { release(); } + + Q_INVOKABLE void create() + { + QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod()); + inputMethodPrivate->testContext = this; + } + + Q_INVOKABLE void release() + { + QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod()); + inputMethodPrivate->testContext = nullptr; + } + + void showInputPanel() override { m_visible = true; } + void hideInputPanel() override { m_visible = false; } + bool isInputPanelVisible() const override { return m_visible; } + +private: + bool m_visible = false; +}; + +QT_BEGIN_NAMESPACE +namespace QTest { + int Q_TESTLIB_EXPORT defaultMouseDelay(); +} +QT_END_NAMESPACE + +class TestInputEvent : public QObject { + Q_OBJECT + +public: + TestInputEvent() = default; + + Q_INVOKABLE bool mouseMultiClick(QObject *item, qreal x, qreal y, int clickCount) + { + QTEST_ASSERT(item); + + QWindow *view = eventWindow(item); + if (!view) + return false; + + for (int i = 0; i < clickCount; ++i) { + mouseEvent(QMouseEvent::MouseButtonPress, view, item, QPointF(x, y)); + mouseEvent(QMouseEvent::MouseButtonRelease, view, item, QPointF(x, y)); + } + QTest::lastMouseTimestamp += QTest::mouseDoubleClickInterval; + + return true; + } + +private: + QWindow *eventWindow(QObject *item = nullptr) + { + QWindow *window = qobject_cast<QWindow *>(item); + if (window) + return window; + + QQuickItem *quickItem = qobject_cast<QQuickItem *>(item); + if (quickItem) + return quickItem->window(); + + QQuickItem *testParentItem = qobject_cast<QQuickItem *>(parent()); + if (testParentItem) + return testParentItem->window(); + + return nullptr; + } + + void mouseEvent(QEvent::Type type, QWindow *window, QObject *item, const QPointF &_pos) + { + QTest::qWait(QTest::defaultMouseDelay()); + QTest::lastMouseTimestamp += QTest::defaultMouseDelay(); + + QPoint pos; + QQuickItem *sgitem = qobject_cast<QQuickItem *>(item); + if (sgitem) + pos = sgitem->mapToScene(_pos).toPoint(); + + QMouseEvent me(type, pos, window->mapFromGlobal(pos), Qt::LeftButton, Qt::LeftButton, {}); + me.setTimestamp(++QTest::lastMouseTimestamp); + + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(window, &me)) + qWarning("Mouse click event not accepted by receiving window"); + } +}; + int main(int argc, char **argv) { #if defined(Q_OS_LINUX) && defined(QT_DEBUG) @@ -106,30 +235,42 @@ int main(int argc, char **argv) sigaction(SIGSEGV, &sigAction, 0); #endif - - // Inject the mock ui delegates module - qputenv("QML2_IMPORT_PATH", QByteArray(TESTS_SOURCE_DIR "qmltests/mock-delegates")); - QScopedPointer<Application> app; - + QtWebEngineQuick::initialize(); // Force to use English language for testing due to error message checks QLocale::setDefault(QLocale("en")); - static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")}; - QVector<const char *> w_argv(argc); \ - for (int i = 0; i < argc; ++i) \ - w_argv[i] = argv[i]; \ - for (int i = 0; i < params.size(); ++i) \ - w_argv.append(params[i].data()); \ - int w_argc = w_argv.size(); \ + static QByteArrayList params = {QByteArrayLiteral("--webEngineArgs"),QByteArrayLiteral("--use-fake-device-for-media-stream")}; + QList<const char *> w_argv(argc); + for (int i = 0; i < argc; ++i) w_argv[i] = argv[i]; + for (int i = 0; i < params.size(); ++i) w_argv.append(params[i].data()); + int w_argc = w_argv.size(); + Application app(w_argc, const_cast<char **>(w_argv.data())); - if (!QCoreApplication::instance()) { - app.reset(new Application(w_argc, const_cast<char **>(w_argv.data()))); - } - QtWebEngine::initialize(); QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true); + qmlRegisterType<TempDir>("Test.util", 1, 0, "TempDir"); + qmlRegisterType<TestInputContext>("Test.util", 1, 0, "TestInputContext"); + qmlRegisterType<TestInputEvent>("Test.util", 1, 0, "TestInputEvent"); QTEST_SET_MAIN_SOURCE_PATH + qmlRegisterSingletonType<HttpServer>("Test.Shared", 1, 0, "HttpServer", [&] (QQmlEngine *, QJSEngine *) { + auto server = new HttpServer; + server->setResourceDirs( + { server->sharedDataDir(), + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath() + QLatin1String("/data") }); + return server; + }); - int i = quick_test_main(argc, argv, "qmltests", QUICK_TEST_SOURCE_DIR); +#if QT_CONFIG(ssl) + qmlRegisterSingletonType<HttpsServer>( + "Test.Shared", 1, 0, "HttpsServer", [&](QQmlEngine *, QJSEngine *) { + return new HttpsServer(":/resources/server.pem", ":/resources/server.key", ""); + }); +#endif + Setup setup; + int i = quick_test_main_with_setup( + argc, argv, "qmltests", + qPrintable(QT_TESTCASE_BUILDDIR + QLatin1String("/webengine.qmltests")), &setup); return i; } + +#include "tst_qmltests.moc" |