diff options
author | J-P Nurmi <jpnurmi@theqtcompany.com> | 2016-03-10 14:29:54 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@theqtcompany.com> | 2016-03-15 10:37:42 +0000 |
commit | 3211db409e6fcfdee930bc651761b1036dd7649f (patch) | |
tree | 493983cf77b52e8476420e23892688704c1dcdbc /tests/auto/focus | |
parent | daf8b6655d5fdf12e5f86396ac7d7dc90060e05b (diff) |
Auto test focus navigation with keys
Change-Id: Ieb75c3043b9fac972af492598853ad8501637dbb
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
Diffstat (limited to 'tests/auto/focus')
-rw-r--r-- | tests/auto/focus/data/activeFocusOnTab.qml | 193 | ||||
-rw-r--r-- | tests/auto/focus/data/keyNavigation.qml | 251 | ||||
-rw-r--r-- | tests/auto/focus/focus.pro | 11 | ||||
-rw-r--r-- | tests/auto/focus/tst_focus.cpp | 119 |
4 files changed, 574 insertions, 0 deletions
diff --git a/tests/auto/focus/data/activeFocusOnTab.qml b/tests/auto/focus/data/activeFocusOnTab.qml new file mode 100644 index 00000000..46f9f522 --- /dev/null +++ b/tests/auto/focus/data/activeFocusOnTab.qml @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import Qt.labs.controls 1.0 + +Item { + id: main + objectName: "main" + width: 400 + height: 800 + focus: true + Component.onCompleted: button1.focus = true + Column { + anchors.fill: parent + id: column + objectName: "column" + BusyIndicator { + id: busyindicator + objectName: "busyindicator" + } + Button { + id: button1 + objectName: "button1" + text: "button1" + } + Button { + id: button2 + objectName: "button2" + text: "button2" + } + CheckBox { + id: checkbox + objectName: "checkbox" + text: "checkbox" + } + GroupBox { + id: groupbox1 + objectName: "groupbox1" + title: "grouppox1" + Column { + anchors.fill: parent + CheckBox { + id: checkbox1 + objectName: "checkbox1" + text: "checkbox1" + } + CheckBox { + id: checkbox2 + objectName: "checkbox2" + text: "checkbox2" + } + } + } + Label { + id: label + objectName: "label" + text: "label" + } + PageIndicator { + id: pageindicator + objectName: "pageindicator" + } + ProgressBar { + id: progressbar + objectName: "progressbar" + indeterminate: true + } + RadioButton { + id: radiobutton + objectName: "radiobutton" + text: "radiobutton" + } + GroupBox { + id: groupbox2 + objectName: "groupbox2" + title: "groupbox2" + Column { + anchors.fill: parent + RadioButton { + id: radiobutton1 + objectName: "radiobutton1" + text: "radiobutton1" + } + RadioButton { + id: radiobutton2 + objectName: "radiobutton2" + text: "radiobutton2" + } + } + } + RangeSlider { + id: rangeslider + objectName: "rangeslider" + first.handle.objectName: "rangeslider.first" + second.handle.objectName: "rangeslider.second" + } + // ScrollBar + ScrollIndicator { + id: scrollindicator + objectName: "scrollindicator" + } + Slider { + id: slider + objectName: "slider" + value: 0.5 + } + SpinBox { + id: spinbox + objectName: "spinbox" + editable: true + value: 50 + } + // StackView + Switch { + id: swtich // switch + objectName: "switch" + text: "switch" + } + TabBar { + width: parent.width + id: tabbar + objectName: "tabbar" + TabButton { + id: tabbutton1 + objectName: "tabbutton1" + text: "tabbutton1" + } + TabButton { + id: tabbutton2 + objectName: "tabbutton2" + text: "tabbutton2" + } + } + TextField { + id: textfield + objectName: "textfield" + text: "abc" + } + ToolBar { + width: parent.width + id: toolbar + objectName: "toolbar" + ToolButton { + id: toolbutton + objectName: "toolbutton" + text: "toolbutton" + } + } + TextArea { + id: textarea + objectName: "textarea" + text: "abc" + } + } +} diff --git a/tests/auto/focus/data/keyNavigation.qml b/tests/auto/focus/data/keyNavigation.qml new file mode 100644 index 00000000..3419fe3f --- /dev/null +++ b/tests/auto/focus/data/keyNavigation.qml @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import Qt.labs.controls 1.0 + +Item { + id: main + objectName: "main" + width: 400 + height: 800 + focus: true + Component.onCompleted: button1.focus = true + Column { + anchors.fill: parent + id: column + objectName: "column" + BusyIndicator { + id: busyindicator + objectName: "busyindicator" + } + Button { + id: button1 + objectName: "button1" + text: "button1" + KeyNavigation.up: textarea + KeyNavigation.down: button2 + KeyNavigation.left: toolbutton + KeyNavigation.right: button2 + } + Button { + id: button2 + objectName: "button2" + text: "button2" + KeyNavigation.up: button1 + KeyNavigation.down: checkbox + KeyNavigation.left: button1 + KeyNavigation.right: checkbox + } + CheckBox { + id: checkbox + objectName: "checkbox" + text: "checkbox" + KeyNavigation.up: button2 + KeyNavigation.down: checkbox1 + KeyNavigation.left: button2 + KeyNavigation.right: checkbox1 + } + GroupBox { + id: groupbox1 + objectName: "groupbox1" + title: "grouppox1" + Column { + anchors.fill: parent + CheckBox { + id: checkbox1 + objectName: "checkbox1" + text: "checkbox1" + KeyNavigation.up: checkbox + KeyNavigation.down: checkbox2 + KeyNavigation.left: checkbox + KeyNavigation.right: checkbox2 + } + CheckBox { + id: checkbox2 + objectName: "checkbox2" + text: "checkbox2" + KeyNavigation.up: checkbox1 + KeyNavigation.down: radiobutton + KeyNavigation.left: checkbox1 + KeyNavigation.right: radiobutton + } + } + } + Label { + id: label + objectName: "label" + text: "label" + } + PageIndicator { + id: pageindicator + objectName: "pageindicator" + } + ProgressBar { + id: progressbar + objectName: "progressbar" + indeterminate: true + } + RadioButton { + id: radiobutton + objectName: "radiobutton" + text: "radiobutton" + KeyNavigation.up: checkbox2 + KeyNavigation.down: radiobutton1 + KeyNavigation.left: checkbox2 + KeyNavigation.right: radiobutton1 + } + GroupBox { + id: groupbox2 + objectName: "groupbox2" + title: "groupbox2" + Column { + anchors.fill: parent + RadioButton { + id: radiobutton1 + objectName: "radiobutton1" + text: "radiobutton1" + KeyNavigation.up: radiobutton + KeyNavigation.down: radiobutton2 + KeyNavigation.left: radiobutton + KeyNavigation.right: radiobutton2 + } + RadioButton { + id: radiobutton2 + objectName: "radiobutton2" + text: "radiobutton2" + KeyNavigation.up: radiobutton1 + KeyNavigation.down: rangeslider + KeyNavigation.left: radiobutton1 + KeyNavigation.right: spinbox + } + } + } + RangeSlider { + id: rangeslider + objectName: "rangeslider" + first.handle.objectName: "rangeslider.first" + second.handle.objectName: "rangeslider.second" + KeyNavigation.up: radiobutton2 + KeyNavigation.down: slider + } + // ScrollBar + ScrollIndicator { + id: scrollindicator + objectName: "scrollindicator" + } + Slider { + id: slider + objectName: "slider" + value: 0.5 + KeyNavigation.up: rangeslider + KeyNavigation.down: swtich + } + SpinBox { + id: spinbox + objectName: "spinbox" + editable: true + value: 50 + KeyNavigation.left: radiobutton2 + KeyNavigation.right: swtich + } + // StackView + Switch { + id: swtich // switch + objectName: "switch" + text: "switch" + KeyNavigation.up: slider + KeyNavigation.down: tabbutton1 + KeyNavigation.left: spinbox + KeyNavigation.right: tabbutton1 + } + TabBar { + width: parent.width + id: tabbar + objectName: "tabbar" + TabButton { + id: tabbutton1 + objectName: "tabbutton1" + text: "tabbutton1" + KeyNavigation.up: swtich + KeyNavigation.down: tabbutton2 + KeyNavigation.left: swtich + KeyNavigation.right: tabbutton2 + } + TabButton { + id: tabbutton2 + objectName: "tabbutton2" + text: "tabbutton2" + KeyNavigation.up: tabbutton1 + KeyNavigation.down: textfield + KeyNavigation.left: tabbutton1 + KeyNavigation.right: toolbutton + } + } + TextField { + id: textfield + objectName: "textfield" + text: "abc" + KeyNavigation.up: tabbutton2 + KeyNavigation.down: toolbutton + } + ToolBar { + width: parent.width + id: toolbar + objectName: "toolbar" + ToolButton { + id: toolbutton + objectName: "toolbutton" + text: "toolbutton" + KeyNavigation.up: textfield + KeyNavigation.down: textarea + KeyNavigation.left: tabbutton2 + KeyNavigation.right: button1 + } + } + TextArea { + id: textarea + objectName: "textarea" + text: "abc" + KeyNavigation.up: toolbutton + KeyNavigation.down: button1 + } + } +} diff --git a/tests/auto/focus/focus.pro b/tests/auto/focus/focus.pro new file mode 100644 index 00000000..5eed4a4a --- /dev/null +++ b/tests/auto/focus/focus.pro @@ -0,0 +1,11 @@ +CONFIG += testcase +TARGET = tst_focus +osx:CONFIG -= app_bundle + +SOURCES += tst_focus.cpp + +include (../shared/util.pri) + +TESTDATA = data/* + +QT += core-private gui-private qml-private quick-private testlib diff --git a/tests/auto/focus/tst_focus.cpp b/tests/auto/focus/tst_focus.cpp new file mode 100644 index 00000000..d7283e4d --- /dev/null +++ b/tests/auto/focus/tst_focus.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtTest/QSignalSpy> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlcontext.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/private/qquickitem_p.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qstylehints.h> +#include "../shared/util.h" +#include "../shared/visualtestutil.h" + +using namespace QQuickVisualTestUtil; + +class tst_focus : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void navigation_data(); + void navigation(); +}; + +void tst_focus::initTestCase() +{ + QQmlDataTest::initTestCase(); +} + +void tst_focus::navigation_data() +{ + QTest::addColumn<Qt::Key>("key"); + QTest::addColumn<QString>("testFile"); + QTest::addColumn<Qt::TabFocusBehavior>("behavior"); + QTest::addColumn<QStringList>("order"); + + QTest::newRow("tab-all-controls") << Qt::Key_Tab << QString("activeFocusOnTab.qml") << Qt::TabFocusAllControls << (QStringList() << "button2" << "checkbox" << "checkbox1" << "checkbox2" << "radiobutton" << "radiobutton1" << "radiobutton2" << "rangeslider.first" << "rangeslider.second" << "slider" << "spinbox" << "switch" << "tabbutton1" << "tabbutton2" << "textfield" << "toolbutton" << "textarea" << "button1"); + QTest::newRow("backtab-all-controls") << Qt::Key_Backtab << QString("activeFocusOnTab.qml") << Qt::TabFocusAllControls << (QStringList() << "textarea" << "toolbutton" << "textfield" << "tabbutton2" << "tabbutton1" << "switch" << "spinbox" << "slider" << "rangeslider.second" << "rangeslider.first" << "radiobutton2" << "radiobutton1" << "radiobutton" << "checkbox2" << "checkbox1" << "checkbox" << "button2" << "button1"); + + QTest::newRow("tab-text-controls") << Qt::Key_Tab << QString("activeFocusOnTab.qml") << Qt::TabFocusTextControls << (QStringList() << "spinbox" << "textfield" << "textarea"); + QTest::newRow("backtab-text-controls") << Qt::Key_Backtab << QString("activeFocusOnTab.qml") << Qt::TabFocusTextControls << (QStringList() << "textarea" << "textfield" << "spinbox"); + + QTest::newRow("key-up") << Qt::Key_Up << QString("keyNavigation.qml") << Qt::TabFocusAllControls << (QStringList() << "textarea" << "toolbutton" << "textfield" << "tabbutton2" << "tabbutton1" << "switch" << "slider" << "rangeslider.first" << "radiobutton2" << "radiobutton1" << "radiobutton" << "checkbox2" << "checkbox1" << "checkbox" << "button2" << "button1"); + QTest::newRow("key-down") << Qt::Key_Down << QString("keyNavigation.qml") << Qt::TabFocusAllControls << (QStringList() << "button2" << "checkbox" << "checkbox1" << "checkbox2" << "radiobutton" << "radiobutton1" << "radiobutton2" << "rangeslider.first" << "slider" << "switch" << "tabbutton1" << "tabbutton2" << "textfield" << "toolbutton" << "textarea" << "button1"); + QTest::newRow("key-left") << Qt::Key_Left << QString("keyNavigation.qml") << Qt::TabFocusAllControls << (QStringList() << "toolbutton" << "tabbutton2" << "tabbutton1" << "switch" << "spinbox" << "radiobutton2" << "radiobutton1" << "radiobutton" << "checkbox2" << "checkbox1" << "checkbox" << "button2" << "button1"); + QTest::newRow("key-right") << Qt::Key_Right << QString("keyNavigation.qml") << Qt::TabFocusAllControls << (QStringList() << "button2" << "checkbox" << "checkbox1" << "checkbox2" << "radiobutton" << "radiobutton1" << "radiobutton2" << "spinbox" << "switch" << "tabbutton1" << "tabbutton2" << "toolbutton" << "button1"); +} + +void tst_focus::navigation() +{ + QFETCH(Qt::Key, key); + QFETCH(QString, testFile); + QFETCH(Qt::TabFocusBehavior, behavior); + QFETCH(QStringList, order); + + QGuiApplication::styleHints()->setTabFocusBehavior(behavior); + + QQuickView view; + view.contentItem()->setObjectName("contentItem"); + + view.setSource(testFileUrl(testFile)); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + QVERIFY(QGuiApplication::focusWindow() == &view); + + foreach (const QString &name, order) { + QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier); + QGuiApplication::sendEvent(&view, &event); + QVERIFY(event.isAccepted()); + + QQuickItem *item = findItem<QQuickItem>(view.rootObject(), name); + QVERIFY2(item, qPrintable(name)); + QVERIFY2(item->hasActiveFocus(), qPrintable(QString("expected: '%1', actual: '%2'").arg(name).arg(view.activeFocusItem() ? view.activeFocusItem()->objectName() : "null"))); + } + + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusBehavior(-1)); +} + +QTEST_MAIN(tst_focus) + +#include "tst_focus.moc" |