@@ -1,17 +1,20 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright 2015 Canonical Ltd.
33 *
44 * 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
5+ * it under the terms of the GNU Lesser General Public License as published by
66 * the Free Software Foundation; version 3.
77 *
88 * This program is distributed in the hope that it will be useful,
99 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
11+ * GNU Lesser General Public License for more details.
1212 *
13− * You should have received a copy of the GNU General Public License
13+ * You should have received a copy of the GNU Lesser General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Mirco Mueller <mirco.mueller@canonical.com>
1518 */
1619
1720import QtQuick 2.0
@@ -24,146 +27,134 @@ import Unity.Notifications 1.0
2427import QtMultimedia 5.0
2528
2629Item {
30+ id: foobar
31+
2732 width: notificationsRect.width + interactiveControls.width
2833 height: notificationsRect.height
34+ property int index: 0
2935
3036 Row {
3137 id: rootRow
3238
33− Component {
34− id: mockNotification
35−
36− QtObject {
37− function invokeAction(actionId) {
38− mockModel.actionInvoked(actionId)
39− }
40− }
41− }
42−
43− ListModel {
39+ NotificationModel {
4440 id: mockModel
45− dynamicRoles: true
46−
47− signal actionInvoked(string actionId)
48−
49− function getRaw(id) {
50− return mockNotification.createObject(mockModel)
51− }
5241
5342 // add the default/PlaceHolder notification to the model
5443 Component.onCompleted: {
55− var n = {
56− type: Notification.PlaceHolder,
57− hints: {},
58− summary: "",
59− body: "",
60− icon: "",
61− secondaryIcon: "",
62− actions: []
63− }
64−
44+ var component = Qt.createComponent("Notification.qml")
45+ var n = component.createObject("notification", {"nid": index++,
46+ "type": Notification.PlaceHolder,
47+ "hints": {},
48+ "summary": "",
49+ "body": "",
50+ "icon": "",
51+ "secondaryIcon": "",
52+ "rawActions": []})
53+ n.completed.connect(mockModel.onCompleted)
6554 append(n)
6655 }
6756 }
6857
6958 function add2over1SnapDecisionNotification() {
70− var n = {
71− type: Notification.SnapDecision,
72− hints: {"x-canonical-private-affirmative-tint": "true"},
73− summary: "Theatre at Ferria Stadium",
74− body: "at Ferria Stadium in Bilbao, Spain\n07578545317",
75− icon: "",
76− secondaryIcon: "",
77− actions: [{ id: "ok_id", label: "Ok"},
78− { id: "snooze_id", label: "Snooze"},
79− { id: "view_id", label: "View"}]
80− }
81−
59+ var component = Qt.createComponent("Notification.qml")
60+ var n = component.createObject("notification", {"nid": index++,
61+ "type": Notification.SnapDecision,
62+ "hints": {"x-canonical-private-affirmative-tint": "true"},
63+ "summary": "Theatre at Ferria Stadium",
64+ "body": "at Ferria Stadium in Bilbao, Spain\n07578545317",
65+ "icon": "",
66+ "secondaryIcon": "",
67+ "rawActions": ["ok_id", "Ok",
68+ "snooze_id", "Snooze",
69+ "view_id", "View"]})
70+ n.completed.connect(mockModel.onCompleted)
8271 mockModel.append(n)
8372 }
8473
8574 function addEphemeralNotification() {
86− var n = {
87− type: Notification.Ephemeral,
88− summary: "Cole Raby",
89− body: "I did not expect it to be that late.",
90− icon: "../graphics/avatars/amanda.png",
91− secondaryIcon: "../graphics/applicationIcons/facebook.png",
92− actions: []
93− }
94−
75+ var component = Qt.createComponent("Notification.qml")
76+ var n = component.createObject("notification", {"nid": index++,
77+ "type": Notification.Ephemeral,
78+ "hints": {},
79+ "summary": "Cole Raby",
80+ "body": "I did not expect it to be that late.",
81+ "icon": "../graphics/avatars/amanda.png",
82+ "secondaryIcon": "../graphics/applicationIcons/facebook.png",
83+ "rawActions": ["reply_id", "Dummy"]})
84+ n.completed.connect(mockModel.onCompleted)
9585 mockModel.append(n)
9686 }
9787
9888 function addEphemeralNonShapedIconNotification() {
99− var n = {
100− type: Notification.Ephemeral,
101− hints: {"x-canonical-non-shaped-icon": "true"},
102− summary: "Contacts",
103− body: "Synchronised contacts-database with cloud-storage.",
104− icon: "../graphics/applicationIcons/contacts-app.png",
105− secondaryIcon: "",
106− actions: []
107− }
108−
89+ var component = Qt.createComponent("Notification.qml")
90+ var n = component.createObject("notification", {"nid": index++,
91+ "type": Notification.Ephemeral,
92+ "hints": {"x-canonical-non-shaped-icon": "true"},
93+ "summary": "Contacts",
94+ "body": "Synchronised contacts-database with cloud-storage.",
95+ "icon": "../graphics/applicationIcons/contacts-app.png",
96+ "secondaryIcon": "",
97+ "rawActions": ["reply_id", "Dummy"]})
98+ n.completed.connect(mockModel.onCompleted)
10999 mockModel.append(n)
110100 }
111101
112102 function addEphemeralIconSummaryNotification() {
113− var n = {
114− type: Notification.Ephemeral,
115− hints: {"x-canonical-non-shaped-icon": "false"},
116− summary: "Photo upload completed",
117− body: "",
118− icon: "../graphics/applicationIcons/facebook.png",
119− secondaryIcon: "",
120− actions: []
121− }
122−
103+ var component = Qt.createComponent("Notification.qml")
104+ var n = component.createObject("notification", {"nid": index++,
105+ "type": Notification.Ephemeral,
106+ "hints": {"x-canonical-non-shaped-icon": "false"},
107+ "summary": "Photo upload completed",
108+ "body": "",
109+ "icon": "../graphics/applicationIcons/facebook.png",
110+ "secondaryIcon": "",
111+ "rawActions": ["reply_id", "Dummy"]})
112+ n.completed.connect(mockModel.onCompleted)
123113 mockModel.append(n)
124114 }
125115
126116 function addInteractiveNotification() {
127− var n = {
128− type: Notification.Interactive,
129− summary: "Interactive notification",
130− body: "This is a notification that can be clicked",
131− icon: "../graphics/avatars/anna_olsson.png",
132− secondaryIcon: "",
133− actions: [{ id: "reply_id", label: "Dummy"}],
134− }
135−
117+ var component = Qt.createComponent("Notification.qml")
118+ var n = component.createObject("notification", {"nid": index++,
119+ "type": Notification.Interactive,
120+ "hints": {},
121+ "summary": "Interactive notification",
122+ "body": "This is a notification that can be clicked",
123+ "icon": "../graphics/avatars/anna_olsson.png",
124+ "secondaryIcon": "",
125+ "rawActions": ["reply_id", "Dummy"]})
126+ n.completed.connect(mockModel.onCompleted)
136127 mockModel.append(n)
137128 }
138129
139130 function addConfirmationNotification() {
140− var n = {
141− type: Notification.Confirmation,
142− hints: {"x-canonical-non-shaped-icon": "true"},
143− summary: "Confirmation notification",
144− body: "",
145− icon: "image://theme/audio-volume-medium",
146− secondaryIcon: "",
147− value: 50,
148− actions: [],
149− }
150−
131+ var component = Qt.createComponent("Notification.qml")
132+ var n = component.createObject("notification", {"nid": index++,
133+ "type": Notification.Confirmation,
134+ "hints": {"x-canonical-non-shaped-icon": "true"},
135+ "summary": "Confirmation notification",
136+ "body": "",
137+ "icon": "image://theme/audio-volume-medium",
138+ "secondaryIcon": "",
139+ "value": 50,
140+ "rawActions": ["reply_id", "Dummy"]})
141+ n.completed.connect(mockModel.onCompleted)
151142 mockModel.append(n)
152143 }
153144
154145 function add2ndConfirmationNotification() {
155− var n = {
156− type: Notification.Confirmation,
157− hints: {"x-canonical-non-shaped-icon": "true",
158− "x-canonical-value-bar-tint": "true"},
159− summary: "Confirmation notification",
160− body: "High Volume",
161− icon: "image://theme/audio-volume-high",
162− secondaryIcon: "",
163− value: 85,
164− actions: [],
165− }
166−
146+ var component = Qt.createComponent("Notification.qml")
147+ var n = component.createObject("notification", {"nid": index++,
148+ "type": Notification.Confirmation,
149+ "hints": {"x-canonical-non-shaped-icon": "true",
150+ "x-canonical-value-bar-tint": "true"},
151+ "summary": "Confirmation notification",
152+ "body": "High Volume",
153+ "icon": "image://theme/audio-volume-high",
154+ "secondaryIcon": "",
155+ "value": 85,
156+ "rawActions": ["reply_id", "Dummy"]})
157+ n.completed.connect(mockModel.onCompleted)
167158 mockModel.append(n)
168159 }
169160
@@ -174,8 +165,9 @@ Item {
174165 }
175166
176167 function remove1stNotification() {
177− if (mockModel.count > 1)
178− mockModel.remove(1)
168+ if (mockModel.count > 1) {
169+ mockModel.removeSecond()
170+ }
179171 }
180172
181173 Rectangle {
@@ -273,41 +265,122 @@ Item {
273265 name: "NotificationRendererTest"
274266 when: windowShown
275267
268+ property list<Notification> nlist: [
269+ Notification {
270+ nid: 1
271+ type: Notification.Ephemeral
272+ summary: "Photo upload completed"
273+ body: ""
274+ icon: "../graphics/applicationIcons/facebook.png"
275+ secondaryIcon: ""
276+ value: 0
277+ rawActions: []
278+ },
279+ Notification {
280+ nid: 2
281+ type: Notification.Ephemeral
282+ hints: {"x-canonical-private-affirmative-tint": "false",
283+ "sound-file": "dummy.ogg",
284+ "suppress-sound": "true"}
285+ summary: "New comment successfully published"
286+ body: ""
287+ icon: ""
288+ secondaryIcon: "../graphics/applicationIcons/facebook.png"
289+ value: 0
290+ rawActions: []
291+ },
292+ Notification {
293+ nid: 3
294+ type: Notification.Interactive
295+ hints: {"x-canonical-private-affirmative-tint": "false",
296+ "sound-file": "dummy.ogg"}
297+ summary: "Interactive notification"
298+ body: "This is a notification that can be clicked"
299+ icon: "../graphics/avatars/amanda.png"
300+ secondaryIcon: ""
301+ value: 0
302+ rawActions: ["reply_id", "Dummy"]
303+ },
304+ Notification {
305+ nid: 4
306+ type: Notification.SnapDecision
307+ hints: {"x-canonical-private-affirmative-tint": "false",
308+ "sound-file": "dummy.ogg"}
309+ summary: "Bro Coly"
310+ body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
311+ icon: "../graphics/avatars/anna_olsson.png"
312+ secondaryIcon: ""
313+ value: 0
314+ rawActions: ["accept_id", "Accept",
315+ "reject_id", "Reject"]
316+ },
317+ Notification {
318+ nid: 5
319+ type: Notification.Ephemeral
320+ hints: {"x-canonical-private-affirmative-tint": "false",
321+ "sound-file": "dummy.ogg"}
322+ summary: "Cole Raby"
323+ body: "I did not expect it to be that late."
324+ icon: "../graphics/avatars/funky.png"
325+ secondaryIcon: "../graphics/applicationIcons/facebook.png"
326+ value: 0
327+ rawActions: []
328+ },
329+ Notification {
330+ nid: 6
331+ type: Notification.Ephemeral
332+ hints: {"x-canonical-private-affirmative-tint": "false",
333+ "x-canonical-non-shaped-icon": "true"}
334+ summary: "Contacts"
335+ body: "Synchronised contacts-database with cloud-storage."
336+ icon: "image://theme/contacts-app"
337+ secondaryIcon: ""
338+ value: 0
339+ rawActions: []
340+ },
341+ Notification {
342+ nid: 7
343+ type: Notification.Confirmation
344+ hints: {"x-canonical-non-shaped-icon": "true"}
345+ summary: ""
346+ body: ""
347+ icon: "image://theme/audio-volume-medium"
348+ secondaryIcon: ""
349+ value: 50
350+ rawActions: []
351+ },
352+ Notification {
353+ nid: 8
354+ type: Notification.Confirmation
355+ hints: {"x-canonical-non-shaped-icon": "true",
356+ "x-canonical-value-bar-tint" : "true"}
357+ summary: ""
358+ body: "High Volume"
359+ icon: "image://theme/audio-volume-high"
360+ secondaryIcon: ""
361+ value: 85
362+ rawActions: []
363+ },
364+ Notification {
365+ nid: 9
366+ type: Notification.SnapDecision
367+ hints: {"x-canonical-private-affirmative-tint": "true"}
368+ summary: "Theatre at Ferria Stadium"
369+ body: "at Ferria Stadium in Bilbao, Spain\n07578545317"
370+ icon: ""
371+ secondaryIcon: ""
372+ value: 0
373+ rawActions: ["ok_id", "Ok",
374+ "snooze_id", "Snooze",
375+ "view_id", "View"]
376+ }
377+ ]
378+
276379 function test_NotificationRenderer_data() {
277380 return [
278− {
279− tag: "2-over-1 Snap Decision with button-tint",
280− type: Notification.SnapDecision,
281− hints: {"x-canonical-private-affirmative-tint": "true"},
282− summary: "Theatre at Ferria Stadium",
283− body: "at Ferria Stadium in Bilbao, Spain\n07578545317",
284− icon: "",
285− secondaryIcon: "",
286− actions: [{ id: "ok_id", label: "Ok"},
287− { id: "snooze_id", label: "Snooze"},
288− { id: "view_id", label: "View"}],
289− summaryVisible: true,
290− bodyVisible: true,
291− iconVisible: false,
292− centeredIconVisible: false,
293− shaped: false,
294− secondaryIconVisible: false,
295− buttonRowVisible: false,
296− buttonTinted: true,
297− hasSound: false,
298− valueVisible: false,
299− valueLabelVisible: false,
300− valueTinted: false
301− },
302381 {
303382 tag: "Ephemeral notification - icon-summary layout",
304− type: Notification.Ephemeral,
305− hints: {},
306− summary: "Photo upload completed",
307− body: "",
308− icon: "../graphics/applicationIcons/facebook.png",
309− secondaryIcon: "",
310− actions: [],
383+ n: nlist[0],
311384 summaryVisible: true,
312385 bodyVisible: false,
313386 iconVisible: true,
@@ -323,15 +396,7 @@ Item {
323396 },
324397 {
325398 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
326− type: Notification.Ephemeral,
327− hints: {"x-canonical-private-affirmative-tint": "false",
328− "sound-file": "dummy.ogg",
329− "suppress-sound": "true"},
330− summary: "New comment successfully published",
331− body: "",
332− icon: "",
333− secondaryIcon: "../graphics/applicationIcons/facebook.png",
334− actions: [],
399+ n: nlist[1],
335400 summaryVisible: true,
336401 bodyVisible: false,
337402 interactiveAreaEnabled: false,
@@ -348,14 +413,7 @@ Item {
348413 },
349414 {
350415 tag: "Interactive notification",
351− type: Notification.Interactive,
352− hints: {"x-canonical-private-affirmative-tint": "false",
353− "sound-file": "dummy.ogg"},
354− summary: "Interactive notification",
355− body: "This is a notification that can be clicked",
356− icon: "../graphics/avatars/amanda.png",
357− secondaryIcon: "",
358− actions: [{ id: "reply_id", label: "Dummy"}],
416+ n: nlist[2],
359417 summaryVisible: true,
360418 bodyVisible: true,
361419 iconVisible: true,
@@ -371,15 +429,7 @@ Item {
371429 },
372430 {
373431 tag: "Snap Decision without secondary icon and no button-tint",
374− type: Notification.SnapDecision,
375− hints: {"x-canonical-private-affirmative-tint": "false",
376− "sound-file": "dummy.ogg"},
377− summary: "Bro Coly",
378− body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
379− icon: "../graphics/avatars/anna_olsson.png",
380− secondaryIcon: "",
381− actions: [{ id: "accept_id", label: "Accept"},
382− { id: "reject_id", label: "Reject"}],
432+ n: nlist[3],
383433 summaryVisible: true,
384434 bodyVisible: true,
385435 iconVisible: true,
@@ -395,14 +445,7 @@ Item {
395445 },
396446 {
397447 tag: "Ephemeral notification",
398− type: Notification.Ephemeral,
399− hints: {"x-canonical-private-affirmative-tint": "false",
400− "sound-file": "dummy.ogg"},
401− summary: "Cole Raby",
402− body: "I did not expect it to be that late.",
403− icon: "../graphics/avatars/funky.png",
404− secondaryIcon: "../graphics/applicationIcons/facebook.png",
405− actions: [],
448+ n: nlist[4],
406449 summaryVisible: true,
407450 bodyVisible: true,
408451 iconVisible: true,
@@ -418,14 +461,7 @@ Item {
418461 },
419462 {
420463 tag: "Ephemeral notification with non-shaped icon",
421− type: Notification.Ephemeral,
422− hints: {"x-canonical-private-affirmative-tint": "false",
423− "x-canonical-non-shaped-icon": "true"},
424− summary: "Contacts",
425− body: "Synchronised contacts-database with cloud-storage.",
426− icon: "image://theme/contacts-app",
427− secondaryIcon: "",
428− actions: [],
464+ n: nlist[5],
429465 summaryVisible: true,
430466 bodyVisible: true,
431467 iconVisible: true,
@@ -441,14 +477,7 @@ Item {
441477 },
442478 {
443479 tag: "Confirmation notification with value",
444− type: Notification.Confirmation,
445− hints: {"x-canonical-non-shaped-icon": "true"},
446− summary: "",
447− body: "",
448− icon: "image://theme/audio-volume-medium",
449− secondaryIcon: "",
450− value: 50,
451− actions: [],
480+ n: nlist[6],
452481 summaryVisible: false,
453482 bodyVisible: false,
454483 iconVisible: false,
@@ -464,15 +493,7 @@ Item {
464493 },
465494 {
466495 tag: "Confirmation notification with value, label and tint",
467− type: Notification.Confirmation,
468− hints: {"x-canonical-non-shaped-icon": "true",
469− "x-canonical-value-bar-tint" : "true"},
470− summary: "",
471− body: "High Volume",
472− icon: "image://theme/audio-volume-high",
473− secondaryIcon: "",
474− value: 85,
475− actions: [],
496+ n: nlist[7],
476497 summaryVisible: false,
477498 bodyVisible: false,
478499 iconVisible: false,
@@ -485,6 +506,22 @@ Item {
485506 valueVisible: true,
486507 valueLabelVisible: true,
487508 valueTinted: true
509+ },
510+ {
511+ tag: "2-over-1 Snap Decision with button-tint",
512+ n: nlist[8],
513+ summaryVisible: true,
514+ bodyVisible: true,
515+ iconVisible: false,
516+ centeredIconVisible: false,
517+ shaped: false,
518+ secondaryIconVisible: false,
519+ buttonRowVisible: false,
520+ buttonTinted: true,
521+ hasSound: false,
522+ valueVisible: false,
523+ valueLabelVisible: false,
524+ valueTinted: false
488525 }
489526 ]
490527 }
@@ -509,8 +546,14 @@ Item {
509546 }
510547
511548 function test_NotificationRenderer(data) {
549+ // make sure the clicks on mocked notifications can be checked against by "actionSpy" (mimicking the NotificationServer component)
550+ data.n.actionInvoked.connect(mockModel.actionInvoked)
551+
552+ // hook up notification's completed-signal with model's onCompleted-slot, so that remove() (model) happens on close() (notification)
553+ data.n.completed.connect(mockModel.onCompleted)
554+
512555 // populate model with some mock notifications
513− mockModel.append(data)
556+ mockModel.append(data.n)
514557
515558 // make sure the view is properly updated before going on
516559 notifications.forceLayout();
@@ -548,9 +591,9 @@ Item {
548591
549592 // test input does not fall through
550593 mouseClick(notification)
551− if(data.type == Notification.Interactive) {
594+ if(data.n.type === Notification.Interactive) {
552595 actionSpy.wait()
553− compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
596+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(0, ActionModel.RoleActionId), "got wrong id for interactive action")
554597 }
555598 compare(clickThroughSpy.count, 0, "click on notification fell through")
556599
@@ -559,17 +602,19 @@ Item {
559602 compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect")
560603 compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect")
561604
562− var audioItem = findInvisibleChild(notification, "sound")
563− compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state")
605+ if (data.hasSound) {
606+ var audioItem = findInvisibleChild(notification, "sound")
607+ compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state")
608+ }
564609
565610 if(data.buttonRowVisible) {
566611 var buttonCancel = findChild(buttonRow, "notify_button1")
567612 var buttonAccept = findChild(buttonRow, "notify_button0")
568613
569614 // only test the left/cancel-button if two actions have been passed in
570− if (data.actions.length == 2) {
615+ if (data.n.actions.count === 2) {
571616 tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
572− compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
617+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action")
573618 actionSpy.clear()
574619 }
575620
@@ -578,36 +623,49 @@ Item {
578623
579624 // click the positive/right button
580625 tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
581− compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
626+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(0, ActionModel.RoleActionId), "got wrong id positive action")
582627 actionSpy.clear()
583− waitForRendering (notification)
584628
585629 // check if there's a ComboButton created due to more actions being passed
586− if (data.actions.length > 2) {
630+ if (data.n.actions.count > 3) {
587631 var comboButton = findChild(notification, "notify_button2")
588− tryCompareFunction(function() { return comboButton.expanded == false; }, true);
632+ tryCompareFunction(function() { return comboButton.expanded === false; }, true);
589633
590634 // click to expand
591− tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == true; }, true);
635+ tryCompareFunction(function() { mouseClick(comboButton, comboButton.width / 2, comboButton.height / 2); return comboButton.expanded === true; }, true);
592636
593637 // try clicking on choices in expanded comboList
594638 var choiceButton1 = findChild(notification, "notify_button3")
595639 tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
596− compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1")
640+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(3, ActionModel.RoleActionId), "got wrong id choice action 1")
597641 actionSpy.clear()
598642
599643 var choiceButton2 = findChild(notification, "notify_button4")
600644 tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
601− compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2")
645+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(4, ActionModel.RoleActionId), "got wrong id choice action 2")
602646 actionSpy.clear()
603647
604648 // click to collapse
605− //tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == false; }, true);
649+ tryCompareFunction(function() { mouseClick(comboButton, comboButton.width / 2, comboButton.height / 2); return comboButton.expanded == false; }, true);
606650 } else {
607651 mouseClick(buttonCancel)
608− compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
652+ compare(actionSpy.signalArguments[0][0], data.n.actions.data(1, ActionModel.RoleActionId), "got wrong id for negative action")
609653 }
610654 }
655+
656+ // swipe-to-dismiss check
657+ waitForRendering(notification)
658+ var before = mockModel.count
659+ var dragStart = notification.width * 0.25;
660+ var dragEnd = notification.width;
661+ var dragY = notification.height / 2;
662+ touchFlick(notification, dragStart, dragY, dragEnd, dragY)
663+ waitForRendering(notification)
664+ if ((data.n.type === Notification.SnapDecision && notification.state === "expanded") || data.n.type === Notification.Confirmation) {
665+ tryCompare(mockModel, "count", before)
666+ } else {
667+ tryCompare(mockModel, "count", before - 1)
668+ }
611669 }
612670 }
613671 }