@@ -1,17 +1,20 @@
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright 2015 Canonical Ltd.
4 * This program is free software; you can redistribute it and/or modify
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
5+ * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * 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.
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
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ * Mirco Mueller <mirco.mueller@canonical.com>
17import QtQuick 2.0
20import QtQuick 2.0
@@ -24,146 +27,134 @@ import Unity.Notifications 1.0
24import QtMultimedia 5.0
27import QtMultimedia 5.0
27 width: notificationsRect.width + interactiveControls.width
32 width: notificationsRect.width + interactiveControls.width
28 height: notificationsRect.height
33 height: notificationsRect.height
34+ property int index: 0
31 id: rootRow
37 id: rootRow
33− Component {
39+ NotificationModel {
37− function invokeAction(actionId) {
38− mockModel.actionInvoked(actionId)
44 id: mockModel
40 id: mockModel
47− signal actionInvoked(string actionId)
49− function getRaw(id) {
50− return mockNotification.createObject(mockModel)
53 // add the default/PlaceHolder notification to the model
42 // add the default/PlaceHolder notification to the model
54 Component.onCompleted: {
43 Component.onCompleted: {
55− var n = {
44+ var component = Qt.createComponent("Notification.qml")
45+ var n = component.createObject("notification", {"nid": index++,
56− type: Notification.PlaceHolder,
46+ "type": Notification.PlaceHolder,
57− hints: {},
47+ "hints": {},
58− summary: "",
48+ "summary": "",
59− body: "",
49+ "body": "",
60− icon: "",
50+ "icon": "",
61− secondaryIcon: "",
51+ "secondaryIcon": "",
62− actions: []
52+ "rawActions": []})
63− }
53+ n.completed.connect(mockModel.onCompleted)
69 function add2over1SnapDecisionNotification() {
58 function add2over1SnapDecisionNotification() {
70− var n = {
59+ var component = Qt.createComponent("Notification.qml")
60+ var n = component.createObject("notification", {"nid": index++,
71− type: Notification.SnapDecision,
61+ "type": Notification.SnapDecision,
72− hints: {"x-canonical-private-affirmative-tint": "true"},
62+ "hints": {"x-canonical-private-affirmative-tint": "true"},
73− summary: "Theatre at Ferria Stadium",
63+ "summary": "Theatre at Ferria Stadium",
74− body: "at Ferria Stadium in Bilbao, Spain\n07578545317",
64+ "body": "at Ferria Stadium in Bilbao, Spain\n07578545317",
75− icon: "",
65+ "icon": "",
76− secondaryIcon: "",
66+ "secondaryIcon": "",
77− actions: [{ id: "ok_id", label: "Ok"},
67+ "rawActions": ["ok_id", "Ok",
78− { id: "snooze_id", label: "Snooze"},
68+ "snooze_id", "Snooze",
79− { id: "view_id", label: "View"}]
69+ "view_id", "View"]})
80− }
70+ n.completed.connect(mockModel.onCompleted)
82 mockModel.append(n)
71 mockModel.append(n)
85 function addEphemeralNotification() {
74 function addEphemeralNotification() {
86− var n = {
75+ var component = Qt.createComponent("Notification.qml")
76+ var n = component.createObject("notification", {"nid": index++,
87− type: Notification.Ephemeral,
77+ "type": Notification.Ephemeral,
88− summary: "Cole Raby",
79+ "summary": "Cole Raby",
89− body: "I did not expect it to be that late.",
80+ "body": "I did not expect it to be that late.",
90− icon: "../graphics/avatars/amanda.png",
81+ "icon": "../graphics/avatars/amanda.png",
91− secondaryIcon: "../graphics/applicationIcons/facebook.png",
82+ "secondaryIcon": "../graphics/applicationIcons/facebook.png",
92− actions: []
83+ "rawActions": ["reply_id", "Dummy"]})
93− }
84+ n.completed.connect(mockModel.onCompleted)
95 mockModel.append(n)
85 mockModel.append(n)
98 function addEphemeralNonShapedIconNotification() {
88 function addEphemeralNonShapedIconNotification() {
99− var n = {
89+ var component = Qt.createComponent("Notification.qml")
90+ var n = component.createObject("notification", {"nid": index++,
100− type: Notification.Ephemeral,
91+ "type": Notification.Ephemeral,
101− hints: {"x-canonical-non-shaped-icon": "true"},
92+ "hints": {"x-canonical-non-shaped-icon": "true"},
102− summary: "Contacts",
93+ "summary": "Contacts",
103− body: "Synchronised contacts-database with cloud-storage.",
94+ "body": "Synchronised contacts-database with cloud-storage.",
104− icon: "../graphics/applicationIcons/contacts-app.png",
95+ "icon": "../graphics/applicationIcons/contacts-app.png",
105− secondaryIcon: "",
96+ "secondaryIcon": "",
106− actions: []
97+ "rawActions": ["reply_id", "Dummy"]})
107− }
98+ n.completed.connect(mockModel.onCompleted)
109 mockModel.append(n)
99 mockModel.append(n)
112 function addEphemeralIconSummaryNotification() {
102 function addEphemeralIconSummaryNotification() {
113− var n = {
103+ var component = Qt.createComponent("Notification.qml")
104+ var n = component.createObject("notification", {"nid": index++,
114− type: Notification.Ephemeral,
105+ "type": Notification.Ephemeral,
115− hints: {"x-canonical-non-shaped-icon": "false"},
106+ "hints": {"x-canonical-non-shaped-icon": "false"},
116− summary: "Photo upload completed",
107+ "summary": "Photo upload completed",
117− body: "",
108+ "body": "",
118− icon: "../graphics/applicationIcons/facebook.png",
109+ "icon": "../graphics/applicationIcons/facebook.png",
119− secondaryIcon: "",
110+ "secondaryIcon": "",
120− actions: []
111+ "rawActions": ["reply_id", "Dummy"]})
121− }
112+ n.completed.connect(mockModel.onCompleted)
123 mockModel.append(n)
113 mockModel.append(n)
126 function addInteractiveNotification() {
116 function addInteractiveNotification() {
127− var n = {
117+ var component = Qt.createComponent("Notification.qml")
118+ var n = component.createObject("notification", {"nid": index++,
128− type: Notification.Interactive,
119+ "type": Notification.Interactive,
129− summary: "Interactive notification",
121+ "summary": "Interactive notification",
130− body: "This is a notification that can be clicked",
122+ "body": "This is a notification that can be clicked",
131− icon: "../graphics/avatars/anna_olsson.png",
123+ "icon": "../graphics/avatars/anna_olsson.png",
132− secondaryIcon: "",
124+ "secondaryIcon": "",
133− actions: [{ id: "reply_id", label: "Dummy"}],
125+ "rawActions": ["reply_id", "Dummy"]})
134− }
126+ n.completed.connect(mockModel.onCompleted)
136 mockModel.append(n)
127 mockModel.append(n)
139 function addConfirmationNotification() {
130 function addConfirmationNotification() {
140− var n = {
131+ var component = Qt.createComponent("Notification.qml")
132+ var n = component.createObject("notification", {"nid": index++,
141− type: Notification.Confirmation,
133+ "type": Notification.Confirmation,
142− hints: {"x-canonical-non-shaped-icon": "true"},
134+ "hints": {"x-canonical-non-shaped-icon": "true"},
143− summary: "Confirmation notification",
135+ "summary": "Confirmation notification",
144− body: "",
136+ "body": "",
145− icon: "image://theme/audio-volume-medium",
137+ "icon": "image://theme/audio-volume-medium",
146− secondaryIcon: "",
138+ "secondaryIcon": "",
147− value: 50,
139+ "value": 50,
148− actions: [],
140+ "rawActions": ["reply_id", "Dummy"]})
149− }
141+ n.completed.connect(mockModel.onCompleted)
151 mockModel.append(n)
142 mockModel.append(n)
154 function add2ndConfirmationNotification() {
145 function add2ndConfirmationNotification() {
155− var n = {
146+ var component = Qt.createComponent("Notification.qml")
147+ var n = component.createObject("notification", {"nid": index++,
156− type: Notification.Confirmation,
148+ "type": Notification.Confirmation,
157− hints: {"x-canonical-non-shaped-icon": "true",
149+ "hints": {"x-canonical-non-shaped-icon": "true",
158− "x-canonical-value-bar-tint": "true"},
150+ "x-canonical-value-bar-tint": "true"},
159− summary: "Confirmation notification",
151+ "summary": "Confirmation notification",
160− body: "High Volume",
152+ "body": "High Volume",
161− icon: "image://theme/audio-volume-high",
153+ "icon": "image://theme/audio-volume-high",
162− secondaryIcon: "",
154+ "secondaryIcon": "",
163− value: 85,
155+ "value": 85,
164− actions: [],
156+ "rawActions": ["reply_id", "Dummy"]})
165− }
157+ n.completed.connect(mockModel.onCompleted)
167 mockModel.append(n)
158 mockModel.append(n)
@@ -174,8 +165,9 @@ Item {
176 function remove1stNotification() {
167 function remove1stNotification() {
177− if (mockModel.count > 1)
168+ if (mockModel.count > 1) {
178− mockModel.remove(1)
169+ mockModel.removeSecond()
181 Rectangle {
173 Rectangle {
@@ -273,41 +265,122 @@ Item {
273 name: "NotificationRendererTest"
265 name: "NotificationRendererTest"
274 when: windowShown
266 when: windowShown
268+ property list<Notification> nlist: [
271+ type: Notification.Ephemeral
272+ summary: "Photo upload completed"
274+ icon: "../graphics/applicationIcons/facebook.png"
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"
288+ secondaryIcon: "../graphics/applicationIcons/facebook.png"
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"
302+ rawActions: ["reply_id", "Dummy"]
306+ type: Notification.SnapDecision
307+ hints: {"x-canonical-private-affirmative-tint": "false",
308+ "sound-file": "dummy.ogg"}
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"
314+ rawActions: ["accept_id", "Accept",
315+ "reject_id", "Reject"]
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"
331+ type: Notification.Ephemeral
332+ hints: {"x-canonical-private-affirmative-tint": "false",
333+ "x-canonical-non-shaped-icon": "true"}
335+ body: "Synchronised contacts-database with cloud-storage."
336+ icon: "image://theme/contacts-app"
343+ type: Notification.Confirmation
344+ hints: {"x-canonical-non-shaped-icon": "true"}
347+ icon: "image://theme/audio-volume-medium"
354+ type: Notification.Confirmation
355+ hints: {"x-canonical-non-shaped-icon": "true",
356+ "x-canonical-value-bar-tint" : "true"}
359+ icon: "image://theme/audio-volume-high"
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"
373+ rawActions: ["ok_id", "Ok",
374+ "snooze_id", "Snooze",
276 function test_NotificationRenderer_data() {
379 function test_NotificationRenderer_data() {
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",
286− actions: [{ id: "ok_id", label: "Ok"},
287− { id: "snooze_id", label: "Snooze"},
288− { id: "view_id", label: "View"}],
289− summaryVisible: true,
292− centeredIconVisible: false,
294− secondaryIconVisible: false,
295− buttonRowVisible: false,
298− valueVisible: false,
299− valueLabelVisible: false,
303 tag: "Ephemeral notification - icon-summary layout",
382 tag: "Ephemeral notification - icon-summary layout",
304− type: Notification.Ephemeral,
383+ n: nlist[0],
306− summary: "Photo upload completed",
308− icon: "../graphics/applicationIcons/facebook.png",
311 summaryVisible: true,
384 summaryVisible: true,
312 bodyVisible: false,
385 bodyVisible: false,
313 iconVisible: true,
386 iconVisible: true,
@@ -323,15 +396,7 @@ Item {
325 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
398 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
326− type: Notification.Ephemeral,
399+ n: nlist[1],
327− hints: {"x-canonical-private-affirmative-tint": "false",
328− "sound-file": "dummy.ogg",
329− "suppress-sound": "true"},
330− summary: "New comment successfully published",
333− secondaryIcon: "../graphics/applicationIcons/facebook.png",
335 summaryVisible: true,
400 summaryVisible: true,
336 bodyVisible: false,
401 bodyVisible: false,
337 interactiveAreaEnabled: false,
402 interactiveAreaEnabled: false,
@@ -348,14 +413,7 @@ Item {
350 tag: "Interactive notification",
415 tag: "Interactive notification",
351− type: Notification.Interactive,
416+ n: nlist[2],
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",
358− actions: [{ id: "reply_id", label: "Dummy"}],
359 summaryVisible: true,
417 summaryVisible: true,
360 bodyVisible: true,
418 bodyVisible: true,
361 iconVisible: true,
419 iconVisible: true,
@@ -371,15 +429,7 @@ Item {
373 tag: "Snap Decision without secondary icon and no button-tint",
431 tag: "Snap Decision without secondary icon and no button-tint",
374− type: Notification.SnapDecision,
432+ n: nlist[3],
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",
381− actions: [{ id: "accept_id", label: "Accept"},
382− { id: "reject_id", label: "Reject"}],
383 summaryVisible: true,
433 summaryVisible: true,
384 bodyVisible: true,
434 bodyVisible: true,
385 iconVisible: true,
435 iconVisible: true,
@@ -395,14 +445,7 @@ Item {
397 tag: "Ephemeral notification",
447 tag: "Ephemeral notification",
398− type: Notification.Ephemeral,
448+ n: nlist[4],
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",
406 summaryVisible: true,
449 summaryVisible: true,
407 bodyVisible: true,
450 bodyVisible: true,
408 iconVisible: true,
451 iconVisible: true,
@@ -418,14 +461,7 @@ Item {
420 tag: "Ephemeral notification with non-shaped icon",
463 tag: "Ephemeral notification with non-shaped icon",
421− type: Notification.Ephemeral,
464+ n: nlist[5],
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",
429 summaryVisible: true,
465 summaryVisible: true,
430 bodyVisible: true,
466 bodyVisible: true,
431 iconVisible: true,
467 iconVisible: true,
@@ -441,14 +477,7 @@ Item {
443 tag: "Confirmation notification with value",
479 tag: "Confirmation notification with value",
444− type: Notification.Confirmation,
480+ n: nlist[6],
445− hints: {"x-canonical-non-shaped-icon": "true"},
448− icon: "image://theme/audio-volume-medium",
452 summaryVisible: false,
481 summaryVisible: false,
453 bodyVisible: false,
482 bodyVisible: false,
454 iconVisible: false,
483 iconVisible: false,
@@ -464,15 +493,7 @@ Item {
466 tag: "Confirmation notification with value, label and tint",
495 tag: "Confirmation notification with value, label and tint",
467− type: Notification.Confirmation,
496+ n: nlist[7],
468− hints: {"x-canonical-non-shaped-icon": "true",
469− "x-canonical-value-bar-tint" : "true"},
471− body: "High Volume",
472− icon: "image://theme/audio-volume-high",
476 summaryVisible: false,
497 summaryVisible: false,
477 bodyVisible: false,
498 bodyVisible: false,
478 iconVisible: false,
499 iconVisible: false,
@@ -485,6 +506,22 @@ Item {
485 valueVisible: true,
506 valueVisible: true,
486 valueLabelVisible: true,
507 valueLabelVisible: true,
487 valueTinted: true
508 valueTinted: true
511+ tag: "2-over-1 Snap Decision with button-tint",
513+ summaryVisible: true,
516+ centeredIconVisible: false,
518+ secondaryIconVisible: false,
519+ buttonRowVisible: false,
522+ valueVisible: false,
523+ valueLabelVisible: false,
@@ -509,8 +546,14 @@ Item {
511 function test_NotificationRenderer(data) {
548 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)
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)
512 // populate model with some mock notifications
555 // populate model with some mock notifications
513− mockModel.append(data)
556+ mockModel.append(data.n)
515 // make sure the view is properly updated before going on
558 // make sure the view is properly updated before going on
516 notifications.forceLayout();
559 notifications.forceLayout();
@@ -548,9 +591,9 @@ Item {
549 // test input does not fall through
592 // test input does not fall through
550 mouseClick(notification)
593 mouseClick(notification)
551− if(data.type == Notification.Interactive) {
594+ if(data.n.type === Notification.Interactive) {
552 actionSpy.wait()
595 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")
555 compare(clickThroughSpy.count, 0, "click on notification fell through")
598 compare(clickThroughSpy.count, 0, "click on notification fell through")
@@ -559,17 +602,19 @@ Item {
559 compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect")
602 compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect")
560 compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect")
603 compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect")
605+ if (data.hasSound) {
562− var audioItem = findInvisibleChild(notification, "sound")
606+ var audioItem = findInvisibleChild(notification, "sound")
563− compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state")
607+ compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state")
565 if(data.buttonRowVisible) {
610 if(data.buttonRowVisible) {
566 var buttonCancel = findChild(buttonRow, "notify_button1")
611 var buttonCancel = findChild(buttonRow, "notify_button1")
567 var buttonAccept = findChild(buttonRow, "notify_button0")
612 var buttonAccept = findChild(buttonRow, "notify_button0")
569 // only test the left/cancel-button if two actions have been passed in
614 // 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) {
571 tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
616 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")
573 actionSpy.clear()
618 actionSpy.clear()
@@ -578,36 +623,49 @@ Item {
579 // click the positive/right button
624 // click the positive/right button
580 tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
625 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")
582 actionSpy.clear()
627 actionSpy.clear()
583− waitForRendering (notification)
585 // check if there's a ComboButton created due to more actions being passed
629 // 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) {
587 var comboButton = findChild(notification, "notify_button2")
631 var comboButton = findChild(notification, "notify_button2")
588− tryCompareFunction(function() { return comboButton.expanded == false; }, true);
632+ tryCompareFunction(function() { return comboButton.expanded === false; }, true);
590 // click to expand
634 // 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);
593 // try clicking on choices in expanded comboList
637 // try clicking on choices in expanded comboList
594 var choiceButton1 = findChild(notification, "notify_button3")
638 var choiceButton1 = findChild(notification, "notify_button3")
595 tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
639 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")
597 actionSpy.clear()
641 actionSpy.clear()
599 var choiceButton2 = findChild(notification, "notify_button4")
643 var choiceButton2 = findChild(notification, "notify_button4")
600 tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
644 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")
602 actionSpy.clear()
646 actionSpy.clear()
604 // click to collapse
648 // 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);
607 mouseClick(buttonCancel)
651 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")
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)
667+ tryCompare(mockModel, "count", before - 1)