2 * Copyright (C) 2014 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18import Ubuntu.Components 1.0
20import AccountsService 0.1
22import LightDM 0.1 as LightDM
23import Ubuntu.SystemImage 0.1
24import Ubuntu.Telephony 0.1 as Telephony
25import Unity.Application 0.1
26import Unity.Test 0.1 as UT
33 width: contentRow.width
34 height: contentRow.height
36 Component.onCompleted: {
37 // must set the mock mode before loading the Shell
38 LightDM.Greeter.mockMode = "single-pin";
39 LightDM.Users.mockMode = "single-pin";
40 shellLoader.active = true;
44 id: applicationArguments
46 function hasGeometry() {
69 property bool itemDestroyed: false
70 sourceComponent: Component {
72 property string indicatorProfile: "phone"
74 Component.onDestruction: {
75 shellLoader.itemDestroyed = true
84 height: shellLoader.height
87 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
90 anchors { left: parent.left; right: parent.right }
92 onClicked: LightDM.Greeter.showGreeter()
100 id: maxRetriesTextField
103 var greeter = testCase.findChild(shellLoader.item, "greeter");
104 greeter.maxFailedLogins = text;
113 signalName: "sessionStarted"
119 signalName: "resettingDevice"
124 target: LightDM.Greeter
125 signalName: "showPrompt"
128 Telephony.CallEntry {
130 phoneNumber: "+447812221111"
138 property Item shell: shellLoader.status === Loader.Ready ? shellLoader.item : null
141 tryCompare(shell, "enabled", true); // will be enabled when greeter is all ready
142 var greeter = findChild(shell, "greeter");
143 sessionSpy.target = greeter;
144 swipeAwayGreeter(true);
146 greeter.failedLoginsDelayAttempts = -1;
147 greeter.maxFailedLogins = -1;
151 tryCompare(shell, "enabled", true); // make sure greeter didn't leave us in disabled state
153 shellLoader.itemDestroyed = false
155 shellLoader.active = false
157 tryCompare(shellLoader, "status", Loader.Null)
158 tryCompare(shellLoader, "item", null)
159 // Loader.status might be Loader.Null and Loader.item might be null but the Loader
160 // item might still be alive. So if we set Loader.active back to true
161 // again right now we will get the very same Shell instance back. So no reload
162 // actually took place. Likely because Loader waits until the next event loop
163 // iteration to do its work. So to ensure the reload, we will wait until the
164 // Shell instance gets destroyed.
165 tryCompare(shellLoader, "itemDestroyed", true)
167 // kill all (fake) running apps
170 AccountsService.enableLauncherWhileLocked = true
171 AccountsService.enableIndicatorsWhileLocked = true
172 AccountsService.demoEdges = false
173 callManager.foregroundCall = null
174 LightDM.Greeter.authenticate(""); // reset greeter
176 // reload our test subject to get it in a fresh state once again
177 shellLoader.active = true
179 tryCompare(shellLoader, "status", Loader.Ready)
180 removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item)
183 function killApps() {
184 while (ApplicationManager.count > 1) {
185 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
186 ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
188 compare(ApplicationManager.count, 1)
191 function swipeAwayGreeter(waitForCoverPage) {
192 var greeter = findChild(shell, "greeter");
193 waitForRendering(greeter)
194 var coverPage = findChild(shell, "coverPage");
195 tryCompare(coverPage, "showProgress", 1);
197 var touchX = shell.width - (shell.edgeSize / 2);
198 var touchY = shell.height / 2;
199 touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
201 if (waitForCoverPage) {
202 // wait until the animation has finished
203 var coverPage = findChild(shell, "coverPage");
204 tryCompare(coverPage, "showProgress", 0);
208 function waitForLockscreen() {
209 var lockscreen = findChild(shell, "lockscreen");
210 var pinPadLoader = findChild(lockscreen, "pinPadLoader");
211 tryCompare(pinPadLoader, "status", Loader.Ready)
212 waitForRendering(lockscreen)
215 function enterPin(pin) {
216 for (var i = 0; i < pin.length; ++i) {
217 var character = pin.charAt(i)
218 var button = findChild(shell, "pinPadButton" + character)
219 tryCompare(button, "enabled", true);
224 function confirmLockedApp(app) {
225 var greeter = findChild(shell, "greeter")
226 tryCompare(greeter, "shown", false)
227 tryCompare(greeter, "hasLockedApp", true)
228 tryCompare(greeter, "lockedApp", app)
229 tryCompare(LightDM.Greeter, "active", true)
230 tryCompare(ApplicationManager, "focusedApplicationId", app)
233 function test_greeterChangesIndicatorProfile() {
234 skip("Not supported yet, waiting on design for new settings panel");
236 var panel = findChild(shell, "panel");
237 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
239 LightDM.Greeter.hideGreeter();
240 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
242 LightDM.Greeter.showGreeter();
243 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile + "_greeter");
245 LightDM.Greeter.hideGreeter();
246 tryCompare(panel.indicators.indicatorsModel, "profile", shell.indicatorProfile);
249 function test_login() {
251 tryCompare(sessionSpy, "count", 0)
253 tryCompare(sessionSpy, "count", 1)
256 function test_edgeDemoHidesLockscreen() {
257 LightDM.Greeter.showGreeter()
259 var lockscreen = findChild(shell, "lockscreen")
261 tryCompare(lockscreen, "shown", true)
262 AccountsService.demoEdges = true
263 tryCompare(lockscreen, "shown", false)
265 var greeter = findChild(shell, "greeter");
266 swipeAwayGreeter(false);
267 tryCompare(greeter, "shown", false);
268 tryCompare(sessionSpy, "count", 1)
270 // Lockscreen is only hidden by the edge demo, so if we turn that
271 // off and show greeter again, lockscreen should appear
272 AccountsService.demoEdges = false
273 LightDM.Greeter.showGreeter()
274 lockscreen = findChild(shell, "lockscreen");
275 tryCompare(lockscreen, "shown", true)
278 function test_disabledEdges() {
279 var launcher = findChild(shell, "launcher")
280 tryCompare(launcher, "available", true)
281 AccountsService.enableLauncherWhileLocked = false
282 tryCompare(launcher, "available", false)
284 var indicators = findChild(shell, "indicators")
285 tryCompare(indicators, "available", true)
286 AccountsService.enableIndicatorsWhileLocked = false
287 tryCompare(indicators, "available", false)
290 function test_emergencyCall() {
291 var greeter = findChild(shell, "greeter")
292 var panel = findChild(shell, "panel")
293 var indicators = findChild(shell, "indicators")
294 var launcher = findChild(shell, "launcher")
295 var stage = findChild(shell, "stage")
297 tap(findChild(greeter, "emergencyCallLabel"));
299 tryCompare(greeter, "lockedApp", "dialer-app")
300 tryCompare(greeter, "hasLockedApp", true)
301 tryCompare(greeter, "shown", false);
302 tryCompare(panel, "fullscreenMode", true)
303 tryCompare(indicators, "available", false)
304 tryCompare(launcher, "available", false)
305 tryCompare(stage, "spreadEnabled", false)
307 // Cancel emergency mode, and go back to normal
308 waitForRendering(greeter)
309 LightDM.Greeter.showGreeter()
311 tryCompare(greeter, "shown", true)
312 tryCompare(greeter, "lockedApp", "")
313 tryCompare(greeter, "hasLockedApp", false)
314 tryCompare(greeter, "fullyShown", true);
315 tryCompare(panel, "fullscreenMode", false)
316 tryCompare(indicators, "available", true)
317 tryCompare(launcher, "available", true)
318 tryCompare(stage, "spreadEnabled", true)
321 function test_emergencyCallCrash() {
322 var greeter = findChild(shell, "greeter");
323 var emergencyButton = findChild(greeter, "emergencyCallLabel");
326 tryCompare(greeter, "shown", false);
327 killApps() // kill dialer-app, as if it crashed
328 tryCompare(greeter, "shown", true);
329 tryCompare(findChild(greeter, "lockscreen"), "shown", true);
330 tryCompare(findChild(greeter, "coverPage"), "shown", false);
333 function test_emergencyCallAppLaunch() {
334 var greeter = findChild(shell, "greeter");
335 var emergencyButton = findChild(greeter, "emergencyCallLabel");
338 tryCompare(greeter, "shown", false);
339 ApplicationManager.startApplication("gallery-app", ApplicationManager.NoFlag)
340 tryCompare(greeter, "shown", true);
343 function test_failedLoginsCount() {
344 AccountsService.failedLogins = 0
347 tryCompare(AccountsService, "failedLogins", 1)
350 tryCompare(AccountsService, "failedLogins", 0)
353 function test_wrongEntries() {
354 var greeter = findChild(shell, "greeter");
355 greeter.failedLoginsDelayAttempts = 3;
357 var placeHolder = findChild(shell, "wrongNoticeLabel")
358 tryCompare(placeHolder, "text", "")
361 tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
364 tryCompare(placeHolder, "text", "Sorry, incorrect passcode")
366 var lockscreen = findChild(shell, "lockscreen")
367 tryCompare(lockscreen, "delayMinutes", 0)
369 tryCompare(lockscreen, "delayMinutes", greeter.failedLoginsDelayMinutes);
372 function test_factoryReset() {
373 maxRetriesTextField.text = "3"
378 tryCompareFunction(function() {return findChild(root, "infoPopup") !== null}, true)
380 var dialog = findChild(root, "infoPopup")
381 var button = findChild(dialog, "infoPopupOkButton")
383 tryCompareFunction(function() {return findChild(root, "infoPopup")}, null)
385 tryCompare(resetSpy, "count", 0)
387 tryCompare(resetSpy, "count", 1)
390 function test_emergencyDialerLockOut() {
391 // This is a theoretical attack on the lockscreen: Enter emergency
392 // dialer mode on a phone, then plug into a larger screen,
393 // switching to a tablet interface. This would in theory move the
394 // dialer to a side stage and give access to other apps. So just
395 // confirm that such an attack doesn't work.
397 var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader")
399 // We start in phone mode
400 tryCompare(shell, "sideStageEnabled", false)
401 tryCompare(applicationsDisplayLoader, "tabletMode", false)
403 var lockscreen = findChild(shell, "lockscreen")
404 lockscreen.emergencyCall()
405 confirmLockedApp("dialer-app")
407 // OK, we're in. Now try (but fail) to switch to tablet mode
409 tryCompare(shell, "sideStageEnabled", true)
410 tryCompare(applicationsDisplayLoader, "tabletMode", false)
412 // And when we kill the app, we go back to locked tablet mode
414 var greeter = findChild(shell, "greeter")
415 tryCompare(greeter, "fullyShown", true)
416 tryCompare(shell, "sideStageEnabled", true)
417 tryCompare(applicationsDisplayLoader, "tabletMode", true)
420 function test_emergencyDialerIncoming() {
421 callManager.foregroundCall = phoneCall
422 confirmLockedApp("dialer-app")
425 function test_emergencyDialerActiveCallPanel() {
426 // Make sure that the following sequence works:
427 // - Enter emergency mode call
428 // - Return to greeter
429 // - Click on active call panel
430 // - Should be back in emergency mode dialer
432 var greeter = findChild(shell, "greeter");
433 var lockscreen = findChild(shell, "lockscreen");
435 lockscreen.emergencyCall();
436 confirmLockedApp("dialer-app");
437 callManager.foregroundCall = phoneCall;
439 LightDM.Greeter.showGreeter();
440 tryCompare(lockscreen, "shown", true);
441 tryCompare(greeter, "hasLockedApp", false);
443 // simulate a callHint press, the real thing requires dialer: url support
444 ApplicationManager.requestFocusApplication("dialer-app");
446 confirmLockedApp("dialer-app");
449 function test_normalDialerActiveCallPanel() {
450 // Make sure that the following sequence works:
454 // - Click on active call panel
455 // - Should be back in normal dialer
456 // (we've had a bug where we locked screen in this case)
458 var greeter = findChild(shell, "greeter");
459 var panel = findChild(shell, "panel");
462 tryCompare(greeter, "shown", false);
463 tryCompare(LightDM.Greeter, "active", false);
465 ApplicationManager.startApplication("dialer-app", ApplicationManager.NoFlag);
466 tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
467 callManager.foregroundCall = phoneCall;
469 ApplicationManager.requestFocusApplication("unity8-dash");
470 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
471 tryCompare(panel.callHint, "visible", true);
473 // simulate a callHint press, the real thing requires dialer: url support
474 ApplicationManager.requestFocusApplication("dialer-app");
476 tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
477 tryCompare(greeter, "shown", false);
478 tryCompare(LightDM.Greeter, "active", false);
481 function test_focusRequestedHidesCoverPage() {
482 LightDM.Greeter.showGreeter();
484 var app = ApplicationManager.startApplication("gallery-app");
485 // wait until the app is fully loaded (ie, real surface replaces splash screen)
486 tryCompareFunction(function() { return app.session !== null && app.session.surface !== null }, true);
488 // New app hides coverPage?
489 var greeter = findChild(shell, "greeter");
490 var coverPage = testCase.findChild(shell, "coverPage");
491 tryCompare(coverPage, "showProgress", 0);
492 tryCompare(greeter, "fullyShown", true);
494 LightDM.Greeter.showGreeter();
495 tryCompare(coverPage, "showProgress", 1);
497 // Make sure focusing same app triggers same behavior
498 ApplicationManager.requestFocusApplication("gallery-app");
499 tryCompare(coverPage, "showProgress", 0);
500 tryCompare(greeter, "fullyShown", true);
503 function test_suspend() {
504 var greeter = findChild(shell, "greeter");
507 Powerd.status = Powerd.Off;
509 // If locked, ApplicationManager.suspended should be true
510 tryCompare(ApplicationManager, "suspended", true);
513 Powerd.status = Powerd.On;
514 tryCompare(greeter, "fullyShown", true);
516 // Swipe away greeter to focus app
517 swipeAwayGreeter(true);
519 // We have a lockscreen, make sure we're still suspended
520 tryCompare(ApplicationManager, "suspended", true);
524 // Now that the lockscreen has gone too, make sure we're waking up
525 tryCompare(ApplicationManager, "suspended", false);
529 /* We had a bug (1395075) where if a user kept swiping as the greeter
530 loaded, they would be able to get into the session before the
531 lockscreen appeared. Make sure that doesn't happen. */
532 function test_earlyDisable() {
533 // Kill current shell
534 shellLoader.itemDestroyed = false;
535 shellLoader.active = false;
536 tryCompare(shellLoader, "itemDestroyed", true);
537 LightDM.Greeter.authenticate(""); // reset greeter
541 shellLoader.active = true;
542 tryCompareFunction(function() {return shell !== null}, true);
544 // Confirm that we start disabled
545 compare(promptSpy.count, 0);
546 verify(!shell.enabled);
548 // And that we only become enabled once the lockscreen is up
549 tryCompare(shell, "enabled", true);
550 verify(promptSpy.count > 0);
551 var lockscreen = findChild(shell, "lockscreen");
552 verify(lockscreen.shown);
556 Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1393447
558 Do a left edge drag that is long enough to start displacing the greeter
559 but short engough so that the greeter comes back into place once the
562 In this situation the launcher should remaing fully shown and hide itself
563 only after its idle timeout is triggered.
565 function test_shortLeftEdgeSwipeMakesLauncherStayVisible() {
566 LightDM.Greeter.showGreeter();
567 var coverPage = testCase.findChild(shell, "coverPage");
568 tryCompare(coverPage, "showProgress", 1);
570 var launcher = testCase.findChild(shell, "launcher")
572 var dismissTimer = testCase.findInvisibleChild(launcher, "dismissTimer");
573 // effectively disable the dismiss timer
574 dismissTimer.interval = 24 * 60 * 60 * 1000 // 24 hours
576 var launcherPanel = testCase.findChild(launcher, "launcherPanel");
578 var toX = shell.width * 0.45;
580 1 /* fromX */, shell.height * 0.5 /* fromY */,
581 toX /* toX */, shell.height * 0.5 /* toY */,
582 true /* beginTouch */, false /* endTouch */,
585 // Launcher must be fully shown by now
586 tryCompare(launcherPanel, "x", 0);
588 // Greeter should be displaced
589 tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x > shell.width*0.2; }, true);
591 touchRelease(shell, toX, shell.height * 0.5);
593 // Upon release the greeter should have slid back into full view
594 tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x === 0; }, true);
596 // And the launcher should stay fully shown
597 for (var i = 0; i < 10; ++i) {
599 compare(launcherPanel.x, 0);
603 function test_longLeftEdgeDrags() {
604 var coverPage = findChild(shell, "coverPage");
605 var lockscreen = findChild(shell, "lockscreen");
606 var launcher = findChild(shell, "launcherPanel");
607 ApplicationManager.startApplication("gallery-app");
608 tryCompare(ApplicationManager, "focusedApplicationId", "gallery-app");
611 LightDM.Greeter.showGreeter();
612 tryCompare(coverPage, "showProgress", 1);
614 // Swipe cover page away
615 touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);
616 tryCompare(launcher, "x", -launcher.width);
617 tryCompare(coverPage, "showProgress", 0);
618 compare(lockscreen.shown, true);
619 compare(ApplicationManager.focusedApplicationId, "gallery-app");
621 // Now attempt a swipe on lockscreen
622 touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);
623 tryCompare(launcher, "x", 0);
624 compare(lockscreen.shown, true);
625 compare(ApplicationManager.focusedApplicationId, "gallery-app");
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list