@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013,2014,2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@ import Ubuntu.Components 1.3
2222import Ubuntu.Components.ListItems 1.3
2323import Ubuntu.Telephony 0.1 as Telephony
2424import Unity.Application 0.1
25+import Unity.Notifications 1.0
2526import Unity.Test 0.1 as UT
2627import Utils 0.1
2728
@@ -55,6 +56,33 @@ Rectangle {
5556 phoneNumber: "+447812221111"
5657 }
5758
59+ Component {
60+ id: mockNotification
61+ QtObject {}
62+ }
63+
64+ ListModel {
65+ id: mockNotificationsModel
66+
67+ function getRaw(id) {
68+ return mockNotification.createObject(mockNotificationsModel)
69+ }
70+ }
71+
72+ function addNotification() {
73+ var n = {
74+ type: Notification.Confirmation,
75+ hints: {},
76+ summary: "",
77+ body: "",
78+ icon: "",
79+ secondaryIcon: "",
80+ actions: []
81+ };
82+
83+ mockNotificationsModel.append(n);
84+ }
85+
5886 Component.onCompleted: {
5987 // must set the mock mode before loading the Shell
6088 LightDM.Greeter.mockMode = "single-pin";
@@ -231,6 +259,8 @@ Rectangle {
231259 prepareShell();
232260
233261 var tutorialLeft = findChild(shell, "tutorialLeft");
262+ var tutorialLeftTimer = findInvisibleChild(tutorialLeft, "tutorialLeftTimer");
263+ tutorialLeftTimer.interval = 0;
234264 tryCompare(tutorialLeft, "opacity", 1);
235265 }
236266
@@ -260,6 +290,7 @@ Rectangle {
260290 // reload our test subject to get it in a fresh state once again
261291 shellLoader.active = true;
262292
293+ mockNotificationsModel.clear();
263294 tryCompare(shellLoader, "status", Loader.Ready);
264295 removeTimeConstraintsFromSwipeAreas(shellLoader.item);
265296 }
@@ -300,40 +331,41 @@ Rectangle {
300331 var tutorialTopTimer = findInvisibleChild(tutorialTop, "tutorialTopTimer");
301332
302333 tutorialTopTimer.interval = 1;
303− AccountsService.demoEdgesCompleted = ["left", "left-long"];
334+ AccountsService.demoEdgesCompleted = ["left"];
304335
305336 tryCompare(tutorialLeftLoader, "active", false);
306337 tryCompare(tutorialTop, "shown", true);
307338 tryCompare(tutorialTop, "opacity", 1);
308339 }
309340
341+ function openTutorialLeftLong() {
342+ var tutorialLeftLong = findChild(shell, "tutorialLeftLong");
343+ var tutorialLeftLongTimer = findChild(tutorialLeftLong, "tutorialLeftLongTimer");
344+
345+ AccountsService.demoEdgesCompleted = ["left", "top"];
346+ ApplicationManager.startApplication("gallery-app");
347+
348+ tutorialLeftLongTimer.interval = 1;
349+ tryCompare(tutorialLeftLong, "shown", true);
350+ tryCompare(tutorialLeftLong, "opacity", 1);
351+ }
352+
310353 function openTutorialRight() {
311354 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
312355 var tutorialRight = findChild(shell, "tutorialRight");
356+ var tutorialRightTimer = findChild(tutorialRight, "tutorialRightTimer");
313357
314− AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
358+ AccountsService.demoEdgesCompleted = ["left", "top", "left-long"];
315359 ApplicationManager.startApplication("gallery-app");
316360 ApplicationManager.startApplication("facebook-webapp");
361+ ApplicationManager.startApplication("camera-app");
317362
318363 tryCompare(tutorialLeftLoader, "active", false);
364+ tutorialRightTimer.interval = 1;
319365 tryCompare(tutorialRight, "shown", true);
320366 tryCompare(tutorialRight, "opacity", 1);
321367 }
322368
323− function openTutorialBottom() {
324− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
325− var tutorialBottom = findChild(shell, "tutorialBottom");
326−
327− AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right"];
328− tryCompare(tutorialLeftLoader, "active", false);
329−
330− ApplicationManager.startApplication("dialer-app");
331− ApplicationManager.requestFocusApplication("dialer-app");
332−
333− tryCompare(tutorialBottom, "shown", true);
334− tryCompare(tutorialBottom, "opacity", 1);
335− }
336−
337369 function test_tutorialLeftEdges() {
338370 var tutorial = findChild(shell, "tutorial");
339371 var tutorialLeft = findChild(tutorial, "tutorialLeft");
@@ -396,19 +428,21 @@ Rectangle {
396428 tryCompare(launcher, "state", "visible");
397429 }
398430
399− function test_tutorialLeftLongDrag() {
400− // Just confirm that a long drag ("dash" drag) doesn't confuse us
431+ function test_tutorialLeftLongFinish() {
432+ AccountsService.demoEdgesCompleted = ["left", "top"];
433+
434+ var tutorialLeftLongTimer = findInvisibleChild(shell, "tutorialLeftLongTimer");
435+ tutorialLeftLongTimer.interval = 1;
401436
402− // So that we actually switch to dash and launcher hides
403437 ApplicationManager.startApplication("gallery-app");
404438
405− var launcher = findChild(shell, "launcher");
406− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
439+ var tutorialLeftLongLoader = findChild(shell, "tutorialLeftLongLoader");
440+ tryCompare(tutorialLeftLongLoader, "shown", true);
407441
408442 touchFlick(shell, 0, halfHeight, shell.width, halfHeight);
409443
410− tryCompare(tutorialLeftLoader, "shown", false);
411− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long"]);
444+ tryCompare(tutorialLeftLongLoader, "shown", false);
445+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top", "left-long"]);
412446 }
413447
414448 function test_tutorialLeftAutoSkipped() {
@@ -423,6 +457,24 @@ Rectangle {
423457 tryCompare(AccountsService, "demoEdgesCompleted", ["left"]);
424458 }
425459
460+ function test_tutorialLongLeftSwipeDisabled() {
461+ // Test that a long left swipe is disabled until we get to or pass
462+ // the long left tutorial.
463+ var tutorial = findChild(shell, "tutorial");
464+
465+ verify(!tutorial.launcherLongSwipeEnabled);
466+
467+ openTutorialLeftLong();
468+ verify(tutorial.launcherLongSwipeEnabled);
469+
470+ openTutorialRight();
471+ verify(tutorial.launcherLongSwipeEnabled);
472+
473+ AccountsService.demoEdges = false;
474+ tryCompare(tutorial, "running", false);
475+ verify(tutorial.launcherLongSwipeEnabled);
476+ }
477+
426478 function test_tutorialTopEdges() {
427479 var tutorial = findChild(shell, "tutorial");
428480 var tutorialTop = findChild(tutorial, "tutorialTop");
@@ -451,7 +503,7 @@ Rectangle {
451503 touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
452504
453505 tryCompare(tutorialTopLoader, "shown", false);
454− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
506+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top"]);
455507 tryCompare(panel.indicators, "fullyOpened", true);
456508 }
457509
@@ -477,12 +529,12 @@ Rectangle {
477529
478530 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
479531 var tutorialTopLoader = findChild(shell, "tutorialTopLoader");
480− AccountsService.demoEdgesCompleted = ["left", "left-long"];
532+ AccountsService.demoEdgesCompleted = ["left"];
481533 tryCompare(tutorialLeftLoader, "active", false);
482534 verify(!tutorialTopLoader.shown);
483535
484536 touchFlick(shell, halfWidth, 0, halfWidth, shell.height);
485− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top"]);
537+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top"]);
486538 }
487539
488540 function test_tutorialRightEdges() {
@@ -505,15 +557,11 @@ Rectangle {
505557 }
506558
507559 function test_tutorialRightFinish() {
508− var tutorial = findChild(shell, "tutorial");
509− var tutorialRightLoader = findChild(tutorial, "tutorialRightLoader");
510− var stage = findChild(shell, "stage");
511−
512560 openTutorialRight();
513561 touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
514562
515− tryCompare(tutorialRightLoader, "shown", false);
516− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right"]);
563+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "top", "left-long", "right"]);
564+ tryCompare(AccountsService, "demoEdges", false);
517565 }
518566
519567 function test_tutorialRightShortDrag() {
@@ -537,17 +585,18 @@ Rectangle {
537585 // Test that if we exit the top tutorial, we don't immediately
538586 // jump into right tutorial.
539587 var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
540− var tutorialRightTimer = findInvisibleChild(tutorialRightLoader, "tutorialRightInactivityTimer");
588+ var tutorialRightTimer = findInvisibleChild(tutorialRightLoader, "tutorialRightTimer");
541589
542− tutorialRightTimer.interval = 1;
543590 openTutorialTop();
544591 ApplicationManager.startApplication("gallery-app");
545592 ApplicationManager.startApplication("facebook-webapp");
546− tryCompare(ApplicationManager, "count", 3);
593+ ApplicationManager.startApplication("camera-app");
594+ tryCompare(ApplicationManager, "count", 4);
547595
548− AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
549− verify(tutorialRightTimer.running, true);
596+ AccountsService.demoEdgesCompleted = ["left", "top", "left-long"];
597+ verify(tutorialRightTimer.running);
550598 verify(!tutorialRightLoader.shown);
599+ tutorialRightTimer.interval = 1;
551600 tryCompare(tutorialRightLoader, "shown", true);
552601 }
553602
@@ -555,112 +604,11 @@ Rectangle {
555604 // Test that we skip the tutorial if user uses right edge themselves
556605
557606 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
558− AccountsService.demoEdgesCompleted = ["left", "left-long"];
607+ AccountsService.demoEdgesCompleted = ["left"];
559608 tryCompare(tutorialLeftLoader, "active", false);
560609
561610 touchFlick(shell, shell.width, halfHeight, 0, halfHeight);
562− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "right"]);
563− }
564−
565− function test_tutorialBottomEdges() {
566− var tutorial = findChild(shell, "tutorial");
567− var tutorialBottom = findChild(tutorial, "tutorialBottom");
568− var tutorialLabel = findChild(tutorialBottom, "tutorialLabel");
569− var launcher = findChild(shell, "launcher");
570− var stage = findChild(shell, "stage");
571− var panel = findChild(shell, "panel");
572−
573− openTutorialBottom();
574−
575− tryCompare(tutorial, "running", true);
576− verify(!tutorial.launcherEnabled);
577− verify(!tutorial.spreadEnabled);
578− verify(!tutorial.panelEnabled);
579− verify(tutorialBottom.shown);
580− verify(!launcher.available);
581− verify(!stage.spreadEnabled);
582− verify(!panel.indicators.available);
583− compare(tutorialLabel.text, "Swipe up for recent calls");
584− }
585−
586− function test_tutorialBottomFinish() {
587− var tutorial = findChild(shell, "tutorial");
588− var tutorialBottomLoader = findChild(tutorial, "tutorialBottomLoader");
589−
590− openTutorialBottom();
591− touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
592−
593− tryCompare(tutorialBottomLoader, "shown", false);
594− tryCompare(AccountsService, "demoEdgesCompleted", ["left", "left-long", "top", "right", "bottom-dialer-app"]);
595−
596− // OK, we did one, just confirm that when all are done, we mark whole tutorial as done.
597− verify(AccountsService.demoEdges);
598− AccountsService.demoEdgesCompleted = ["left", "left-long", "top", "right",
599− "bottom-address-book-app",
600− "bottom-com.ubuntu.calculator_calculator",
601− "bottom-dialer-app",
602− "bottom-messaging-app"];
603− verify(!AccountsService.demoEdges);
604− }
605−
606− function test_tutorialBottomAppearsBeforeRight() {
607− // Confirm that if bottom edge and right edge would appear on the
608− // the same app open, bottom edge appears first. (this is a lightly
609− // edited version of openTutorialRight)
610− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
611− var tutorialRight = findChild(shell, "tutorialRight");
612− var tutorialBottom = findChild(shell, "tutorialBottom");
613−
614− AccountsService.demoEdgesCompleted = ["left", "left-long", "top"];
615− ApplicationManager.startApplication("gallery-app");
616− ApplicationManager.startApplication("dialer-app");
617−
618− tryCompare(tutorialLeftLoader, "active", false);
619− tryCompare(tutorialBottom, "shown", true);
620− tryCompare(tutorialBottom, "opacity", 1);
621− tryCompare(tutorialRight, "visible", false);
622− }
623−
624− function test_tutorialBottomOnlyCoversSideStageOnTablet() {
625− loadShell("tablet");
626−
627− var tutorialBottom = findChild(shell, "tutorialBottom");
628− var targetHeight = shell.height - units.gu(4);
629− var mainStageX = units.gu(20);
630− var sideStageX = shell.width - units.gu(20);
631−
632− WindowStateStorage.saveStage("dialer-app", ApplicationInfoInterface.SideStage);
633− openTutorialBottom();
634−
635− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
636− compare(tutorialBottom.opacity, 1);
637− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
638−
639− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
640− verify(tutorialBottom.opacity < 1);
641− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
642− }
643−
644− function test_tutorialBottomOnlyCoversMainStageOnTablet() {
645− loadShell("tablet");
646−
647− var tutorialBottom = findChild(shell, "tutorialBottom");
648− var targetHeight = shell.height - units.gu(4);
649− var mainStageX = units.gu(20);
650− var sideStageX = shell.width - units.gu(20);
651−
652− WindowStateStorage.saveStage("notes-app", ApplicationInfoInterface.SideStage);
653− ApplicationManager.startApplication("notes-app");
654−
655− openTutorialBottom();
656−
657− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, true, false);
658− compare(tutorialBottom.opacity, 1);
659− touchFlick(shell, sideStageX, shell.height, sideStageX, targetHeight, false, true);
660−
661− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, true, false);
662− verify(tutorialBottom.opacity < 1);
663− touchFlick(shell, mainStageX, shell.height, mainStageX, targetHeight, false, true);
611+ tryCompare(AccountsService, "demoEdgesCompleted", ["left", "right"]);
664612 }
665613
666614 function test_activeCallInterruptsTutorial() {
@@ -678,31 +626,6 @@ Rectangle {
678626 verify(!tutorialLeft.paused);
679627 }
680628
681− function test_dialerInterruptionWithNoOverlappingTutorials() {
682− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
683− var tutorialBottomLoader = findChild(shell, "tutorialBottomLoader");
684− verify(tutorialLeftLoader.shown);
685−
686− // Start call, hiding left tutorial
687− callManager.foregroundCall = phoneCall;
688− tryCompare(tutorialLeftLoader, "shown", false);
689−
690− // Start dialer app
691− ApplicationManager.startApplication("dialer-app");
692− tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
693− verify(!tutorialBottomLoader.shown);
694−
695− // Dismiss call, bottom tutorial should appear
696− callManager.foregroundCall = null;
697− tryCompare(tutorialBottomLoader, "shown", true);
698− verify(!tutorialLeftLoader.shown);
699−
700− // Get rid of bottom tutorial, left should now be shown
701− touchFlick(shell, halfWidth, shell.height, halfWidth, halfHeight);
702− tryCompare(tutorialBottomLoader, "shown", false);
703− tryCompare(tutorialLeftLoader, "shown", true);
704− }
705−
706629 function test_greeterInterruptsTutorial() {
707630 var tutorialLeft = findChild(shell, "tutorialLeft");
708631 verify(tutorialLeft.shown);
@@ -738,7 +661,7 @@ Rectangle {
738661 verify(!tutorialRight.isReady);
739662 verify(!tutorialRight.shown);
740663 verify(!tutorialRight.paused);
741− compare(AccountsService.demoEdgesCompleted, ["left", "left-long", "top"]);
664+ compare(AccountsService.demoEdgesCompleted, ["left", "top", "left-long"]);
742665 }
743666
744667 function test_desktopOnlyShowsTutorialRight() {
@@ -746,17 +669,22 @@ Rectangle {
746669
747670 var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
748671 var tutorialTopLoader = findChild(shell, "tutorialTopLoader");
672+ var tutorialLeftLongLoader = findChild(shell, "tutorialLeftLongLoader");
749673 var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
750− var tutorialBottomLoader = findChild(shell, "tutorialBottomLoader");
751674 verify(!tutorialLeftLoader.active);
752675 verify(!tutorialTopLoader.active);
676+ verify(!tutorialLeftLongLoader.active);
753677 verify(tutorialRightLoader.active);
754− verify(!tutorialBottomLoader.active);
755678 compare(AccountsService.demoEdgesCompleted, []);
756679
680+ var tutorialRightTimer = findInvisibleChild(tutorialRightLoader, "tutorialRightTimer");
681+ tutorialRightTimer.interval = 1;
682+
757683 ApplicationManager.startApplication("dialer-app");
758684 ApplicationManager.startApplication("camera-app");
685+ ApplicationManager.startApplication("facebook-webapp");
759686 tryCompare(tutorialRightLoader.item, "isReady", true);
687+
760688 tryCompare(tutorialRightLoader, "shown", true);
761689 }
762690
@@ -764,8 +692,11 @@ Rectangle {
764692 loadShell("desktop");
765693
766694 var tutorialRightLoader = findChild(shell, "tutorialRightLoader");
695+ var tutorialRightTimer = findInvisibleChild(tutorialRightLoader, "tutorialRightTimer");
696+ tutorialRightTimer.interval = 1;
767697 ApplicationManager.startApplication("dialer-app");
768698 ApplicationManager.startApplication("camera-app");
699+ ApplicationManager.startApplication("facebook-webapp");
769700 tryCompare(tutorialRightLoader, "shown", true);
770701
771702 var stage = findChild(shell, "stage");
@@ -789,24 +720,60 @@ Rectangle {
789720 verify(tutorialLeftLoader.shown);
790721 }
791722
792− function test_oskPreventsTutorial() {
793− var surface = SurfaceManager.inputMethodSurface;
794− var inputMethod = findInvisibleChild(shell, "inputMethod");
723+ function test_oskDelaysTutorial() {
724+ var tutorial = findChild(shell, "tutorial");
725+ verify(!tutorial.delayed);
795726
796− AccountsService.demoEdges = false;
797− surface.setState(Mir.RestoredState);
798− tryCompare(inputMethod, "state", "shown");
727+ SurfaceManager.inputMethodSurface.setState(Mir.RestoredState);
799728
729+ tryCompare(tutorial, "delayed", true);
730+ }
731+
732+ function test_notificationDelaysTutorial() {
800733 var tutorial = findChild(shell, "tutorial");
801− tryCompare(tutorial, "keyboardVisible", true);
734+ verify(!tutorial.delayed);
802735
803− AccountsService.demoEdges = true;
804− var tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
805− verify(!tutorialLeftLoader.shown);
736+ var notifications = findChild(shell, "notificationList");
737+ notifications.model = mockNotificationsModel;
738+ addNotification(); // placeholder
739+ addNotification();
806740
807− surface.setState(Mir.MinimizedState);
808− tryCompare(inputMethod, "state", "hidden");
809− tryCompare(tutorialLeftLoader, "shown", false);
741+ tryCompare(tutorial, "delayed", true);
742+ }
743+
744+ function test_dialogDelaysTutorial() {
745+ var tutorial = findChild(shell, "tutorial");
746+ verify(!tutorial.delayed);
747+
748+ var dialogs = findChild(shell, "dialogs");
749+ dialogs.showPowerDialog();
750+
751+ verify(tutorial.delayed);
752+ }
753+
754+ function test_delayedTutorial() {
755+ var tutorial = findChild(shell, "tutorial");
756+ var tutorialTop = findChild(tutorial, "tutorialTop");
757+ var tutorialTopTimer = findChild(tutorialTop, "tutorialTopTimer");
758+
759+ // Get top tutorial ready
760+ AccountsService.demoEdgesCompleted = ["left"];
761+ verify(tutorialTop.isReady);
762+ verify(tutorialTopTimer.running);
763+
764+ // Confirm that we become unready when delayed, but timer still goes
765+ tutorial.delayed = true;
766+ verify(!tutorialTop.isReady);
767+ verify(tutorialTopTimer.running);
768+
769+ // Confirm that we don't open the tutorial when delayed
770+ tutorialTopTimer.interval = 1;
771+ wait(5);
772+ verify(!tutorialTop.shown);
773+
774+ // Confirm we go back to normal when undelayed
775+ tutorial.delayed = false;
776+ tryCompare(tutorialTop, "shown", true);
810777 }
811778
812779 function test_accountsServiceSettings() {
@@ -818,7 +785,8 @@ Rectangle {
818785
819786 AccountsService.demoEdges = true;
820787 tutorialLeftLoader = findChild(shell, "tutorialLeftLoader");
821− tryCompare(tutorialLeftLoader, "shown", true);
788+ var tutorialLeftTimer = findChild(tutorialLeftLoader, "tutorialLeftTimer");
789+ verify(tutorialLeftTimer.running);
822790 }
823791 }
824792}