on xenial help sign in
Really fix binding and add a test for the binding, fixing up some mock delta along the way
commit9007ce1773522d8d0df71405c30efefa2f3fcaef authorMichael Terry <michael.terry@canonical.com> dateTue 3 May 2016, 14:38 (10 years ago) parentf8d95b6
7 files changed+113−83
qml/Shell.qml+2−1 tests/mocks/Unity/Notifications/MockNotificationModel.cpp+23−5 tests/mocks/Unity/Notifications/MockNotificationModel.h+8 tests/mocks/Unity/Notifications/plugin.cpp+6−1 tests/qmltests/Notifications/tst_Notifications.qml+45−49 tests/qmltests/Tutorial/tst_Tutorial.qml+13−26 tests/qmltests/tst_Shell.qml+16−1
qml/Shell.qml+2−1
@@ -669,7 +669,8 @@ Item {
669669
670670 Binding {
671671 target: NotificationBackend.Model
672− paused: tutorial.running
672+ property: "paused"
673+ value: tutorial.running
673674 }
674675
675676 states: [
tests/mocks/Unity/Notifications/MockNotificationModel.cpp+23−5
@@ -31,14 +31,14 @@
3131
3232using namespace unity::shell::notifications;
3333
34−MockNotificationModel::MockNotificationModel(QObject *parent) : QAbstractListModel(parent) {
34+MockNotificationModel::MockNotificationModel(QObject *parent)
35+ : QAbstractListModel(parent)
36+ , m_paused(false)
37+{
3538}
3639
3740MockNotificationModel::~MockNotificationModel() {
38− Q_FOREACH(MockNotification *n, m_queue) {
39− n->deleteLater();
40− }
41− m_queue.clear();
41+ clear();
4242}
4343
4444int MockNotificationModel::rowCount(const QModelIndex &) const {
@@ -89,6 +89,17 @@ QVariant MockNotificationModel::data(const QModelIndex &index, int role) const {
8989 }
9090}
9191
92+bool MockNotificationModel::getPaused() const {
93+ return m_paused;
94+}
95+
96+void MockNotificationModel::setPaused(bool paused) {
97+ if (m_paused != paused) {
98+ m_paused = paused;
99+ Q_EMIT pausedChanged(paused);
100+ }
101+}
102+
92103void MockNotificationModel::append(MockNotification* n) {
93104 int location = m_queue.size();
94105 QModelIndex insertionPoint = QModelIndex();
@@ -107,6 +118,13 @@ MockNotification* MockNotificationModel::getNotification(int id) const {
107118 return nullptr;
108119}
109120
121+void MockNotificationModel::clear() {
122+ Q_FOREACH(MockNotification *n, m_queue) {
123+ n->deleteLater();
124+ }
125+ m_queue.clear();
126+}
127+
110128void MockNotificationModel::remove(const int id) {
111129 for(int i = 0; i < m_queue.size(); i++) {
112130 if(m_queue[i]->getID() == id) {
tests/mocks/Unity/Notifications/MockNotificationModel.h+8
@@ -30,6 +30,7 @@ class MockNotification;
3030class MockNotificationModel : public QAbstractListModel {
3131 Q_OBJECT
3232 Q_PROPERTY(int count READ getCount)
33+ Q_PROPERTY(bool paused READ getPaused WRITE setPaused NOTIFY pausedChanged)
3334
3435public:
3536 MockNotificationModel(QObject *parent=nullptr);
@@ -39,6 +40,9 @@ public:
3940 QVariant data(const QModelIndex &index, int role) const override;
4041 QHash<int, QByteArray> roleNames() const override;
4142
43+ bool getPaused() const;
44+ void setPaused(bool paused);
45+
4246 Q_INVOKABLE void append(MockNotification* n);
4347 MockNotification* getNotification(int id) const;
4448
@@ -50,6 +54,8 @@ public:
5054 Q_INVOKABLE void remove(const int id);
5155 Q_INVOKABLE void removeSecond();
5256
57+ Q_INVOKABLE void clear(); // only in mock
58+
5359 int getCount() const;
5460
5561Q_SIGNALS:
@@ -63,9 +69,11 @@ private Q_SLOTS:
6369
6470Q_SIGNALS:
6571 void queueSizeChanged(int newSize);
72+ void pausedChanged(bool paused);
6673
6774private:
6875 QList<MockNotification*> m_queue;
76+ bool m_paused;
6977 void removeInternal(int loc);
7078};
7179
tests/mocks/Unity/Notifications/plugin.cpp+6−1
@@ -24,10 +24,15 @@
2424
2525#include <QtQml/qqml.h>
2626
27+static QObject* modelProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
28+{
29+ return new MockNotificationModel;
30+}
31+
2732void TestNotificationPlugin::registerTypes(const char* uri)
2833{
2934 // @uri Unity.Notifications
3035 qmlRegisterType<MockNotification>(uri, 1, 0, "Notification");
31− qmlRegisterType<MockNotificationModel>(uri, 1, 0, "NotificationModel");
36+ qmlRegisterSingletonType<MockNotificationModel>(uri, 1, 0, "Model", modelProvider);
3237 qmlRegisterType<ActionModel>(uri, 1, 0, "ActionModel");
3338}
tests/qmltests/Notifications/tst_Notifications.qml+45−49
@@ -34,23 +34,19 @@ Item {
3434 Row {
3535 id: rootRow
3636
37− NotificationModel {
38− id: mockModel
39−
40− // add the default/PlaceHolder notification to the model
41− Component.onCompleted: {
42− var component = Qt.createComponent("Notification.qml")
43− var n = component.createObject("notification", {"nid": index++,
44− "type": Notification.PlaceHolder,
45− "hints": {},
46− "summary": "",
47− "body": "",
48− "icon": "",
49− "secondaryIcon": "",
50− "rawActions": []})
51− n.completed.connect(mockModel.onCompleted)
52− append(n)
53− }
37+ // add the default/PlaceHolder notification to the model
38+ Component.onCompleted: {
39+ var component = Qt.createComponent("Notification.qml")
40+ var n = component.createObject("notification", {"nid": index++,
41+ "type": Notification.PlaceHolder,
42+ "hints": {},
43+ "summary": "",
44+ "body": "",
45+ "icon": "",
46+ "secondaryIcon": "",
47+ "rawActions": []})
48+ n.completed.connect(Model.onCompleted)
49+ Model.append(n)
5450 }
5551
5652 function add2over1SnapDecisionNotification() {
@@ -65,8 +61,8 @@ Item {
6561 "rawActions": ["ok_id", "Ok",
6662 "snooze_id", "Snooze",
6763 "view_id", "View"]})
68− n.completed.connect(mockModel.onCompleted)
69− mockModel.append(n)
64+ n.completed.connect(Model.onCompleted)
65+ Model.append(n)
7066 }
7167
7268 function addEphemeralNotification() {
@@ -79,8 +75,8 @@ Item {
7975 "icon": "../../tests/graphics/avatars/amanda.png",
8076 "secondaryIcon": "../../tests/graphics/applicationIcons/facebook.png",
8177 "rawActions": ["reply_id", "Dummy"]})
82− n.completed.connect(mockModel.onCompleted)
83− mockModel.append(n)
78+ n.completed.connect(Model.onCompleted)
79+ Model.append(n)
8480 }
8581
8682 function addEphemeralNonShapedIconNotification() {
@@ -93,8 +89,8 @@ Item {
9389 "icon": "../../tests/graphics/applicationIcons/contacts-app.png",
9490 "secondaryIcon": "",
9591 "rawActions": ["reply_id", "Dummy"]})
96− n.completed.connect(mockModel.onCompleted)
97− mockModel.append(n)
92+ n.completed.connect(Model.onCompleted)
93+ Model.append(n)
9894 }
9995
10096 function addEphemeralIconSummaryNotification() {
@@ -107,8 +103,8 @@ Item {
107103 "icon": "../../tests/graphics/applicationIcons/facebook.png",
108104 "secondaryIcon": "",
109105 "rawActions": ["reply_id", "Dummy"]})
110− n.completed.connect(mockModel.onCompleted)
111− mockModel.append(n)
106+ n.completed.connect(Model.onCompleted)
107+ Model.append(n)
112108 }
113109
114110 function addInteractiveNotification() {
@@ -121,8 +117,8 @@ Item {
121117 "icon": "../../tests/graphics/avatars/anna_olsson.png",
122118 "secondaryIcon": "",
123119 "rawActions": ["reply_id", "Dummy"]})
124− n.completed.connect(mockModel.onCompleted)
125− mockModel.append(n)
120+ n.completed.connect(Model.onCompleted)
121+ Model.append(n)
126122 }
127123
128124 function addConfirmationNotification() {
@@ -136,8 +132,8 @@ Item {
136132 "secondaryIcon": "",
137133 "value": 50,
138134 "rawActions": ["reply_id", "Dummy"]})
139− n.completed.connect(mockModel.onCompleted)
140− mockModel.append(n)
135+ n.completed.connect(Model.onCompleted)
136+ Model.append(n)
141137 }
142138
143139 function add2ndConfirmationNotification() {
@@ -152,19 +148,19 @@ Item {
152148 "secondaryIcon": "",
153149 "value": 85,
154150 "rawActions": ["reply_id", "Dummy"]})
155− n.completed.connect(mockModel.onCompleted)
156− mockModel.append(n)
151+ n.completed.connect(Model.onCompleted)
152+ Model.append(n)
157153 }
158154
159155 function clearNotifications() {
160− while(mockModel.count > 1) {
156+ while(Model.count > 1) {
161157 remove1stNotification()
162158 }
163159 }
164160
165161 function remove1stNotification() {
166− if (mockModel.count > 1) {
167− mockModel.removeSecond()
162+ if (Model.count > 1) {
163+ Model.removeSecond()
168164 }
169165 }
170166
@@ -186,7 +182,7 @@ Item {
186182 margin: units.gu(1)
187183
188184 anchors.fill: parent
189− model: mockModel
185+ model: Model
190186 hasMouse: fakeMouseCB.checked
191187 inverseMode: inverseModeCB.checked
192188 }
@@ -558,7 +554,7 @@ Item {
558554 SignalSpy {
559555 id: actionSpy
560556
561− target: mockModel
557+ target: Model
562558 signalName: "actionInvoked"
563559 }
564560
@@ -569,19 +565,19 @@ Item {
569565
570566 function test_NotificationRenderer(data) {
571567 // make sure the clicks on mocked notifications can be checked against by "actionSpy" (mimicking the NotificationServer component)
572− data.n.actionInvoked.connect(mockModel.actionInvoked)
568+ data.n.actionInvoked.connect(Model.actionInvoked)
573569
574570 // hook up notification's completed-signal with model's onCompleted-slot, so that remove() (model) happens on close() (notification)
575− data.n.completed.connect(mockModel.onCompleted)
571+ data.n.completed.connect(Model.onCompleted)
576572
577573 // populate model with some mock notifications
578− mockModel.append(data.n)
574+ Model.append(data.n)
579575
580576 // make sure the view is properly updated before going on
581577 notifications.forceLayout();
582578 waitForRendering(notifications);
583579
584− var notification = findChild(notifications, "notification" + (mockModel.count - 1))
580+ var notification = findChild(notifications, "notification" + (Model.count - 1))
585581 verify(notification !== undefined, "notification wasn't found");
586582
587583 waitForRendering(notification);
@@ -627,7 +623,7 @@ Item {
627623
628624 // After clicking the state of notifications can change so let's wait
629625 // for their height animations to finish before continuing
630− for (var i = 0; i < mockModel.count; ++i) {
626+ for (var i = 0; i < Model.count; ++i) {
631627 var n = findChild(notifications, "notification" + i)
632628 tryCompare(n, "height", n.state === "contracted" ? units.gu(10) : n.implicitHeight);
633629 }
@@ -685,16 +681,16 @@ Item {
685681
686682 // swipe-to-dismiss check
687683 waitForRendering(notification)
688− var before = mockModel.count
684+ var before = Model.count
689685 var dragStart = notification.width * 0.25;
690686 var dragEnd = notification.width;
691687 var dragY = notification.height / 2;
692688 touchFlick(notification, dragStart, dragY, dragEnd, dragY)
693689 waitForRendering(notification)
694690 if ((data.n.type === Notification.SnapDecision && notification.state === "expanded") || data.n.type === Notification.Confirmation) {
695− tryCompare(mockModel, "count", before)
691+ tryCompare(Model, "count", before)
696692 } else {
697− tryCompare(mockModel, "count", before - 1)
693+ tryCompare(Model, "count", before - 1)
698694 }
699695 }
700696
@@ -705,27 +701,27 @@ Item {
705701
706702 function test_clickToClose(data) {
707703 // populate model with some mock notifications
708− mockModel.append(data.n)
704+ Model.append(data.n)
709705
710706 // make sure the view is properly updated before going on
711707 notifications.forceLayout();
712708 waitForRendering(notifications);
713709
714− var notification = findChild(notifications, "notification" + (mockModel.count - 1))
710+ var notification = findChild(notifications, "notification" + (Model.count - 1))
715711 verify(!!notification, "notification wasn't found");
716712
717713 // click-to-dismiss check
718714 waitForRendering(notification);
719− var before = mockModel.count;
715+ var before = Model.count;
720716 var canBeClosed = notification.canBeClosed;
721717 mouseClick(notification);
722718
723719 if (canBeClosed) {
724720 // closing the notification, the model count should be one less
725− tryCompare(mockModel, "count", before - 1)
721+ tryCompare(Model, "count", before - 1)
726722 } else {
727723 // not closing, model stays the same
728− tryCompare(mockModel, "count", before)
724+ tryCompare(Model, "count", before)
729725 }
730726 }
731727
tests/qmltests/Tutorial/tst_Tutorial.qml+13−26
@@ -22,7 +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
25+import Unity.Notifications 1.0 as NotificationBackend
2626import Unity.Test 0.1 as UT
2727import Utils 0.1
2828
@@ -57,32 +57,21 @@ Rectangle {
5757 }
5858
5959 Component {
60− id: mockNotification
61− QtObject {}
62− }
63−
64− ListModel {
65− id: mockNotificationsModel
66−
67− property bool paused
68−
69− function getRaw(id) {
70− return mockNotification.createObject(mockNotificationsModel)
60+ id: notification
61+ NotificationBackend.Notification {
62+ nid: 1
63+ type: NotificationBackend.Notification.Confirmation
64+ summary: ""
65+ body: ""
66+ icon: ""
67+ secondaryIcon: ""
68+ value: 0
69+ rawActions: []
7170 }
7271 }
7372
7473 function addNotification() {
75− var n = {
76− type: Notification.Confirmation,
77− hints: {},
78− summary: "",
79− body: "",
80− icon: "",
81− secondaryIcon: "",
82− actions: []
83− };
84−
85− mockNotificationsModel.append(n);
74+ NotificationBackend.Model.append(notification.createObject());
8675 }
8776
8877 Component.onCompleted: {
@@ -288,11 +277,11 @@ Rectangle {
288277
289278 // kill all (fake) running apps
290279 killApps();
280+ NotificationBackend.Model.clear();
291281
292282 // reload our test subject to get it in a fresh state once again
293283 shellLoader.active = true;
294284
295− mockNotificationsModel.clear();
296285 tryCompare(shellLoader, "status", Loader.Ready);
297286 removeTimeConstraintsFromDirectionalDragAreas(shellLoader.item);
298287 }
@@ -734,8 +723,6 @@ Rectangle {
734723 var tutorial = findChild(shell, "tutorial");
735724 verify(!tutorial.delayed);
736725
737− var notifications = findChild(shell, "notificationList");
738− notifications.model = mockNotificationsModel;
739726 addNotification();
740727
741728 tryCompare(tutorial, "delayed", true);
tests/qmltests/tst_Shell.qml+16−1
@@ -25,7 +25,7 @@ import Ubuntu.Telephony 0.1 as Telephony
2525import Unity.Application 0.1
2626import Unity.Connectivity 0.1
2727import Unity.Indicators 0.1
28−import Unity.Notifications 1.0
28+import Unity.Notifications 1.0 as NotificationBackend
2929import Unity.Launcher 0.1
3030import Unity.Test 0.1
3131import Powerd 0.1
@@ -1289,6 +1289,21 @@ Rectangle {
12891289 tryCompare(tutorial, "paused", false);
12901290 }
12911291
1292+ function test_notificationsPausedDuringTutorial() {
1293+ loadShell("phone");
1294+ swipeAwayGreeter();
1295+ verify(!NotificationBackend.Model.paused);
1296+
1297+ AccountsService.demoEdges = true;
1298+ var tutorialLeft = findChild(shell, "tutorialLeft");
1299+ var tutorialLeftTimer = findInvisibleChild(tutorialLeft, "tutorialLeftTimer");
1300+ tutorialLeftTimer.interval = 0;
1301+ tryCompare(NotificationBackend.Model, "paused", true);
1302+
1303+ AccountsService.demoEdges = false;
1304+ tryCompare(NotificationBackend.Model, "paused", false);
1305+ }
1306+
12921307 function test_tapOnRightEdgeReachesApplicationSurface() {
12931308 loadShell("phone");
12941309 swipeAwayGreeter();