1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* Copyright 2015 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.4
import QtTest 1.0
import Lomiri.Test 1.0
import Lomiri.Components 1.3
Item {
id: root
width: 400
height: 600
// actions must be either assigned to an active ActionContext or to an ActionItem to activate shortcuts
ActionContext {
id: context
active: true
Action {
id: action
}
Action {
id: other
shortcut: 'Ctrl+G'
}
}
TestUtil {
id: util
}
LomiriTestCase {
id: testCase
name: "Shortcuts"
when: windowShown
function initTestCase() {
}
function init() {
context.active = true;
spy.target = action;
}
function cleanup() {
spy.clear();
shortcutSpy.clear();
}
SignalSpy {
id: spy
signalName: 'triggered'
target: action
}
function ignoreQMLWarning(message) {
ignoreWarning(util.callerFile() + message);
}
function test_shortcut_triggered_data() {
return [
{ tag: 'Multiple modifiers and letter', shortcut: 'Ctrl+Shift+Alt+A', key: Qt.Key_A, mod: Qt.ControlModifier + Qt.ShiftModifier + Qt.AltModifier },
{ tag: 'Modifier and letter', shortcut: 'Ctrl+A', key: Qt.Key_A, mod: Qt.ControlModifier },
{ tag: 'Single letter', shortcut: 'E', key: Qt.Key_E, mod: Qt.NoModifier },
{ tag: 'StandardKey', shortcut: StandardKey.Copy, key: Qt.Key_C, mod: Qt.ControlModifier }
];
}
function test_shortcut_triggered(data) {
action.shortcut = data.shortcut;
spy.clear();
keyClick(data.key, data.mod);
spy.wait();
}
function test_shortcut_invalid_data() {
return [
{ tag: 'Typo', shortcut: 'Ctr+F' },
{ tag: 'Number', shortcut: 1234567890 },
{ tag: "Empty string", shortcut: "" }
];
}
function test_shortcut_invalid(data) {
ignoreQMLWarning(':31:9: QML Action: Invalid shortcut: ');
action.shortcut = data;
}
function test_shortcut_duplicate() {
ignoreQMLWarning(':34:9: QML Action: Ambiguous shortcut: Ctrl+G');
action.shortcut = other.shortcut;
keyClick(Qt.Key_G, Qt.ControlModifier);
}
SignalSpy {
id: shortcutSpy
signalName: "shortcutChanged"
}
function test_shortcut_reset_bug1518420() {
shortcutSpy.target = action;
action.shortcut = "Ctrl+A";
shortcutSpy.wait(200);
shortcutSpy.clear();
action.shortcut = undefined;
shortcutSpy.wait(200);
shortcutSpy.target = null;
}
function test_mnemonic_data() {
return [
{tag: "HW keyboard, valid 'C&all'", kbd: true, text: "C&all", displayText: "C<u>a</u>ll", key: Qt.Key_A, xfail: false},
{tag: "HW keyboard, valid '&Save & Exit", kbd: true, text: "&Save & Exit", displayText: "<u>S</u>ave & Exit", key: Qt.Key_S, xfail: false},
{tag: "HW keyboard, valid 'Hide &Seek'", kbd: true, text: "Hide&Seek", displayText: "Hide<u>S</u>eek", key: Qt.Key_S, xfail: false},
{tag: "HW keyboard, valid 'Save & Exit'", kbd: true, text: "Save & Exit", displayText: "Save <u> </u>Exit", key: Qt.Key_Space, xfail: false},
{tag: "HW keyboard, valid 'Paste &&&Proceed'", kbd: true, text: "Paste &&&Proceed", displayText: "Paste &<u>P</u>roceed", key: Qt.Key_P, xfail: false},
{tag: "HW keyboard, valid 'Cut &$'", kbd: true, text: "Cut &$", displayText: "Cut <u>$</u>", key: Qt.Key_Dollar, xfail: false},
{tag: "HW keyboard, valid 'At &@'", kbd: true, text: "At &@", displayText: "At <u>@</u>", key: Qt.Key_At, xfail: false},
{tag: "HW keyboard, valid '&_'", kbd: true, text: "&_", displayText: "<u>_</u>", key: Qt.Key_Underscore, xfail: false},
{tag: "HW keyboard, invalid 'Apps && Scopes'", kbd: true, text: "Apps && Scopes", displayText: "Apps & Scopes", key: Qt.Key_Asterisk, xfail: true},
{tag: "HW keyboard, invalid 'Jump &'", kbd: true, text: "Jump &", displayText: "Jump &", key: Qt.Key_Asterisk, xfail: true},
{tag: "HW keyboard, invalid '&&'", kbd: true, text: "&&", displayText: "&", key: Qt.Key_Asterisk, xfail: true},
{tag: "no HW keyboard", kbd: false, text: "&Call", displayText: "Call", key: Qt.Key_C, xfail: false},
];
}
function test_mnemonic(data) {
QuickUtils.keyboardAttached = data.kbd;
action.text = data.text;
if (!data.kbd && QuickUtils.keyboardAttached) {
skip("Cannot test this case: " + data.tag);
}
compare(action.text, data.displayText);
// shortcut
keyClick(data.key, Qt.AltModifier);
if (data.xfail) {
expectFail(data.tag, "invalid mnemonic");
}
spy.wait(200);
}
SignalSpy {
id: textSpy
target: action
signalName: "textChanged"
}
function test_mnemonic_displaytext() {
QuickUtils.keyboardAttached = false;
if (QuickUtils.keyboardAttached) {
skip("the test needs to be able to detach the keyboard");
}
action.text = "&Call";
textSpy.clear();
QuickUtils.keyboardAttached = true;
if (!QuickUtils.keyboardAttached) {
skip("the test needs to be able to attach the keyboard");
}
textSpy.wait(200);
}
function test_contextual_action_shortcut_data() {
return [
{tag: "Active context", active: true, xfail: false},
{tag: "Inactive context", active: false, xfail: true},
];
}
function test_contextual_action_shortcut(data) {
context.active = data.active;
spy.target = other;
spy.clear();
keyClick(Qt.Key_G, Qt.ControlModifier);
if (data.xfail) {
expectFailContinue("", "No shortcut fires");
}
spy.wait(200);
}
}
}
|