@@ -23,25 +23,33 @@ import LightDM 0.1 as LightDM
23import Unity.Test 0.1 as UT
23import Unity.Test 0.1 as UT
25Rectangle {
25Rectangle {
26− width: units.gu(60)
27+ width: units.gu(80)
27 height: units.gu(80)
28 height: units.gu(80)
28 color: "orange"
29 color: "orange"
30 Lockscreen {
31 Lockscreen {
31 id: lockscreen
32 id: lockscreen
32 anchors.fill: parent
33 anchors.fill: parent
33− anchors.rightMargin: units.gu(18)
34+ anchors.rightMargin: units.gu(30)
34 placeholderText: "Please enter your PIN"
35 placeholderText: "Please enter your PIN"
35 alphaNumeric: pinPadCheckBox.checked
36 alphaNumeric: pinPadCheckBox.checked
36− pinLength: pinLengthTextField.text
37+ minPinLength: minPinLengthTextField.text
38+ maxPinLength: maxPinLengthTextField.text
39+ retryCount: retryCountTextField.text
37 username: "Lola"
40 username: "Lola"
41+ background: "../../../qml/graphics/phone_background.jpg"
42+ infoText: infoTextTextField.text
40 Connections {
45 Connections {
41 target: lockscreen
46 target: lockscreen
43 onEmergencyCall: emergencyCheckBox.checked = true
48 onEmergencyCall: emergencyCheckBox.checked = true
44− onEntered: enteredLabel.text = passphrase
50+ enteredLabel.text = passphrase
51+ lockscreen.clear(true)
47 Connections {
55 Connections {
@@ -49,9 +57,9 @@ Rectangle {
50 onShowPrompt: {
58 onShowPrompt: {
51 if (text.indexOf("PIN") >= 0) {
59 if (text.indexOf("PIN") >= 0) {
52− lockscreen.alphaNumeric = false
60+ pinPadCheckBox.checked = false
54− lockscreen.alphaNumeric = true
62+ pinPadCheckBox.checked = true
56 lockscreen.placeholderText = text;
64 lockscreen.placeholderText = text;
@@ -65,6 +73,7 @@ Rectangle {
66 anchors.fill: parent
74 anchors.fill: parent
67 anchors.margins: units.gu(1)
75 anchors.margins: units.gu(1)
70 CheckBox {
79 CheckBox {
@@ -86,12 +95,32 @@ Rectangle {
88 TextField {
97 TextField {
89− id: pinLengthTextField
98+ id: minPinLengthTextField
103+ text: "Min PIN length"
108+ id: maxPinLengthTextField
90 width: units.gu(7)
109 width: units.gu(7)
91 text: "4"
110 text: "4"
94− text: "PIN length"
113+ text: "Max PIN length"
118+ id: retryCountTextField
123+ text: "Retries left"
@@ -108,12 +137,40 @@ Rectangle {
110 text: "start auth (1234)"
139 text: "start auth (1234)"
111 onClicked: LightDM.Greeter.authenticate("has-pin")
141 onClicked: LightDM.Greeter.authenticate("has-pin")
114 text: "start auth (password)"
144 text: "start auth (password)"
115 onClicked: LightDM.Greeter.authenticate("has-password")
146 onClicked: LightDM.Greeter.authenticate("has-password")
150+ id: infoTextTextField
152+ placeholderText: "Infotext"
153+ text: "+49 179 3253553"
157+ id: infoPopupTitleTextField
159+ placeholderText: "Popup title"
160+ text: "This will be the last attempt"
164+ id: infoPopupTextArea
166+ text: "If the SIM PIN is entered incorrectly, your SIM will be blocked and would require the PUK code to unlock."
170+ text: "open info popup"
172+ onClicked: lockscreen.showInfoPopup(infoPopupTitleTextField.text, infoPopupTextArea.text)
@@ -121,6 +178,16 @@ Rectangle {
121 name: "Lockscreen"
178 name: "Lockscreen"
122 when: windowShown
179 when: windowShown
181+ function cleanup() {
182+ lockscreen.clear(false);
185+ function waitForLockscreenReady() {
186+ var pinPadLoader = findChild(lockscreen, "pinPadLoader");
187+ tryCompare(pinPadLoader, "status", Loader.Ready)
188+ waitForRendering(lockscreen)
124 function test_loading_data() {
191 function test_loading_data() {
126 {tag: "numeric", alphanumeric: false, pinPadAvailable: true },
193 {tag: "numeric", alphanumeric: false, pinPadAvailable: true },
@@ -129,8 +196,8 @@ Rectangle {
131 function test_loading(data) {
198 function test_loading(data) {
132− lockscreen.alphaNumeric = data.alphanumeric
199+ pinPadCheckBox.checked = data.alphanumeric
133− waitForRendering(lockscreen)
200+ waitForLockscreenReady();
134 if (data.pinPadAvailable) {
201 if (data.pinPadAvailable) {
135 compare(findChild(lockscreen, "pinPadButton8").text, "8", "Could not find number 8 on PinPad")
202 compare(findChild(lockscreen, "pinPadButton8").text, "8", "Could not find number 8 on PinPad")
@@ -147,8 +214,8 @@ Rectangle {
148 function test_emergency_call(data) {
215 function test_emergency_call(data) {
149 emergencyCheckBox.checked = false
216 emergencyCheckBox.checked = false
150− lockscreen.alphaNumeric = data.alphanumeric
217+ pinPadCheckBox.checked = data.alphanumeric
151− waitForRendering(lockscreen)
218+ waitForLockscreenReady();
152 var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
219 var emergencyButton = findChild(lockscreen, "emergencyCallIcon")
153 mouseClick(emergencyButton, units.gu(1), units.gu(1))
220 mouseClick(emergencyButton, units.gu(1), units.gu(1))
154 tryCompare(emergencyCheckBox, "checked", true)
221 tryCompare(emergencyCheckBox, "checked", true)
@@ -163,9 +230,9 @@ Rectangle {
165 function test_labels(data) {
232 function test_labels(data) {
166− lockscreen.alphaNumeric = data.alphanumeric
233+ pinPadCheckBox.checked = data.alphanumeric
167 lockscreen.placeholderText = data.placeholderText
234 lockscreen.placeholderText = data.placeholderText
168− waitForRendering(lockscreen)
235+ waitForLockscreenReady();
169 compare(findChild(lockscreen, "pinentryField").placeholderText, data.placeholderText, "Placeholdertext is not what it should be")
236 compare(findChild(lockscreen, "pinentryField").placeholderText, data.placeholderText, "Placeholdertext is not what it should be")
170 if (data.alphanumeric) {
237 if (data.alphanumeric) {
171 compare(findChild(lockscreen, "greeterLabel").text, "Hello " + data.username, "Greeter is not set correctly")
238 compare(findChild(lockscreen, "greeterLabel").text, "Hello " + data.username, "Greeter is not set correctly")
@@ -175,23 +242,25 @@ Rectangle {
176 function test_unlock_data() {
243 function test_unlock_data() {
178− {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", pinLength: 4},
245+ {tag: "numeric", alphanumeric: false, username: "has-pin", password: "1234", minPinLength: 4, maxPinLength: 4},
179− {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", pinLength: -1},
246+ {tag: "alphanumeric", alphanumeric: true, username: "has-password", password: "password", minPinLength: -1, maxPinLength: -1},
180− {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", pinLength: 4},
247+ {tag: "numeric (wrong)", alphanumeric: false, username: "has-pin", password: "4321", minPinLength: 4, maxPinLength: 4},
181− {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", pinLength: -1},
248+ {tag: "alphanumeric (wrong)", alphanumeric: true, username: "has-password", password: "drowssap", minPinLength: -1, maxPinLength: -1},
182− {tag: "flexible length", alphanumeric: false, username: "has-pin", password: "1234", pinLength: -1},
249+ {tag: "flexible length", alphanumeric: false, username: "has-pin", password: "1234", minPinLength: -1, maxPinLength: -1},
186 function test_unlock(data) {
253 function test_unlock(data) {
187 enteredLabel.text = ""
254 enteredLabel.text = ""
188− pinLengthTextField.text = data.pinLength
255+ minPinLengthTextField.text = data.minPinLength
256+ maxPinLengthTextField.text = data.maxPinLength
189 LightDM.Greeter.authenticate(data.username)
257 LightDM.Greeter.authenticate(data.username)
190− waitForRendering(lockscreen)
258+ waitForLockscreenReady();
192 var inputField = findChild(lockscreen, "pinentryField")
260 var inputField = findChild(lockscreen, "pinentryField")
193 if (data.alphanumeric) {
261 if (data.alphanumeric) {
194 mouseClick(inputField, units.gu(1), units.gu(1))
262 mouseClick(inputField, units.gu(1), units.gu(1))
263+ tryCompare(inputField, "focus", true);
195 typeString(data.password)
264 typeString(data.password)
196 keyClick(Qt.Key_Enter)
265 keyClick(Qt.Key_Enter)
@@ -200,7 +269,7 @@ Rectangle {
200 var button = findChild(lockscreen, "pinPadButton" + character)
269 var button = findChild(lockscreen, "pinPadButton" + character)
201 mouseClick(button, units.gu(1), units.gu(1))
270 mouseClick(button, units.gu(1), units.gu(1))
203− if (data.pinLength == -1) {
272+ if (data.minPinLength !== data.maxPinLength || data.minPinLength == -1) {
204 var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
273 var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
205 mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
274 mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
@@ -219,11 +288,12 @@ Rectangle {
220 function test_clear(data) {
289 function test_clear(data) {
221 pinPadCheckBox.checked = data.alphanumeric
290 pinPadCheckBox.checked = data.alphanumeric
222− waitForRendering(lockscreen)
291+ waitForLockscreenReady();
224 var inputField = findChild(lockscreen, "pinentryField")
293 var inputField = findChild(lockscreen, "pinentryField")
225 if (data.alphanumeric) {
294 if (data.alphanumeric) {
226 mouseClick(inputField, units.gu(1), units.gu(1))
295 mouseClick(inputField, units.gu(1), units.gu(1))
296+ tryCompare(inputField, "activeFocus", true);
227 typeString("1")
297 typeString("1")
229 var button = findChild(lockscreen, "pinPadButton1")
299 var button = findChild(lockscreen, "pinPadButton1")
@@ -246,33 +316,121 @@ Rectangle {
247 function test_backspace_data() {
317 function test_backspace_data() {
249− {tag: "fixed length", pinLength: 4},
319+ {tag: "fixed length", minPinLength: 4, maxPinLength: 4},
250− {tag: "variable length", pinLength: -1}
320+ {tag: "variable undefined length", minPinLength: -1, maxPinLength: -1},
321+ {tag: "variable restricted length", minPinLength: 4, maxPinLength: 8}
254 function test_backspace(data) {
325 function test_backspace(data) {
255 pinPadCheckBox.checked = false
326 pinPadCheckBox.checked = false
256− pinLengthTextField.text = data.pinLength
327+ minPinLengthTextField.text = data.minPinLength
257− waitForRendering(lockscreen);
328+ maxPinLengthTextField.text = data.maxPinLength
329+ waitForLockscreenReady();
259 var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
331 var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
260 var backspaceIcon = findChild(lockscreen, "backspaceIcon");
332 var backspaceIcon = findChild(lockscreen, "backspaceIcon");
261 var pinEntryField = findChild(lockscreen, "pinentryField");
333 var pinEntryField = findChild(lockscreen, "pinentryField");
335+ var autoConfirmEnabled = data.minPinLength === data.maxPinLength && data.minPinLength !== -1;
263− compare(pinPadButtonErase.iconName, data.pinLength == -1 ? "" : "erase");
336+ compare(pinPadButtonErase.iconName, autoConfirmEnabled ? "erase" : "");
264− compare(backspaceIcon.visible, data.pinLength == -1);
337+ compare(backspaceIcon.visible, !autoConfirmEnabled);
266 var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
339 var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
267 mouseClick(pinPadButton5, units.gu(1), units.gu(1));
340 mouseClick(pinPadButton5, units.gu(1), units.gu(1));
268 compare(pinEntryField.text, "5");
341 compare(pinEntryField.text, "5");
270− if (data.pinLength == -1) {
343+ if (data.minPinLength !== data.maxPinLength) {
271 mouseClick(backspaceIcon, units.gu(1), units.gu(1));
344 mouseClick(backspaceIcon, units.gu(1), units.gu(1));
273 mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
346 mouseClick(pinPadButtonErase, units.gu(1), units.gu(1));
275 compare(pinEntryField.text, "");
348 compare(pinEntryField.text, "");
351+ function test_minMaxLength_data() {
353+ {tag: "undefined", minPinLength: -1, maxPinLength: -1},
354+ {tag: "fixed", minPinLength: 4, maxPinLength: 4},
355+ {tag: "variable, limited", minPinLength: 4, maxPinLength: 8},
359+ function test_minMaxLength(data) {
360+ pinPadCheckBox.checked = false
361+ minPinLengthTextField.text = data.minPinLength
362+ maxPinLengthTextField.text = data.maxPinLength
363+ waitForLockscreenReady();
365+ var pinPadButton5 = findChild(lockscreen, "pinPadButton5");
366+ var pinPadButtonErase = findChild(lockscreen, "pinPadButtonErase");
367+ var inputField = findChild(lockscreen, "pinentryField")
369+ for (var i = 0; i < 10; i++) {
370+ mouseClick(pinPadButton5, units.gu(1), units.gu(1));
372+ if (data.minPinLength == data.maxPinLength && data.minPinLength != -1) {
373+ // auto confirm mode...
374+ compare(inputField.text.length, (i+1) % data.minPinLength);
376+ // manual confirm mode
377+ tryCompare(pinPadButtonErase, "enabled", (i+1) >= data.minPinLength)
378+ if (data.maxPinLength == -1) {
379+ compare(inputField.text.length, i+1);
381+ compare(inputField.text.length, Math.min(data.maxPinLength, i+1));
388+ function test_retryDisplay_data() {
390+ {tag: "0", retryCount: 0, shown: true},
391+ {tag: "1", retryCount: 1, shown: true},
392+ {tag: "3", retryCount: 3, shown: true},
393+ {tag: "-1", retryCount: -1, shown: false},
397+ function test_retryDisplay(data) {
398+ pinPadCheckBox.checked = false
399+ waitForLockscreenReady();
401+ retryCountTextField.text = data.retryCount;
402+ var label = findChild(lockscreen, "retryCountLabel")
403+ compare(label.visible, data.shown);
406+ function test_infoPopup() {
407+ verify(findChild(root, "infoPopup") === null);
408+ lockscreen.showInfoPopup("foo", "bar");
409+ tryCompareFunction(function() { return findChild(root, "infoPopup") !== null}, true);
411+ var infoPopup = findChild(root, "infoPopup");
412+ compare(infoPopup.title, "foo");
413+ compare(infoPopup.text, "bar");
414+ var okButton = findChild(root, "infoPopupOkButton");
415+ mouseClick(okButton, okButton.width / 2, okButton.height / 2);
417+ tryCompareFunction(function() { return findChild(root, "infoPopup") === null}, true);
420+ function test_infoTextDisplay_data() {
422+ {tag: "empty string", text: "", shown: false},
423+ {tag: "hello world", text: "hello world", shown: true},
427+ function test_infoTextDisplay(data) {
428+ pinPadCheckBox.checked = false
429+ waitForLockscreenReady();
431+ infoTextTextField.text = data.text;
432+ var label = findChild(lockscreen, "infoTextLabel")
433+ compare(label.visible, data.shown);