Merge lp:~macslow/unity8/swipe-to-act-fix-1358343 into lp:unity8
- swipe-to-act-fix-1358343
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Albert Astals Cid |
Approved revision: | 1317 |
Merged at revision: | 1412 |
Proposed branch: | lp:~macslow/unity8/swipe-to-act-fix-1358343 |
Merge into: | lp:unity8 |
Diff against target: |
2297 lines (+1471/-666) 15 files modified
qml/Notifications/Notification.qml (+22/-3) qml/Notifications/SwipeToAct.qml (+309/-0) tests/autopilot/unity8/shell/tests/test_notifications.py (+0/-51) tests/mocks/Unity/Notifications/CMakeLists.txt (+15/-1) tests/mocks/Unity/Notifications/MockActionModel.cpp (+72/-0) tests/mocks/Unity/Notifications/MockActionModel.h (+51/-0) tests/mocks/Unity/Notifications/MockNotificationTypes.cpp (+26/-0) tests/mocks/Unity/Notifications/MockNotificationTypes.h (+36/-0) tests/mocks/Unity/Notifications/notification.js (+0/-23) tests/mocks/Unity/Notifications/plugin.cpp (+31/-0) tests/mocks/Unity/Notifications/plugin.h (+35/-0) tests/mocks/Unity/Notifications/qmldir (+2/-1) tests/qmltests/CMakeLists.txt (+1/-0) tests/qmltests/Notifications/tst_Notifications.qml (+595/-587) tests/qmltests/Notifications/tst_SwipeToAct.qml (+276/-0) |
To merge this branch: | bzr merge lp:~macslow/unity8/swipe-to-act-fix-1358343 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Albert Astals Cid (community) | Approve | ||
Josh Arenson | Approve | ||
Review via email: mp+236091@code.launchpad.net |
Commit message
Added dedicated swipe-to-act button for snap-decisions, which avoids accidental taps/button-
Description of the change
Added dedicated swipe-to-act button for snap-decisions, which avoids accidental taps/button-
You can test it with the examples/
For the reviewers convenience, here's a video of all two branches in action: http://
* Are there any related MPs required for this MP to build/function as expected? Please list.
Yes. For correct operation lp:~macslow/unity-notifications/swipe-to-act-fix-1358343 needs to be merged to lp:unity-notifications first. Due to changes in trunk lp:~aacid/unity8/multimediaMocks is also needed now.
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes.
* Did you make sure that your branch does not contain spurious tags?
Yes.
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Not applicable.
* If you changed the UI, has there been a design review?
Yes.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1307
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1308
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1309
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Albert Astals Cid (aacid) wrote : | # |
Please use Loaders so that either SwipeToAct or the Buttons are created but not both, will save us CPU time and make showing the notification faster since less things need to be created.
Albert Astals Cid (aacid) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass?
Let's let it run again after the last bunch of changes
* Did you make sure that the branch does not contain spurious tags?
Yes
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1311
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1315
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Josh Arenson (josharenson) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass?
No, the usual AP failures.
* Did you make sure that the branch does not contain spurious tags?
Yes
While I was fairly sure it wouldn't have an effect, I tested this branch with https:/
Albert Astals Cid (aacid) wrote : | # |
Text conflict in tests/qmltests/
1 conflicts encountered.
Reminder: Was already top approved, should be again after merge is fixed.
- 1316. By Mirco Müller
-
Merged with trunk... resolved conflicts.
- 1317. By Mirco Müller
-
Adapted the SwipeToAct qml-test too after the merge with trunk.
Albert Astals Cid (aacid) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1317
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'qml/Notifications/Notification.qml' |
2 | --- qml/Notifications/Notification.qml 2014-10-30 21:42:32 +0000 |
3 | +++ qml/Notifications/Notification.qml 2014-10-31 10:46:25 +0000 |
4 | @@ -398,7 +398,7 @@ |
5 | |
6 | spacing: contentSpacing |
7 | |
8 | - visible: notification.type == Notification.SnapDecision && oneOverTwoRepeaterTop.count == 3 |
9 | + visible: notification.type === Notification.SnapDecision && oneOverTwoRepeaterTop.count === 3 |
10 | |
11 | Repeater { |
12 | id: oneOverTwoRepeaterTop |
13 | @@ -468,22 +468,41 @@ |
14 | spacing: units.gu(2) |
15 | layoutDirection: Qt.RightToLeft |
16 | |
17 | + Loader { |
18 | + id: notifySwipeButtonLoader |
19 | + active: notification.hints["x-canonical-snap-decisions-swipe"] === "true" |
20 | + |
21 | + sourceComponent: SwipeToAct { |
22 | + objectName: "notify_swipe_button" |
23 | + width: buttonRow.width |
24 | + leftIconName: "call-end" |
25 | + rightIconName: "call-start" |
26 | + onLeftTriggered: { |
27 | + notification.notification.invokeAction(notification.actions.data(0, ActionModel.RoleActionId)) |
28 | + } |
29 | + |
30 | + onRightTriggered: { |
31 | + notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId)) |
32 | + } |
33 | + } |
34 | + } |
35 | + |
36 | Repeater { |
37 | id: actionRepeater |
38 | - |
39 | model: notification.actions |
40 | delegate: Loader { |
41 | id: loader |
42 | |
43 | property string actionId: id |
44 | property string actionLabel: label |
45 | + active: !notifySwipeButtonLoader.active |
46 | |
47 | Component { |
48 | id: actionButton |
49 | |
50 | Button { |
51 | objectName: "notify_button" + index |
52 | - width: buttonRow.width / 2 - spacing*2 |
53 | + width: buttonRow.width / 2 - spacing * 2 |
54 | text: loader.actionLabel |
55 | color: { |
56 | var result = sdDarkGrey; |
57 | |
58 | === added file 'qml/Notifications/SwipeToAct.qml' |
59 | --- qml/Notifications/SwipeToAct.qml 1970-01-01 00:00:00 +0000 |
60 | +++ qml/Notifications/SwipeToAct.qml 2014-10-31 10:46:25 +0000 |
61 | @@ -0,0 +1,309 @@ |
62 | +/* |
63 | + * Copyright (C) 2014 Canonical, Ltd. |
64 | + * |
65 | + * This program is free software; you can redistribute it and/or modify |
66 | + * it under the terms of the GNU General Public License as published by |
67 | + * the Free Software Foundation; version 3. |
68 | + * |
69 | + * This program is distributed in the hope that it will be useful, |
70 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
71 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
72 | + * GNU General Public License for more details. |
73 | + * |
74 | + * You should have received a copy of the GNU General Public License |
75 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
76 | + */ |
77 | + |
78 | +import QtQuick 2.3 |
79 | +import Ubuntu.Components 1.1 |
80 | +import QtGraphicalEffects 1.0 |
81 | + |
82 | +Item { |
83 | + id: swipeToAct |
84 | + |
85 | + width: parent.width |
86 | + height: childrenRect.height |
87 | + |
88 | + signal leftTriggered() |
89 | + signal rightTriggered() |
90 | + |
91 | + property string leftIconName |
92 | + property string rightIconName |
93 | + readonly property double sliderHeight: units.gu(6) |
94 | + readonly property double gap: units.gu(1) |
95 | + readonly property double halfWay: mouseArea.drag.maximumX / 2 |
96 | + |
97 | + Rectangle { |
98 | + id: gradient |
99 | + width: parent.width * 5 |
100 | + height: sliderHeight |
101 | + visible: false |
102 | + LinearGradient { |
103 | + anchors.fill: parent |
104 | + start: Qt.point(parent.x, parent.y) |
105 | + end: Qt.point(parent.width, parent.y) |
106 | + gradient: Gradient { |
107 | + GradientStop { position: 0.0; color: UbuntuColors.red } |
108 | + GradientStop { position: 0.2; color: UbuntuColors.red } |
109 | + GradientStop { position: 0.4; color: "#dddddd" } |
110 | + GradientStop { position: 0.6; color: "#dddddd" } |
111 | + GradientStop { position: 0.8; color: UbuntuColors.green } |
112 | + GradientStop { position: 1.0; color: UbuntuColors.green } |
113 | + } |
114 | + } |
115 | + } |
116 | + |
117 | + ShaderEffectSource { |
118 | + id: effectSourceGradient |
119 | + sourceItem: gradient |
120 | + width: gradient.width |
121 | + height: gradient.height |
122 | + sourceRect: Qt.rect(0.4 * gradient.width * (slider.x / halfWay), 0, mask.width, mask.height) |
123 | + visible: false |
124 | + hideSource: true |
125 | + } |
126 | + |
127 | + UbuntuShape { |
128 | + id: mask |
129 | + color: "black" |
130 | + width: parent.width |
131 | + height: sliderHeight |
132 | + borderSource: "none" |
133 | + visible: false |
134 | + } |
135 | + |
136 | + ShaderEffectSource { |
137 | + id: effectSourceMask |
138 | + sourceItem: mask |
139 | + width: mask.width |
140 | + height: mask.height |
141 | + visible: false |
142 | + hideSource: true |
143 | + } |
144 | + |
145 | + ShaderEffect { |
146 | + width: parent.width |
147 | + height: sliderHeight |
148 | + property variant mask: effectSourceMask |
149 | + property variant gradient: effectSourceGradient |
150 | + vertexShader: " |
151 | + uniform highp mat4 qt_Matrix; |
152 | + attribute highp vec4 qt_Vertex; |
153 | + attribute highp vec2 qt_MultiTexCoord0; |
154 | + varying highp vec2 coord; |
155 | + void main() { |
156 | + coord = qt_MultiTexCoord0; |
157 | + gl_Position = qt_Matrix * qt_Vertex; |
158 | + }" |
159 | + fragmentShader: " |
160 | + varying highp vec2 coord; |
161 | + uniform sampler2D mask; |
162 | + uniform sampler2D gradient; |
163 | + void main() { |
164 | + lowp vec4 texMask = texture2D(mask, coord); |
165 | + lowp vec4 texGradient = texture2D(gradient, coord); |
166 | + gl_FragColor = texGradient.rgba * texMask.a ; |
167 | + }" |
168 | + |
169 | + Row { |
170 | + id: row |
171 | + anchors.fill: parent |
172 | + spacing: gap |
173 | + anchors.margins: gap |
174 | + |
175 | + UbuntuShape { |
176 | + id: leftShape |
177 | + states: [ |
178 | + State { |
179 | + name: "normal" |
180 | + PropertyChanges { |
181 | + target: leftShape |
182 | + color: UbuntuColors.red |
183 | + } |
184 | + PropertyChanges { |
185 | + target: innerLeftShape |
186 | + color: UbuntuColors.red |
187 | + visible: false |
188 | + } |
189 | + }, |
190 | + State { |
191 | + name: "selected" |
192 | + PropertyChanges { |
193 | + target: leftShape |
194 | + color: "white" |
195 | + } |
196 | + PropertyChanges { |
197 | + target: innerLeftShape |
198 | + color: UbuntuColors.red |
199 | + visible: true |
200 | + } |
201 | + } |
202 | + ] |
203 | + state: "normal" |
204 | + height: units.gu(4) |
205 | + width: units.gu(7) |
206 | + borderSource: "none" |
207 | + opacity: slider.x <= halfWay ? 1.0 : 1.0 - ((slider.x - halfWay) / halfWay) |
208 | + UbuntuShape { |
209 | + id: innerLeftShape |
210 | + anchors.centerIn: parent |
211 | + borderSource: "none" |
212 | + width: parent.width - units.gu(.5) |
213 | + height: parent.height - units.gu(.5) |
214 | + } |
215 | + Icon { |
216 | + anchors.centerIn: parent |
217 | + width: units.gu(2) |
218 | + height: units.gu(2) |
219 | + name: leftIconName |
220 | + color: "white" |
221 | + } |
222 | + } |
223 | + |
224 | + Rectangle { |
225 | + id: leftSpacer |
226 | + width: (row.width - (leftShape.width + slider.width + rightShape.width + 4 * row.spacing)) / 2 |
227 | + height: units.gu(4) |
228 | + opacity: 0 |
229 | + } |
230 | + |
231 | + UbuntuShape { |
232 | + id: slider |
233 | + objectName: "slider" |
234 | + |
235 | + Behavior on x { |
236 | + UbuntuNumberAnimation { |
237 | + duration: UbuntuAnimation.FastDuration |
238 | + easing.type: Easing.OutBounce |
239 | + } |
240 | + } |
241 | + |
242 | + Behavior on opacity { |
243 | + UbuntuNumberAnimation { |
244 | + duration: UbuntuAnimation.FastDuration |
245 | + } |
246 | + } |
247 | + |
248 | + onOpacityChanged: { |
249 | + if (opacity === 0) { |
250 | + if (rightShape.state === "selected") { |
251 | + rightTriggered() |
252 | + } |
253 | + if (leftShape.state === "selected") { |
254 | + leftTriggered() |
255 | + } |
256 | + } |
257 | + } |
258 | + |
259 | + z: 1 |
260 | + color: "white" |
261 | + height: units.gu(4) |
262 | + width: units.gu(7) |
263 | + borderSource: "none" |
264 | + Row { |
265 | + anchors.fill: parent |
266 | + spacing: 2 * gap |
267 | + anchors.leftMargin: units.gu(.5) |
268 | + anchors.rightMargin: units.gu(.5) |
269 | + Icon { |
270 | + anchors.verticalCenter: parent.verticalCenter |
271 | + name: "back" |
272 | + width: units.gu(2) |
273 | + height: units.gu(2) |
274 | + } |
275 | + Icon { |
276 | + anchors.verticalCenter: parent.verticalCenter |
277 | + name: "next" |
278 | + width: units.gu(2) |
279 | + height: units.gu(2) |
280 | + } |
281 | + } |
282 | + } |
283 | + |
284 | + Rectangle { |
285 | + id: rightSpacer |
286 | + width: leftSpacer.width |
287 | + height: units.gu(4) |
288 | + opacity: 0 |
289 | + } |
290 | + |
291 | + UbuntuShape { |
292 | + id: rightShape |
293 | + states: [ |
294 | + State { |
295 | + name: "normal" |
296 | + PropertyChanges { |
297 | + target: rightShape |
298 | + color: UbuntuColors.green |
299 | + } |
300 | + PropertyChanges { |
301 | + target: innerRightShape |
302 | + color: UbuntuColors.green |
303 | + visible: false |
304 | + } |
305 | + }, |
306 | + State { |
307 | + name: "selected" |
308 | + PropertyChanges { |
309 | + target: rightShape |
310 | + color: "white" |
311 | + } |
312 | + PropertyChanges { |
313 | + target: innerRightShape |
314 | + color: UbuntuColors.green |
315 | + visible: true |
316 | + } |
317 | + } |
318 | + ] |
319 | + state: "normal" |
320 | + height: units.gu(4) |
321 | + width: units.gu(7) |
322 | + borderSource: "none" |
323 | + opacity: slider.x >= halfWay ? 1.0 : slider.x / halfWay |
324 | + UbuntuShape { |
325 | + id: innerRightShape |
326 | + anchors.centerIn: parent |
327 | + borderSource: "none" |
328 | + width: parent.width - units.gu(.5) |
329 | + height: parent.height - units.gu(.5) |
330 | + } |
331 | + Icon { |
332 | + anchors.centerIn: parent |
333 | + width: units.gu(2) |
334 | + height: units.gu(2) |
335 | + name: rightIconName |
336 | + color: "white" |
337 | + } |
338 | + } |
339 | + } |
340 | + |
341 | + MouseArea { |
342 | + id: mouseArea |
343 | + objectName: "swipeMouseArea" |
344 | + |
345 | + anchors.fill: row |
346 | + drag.target: slider |
347 | + drag.axis: Drag.XAxis |
348 | + drag.minimumX: 0 |
349 | + drag.maximumX: row.width - slider.width |
350 | + |
351 | + onReleased: { |
352 | + if (slider.x !== drag.minimumX || slider.x !== drag.maximumX) { |
353 | + slider.x = halfWay |
354 | + } |
355 | + if (slider.x === drag.minimumX) { |
356 | + slider.x = drag.minimumX |
357 | + slider.opacity = 0 |
358 | + enabled = false |
359 | + leftShape.state = "selected" |
360 | + } |
361 | + if (slider.x === drag.maximumX) { |
362 | + slider.x = drag.maximumX |
363 | + slider.opacity = 0 |
364 | + enabled = false |
365 | + rightShape.state = "selected" |
366 | + } |
367 | + } |
368 | + } |
369 | + } |
370 | +} |
371 | |
372 | === modified file 'tests/autopilot/unity8/shell/tests/test_notifications.py' |
373 | --- tests/autopilot/unity8/shell/tests/test_notifications.py 2014-10-30 21:43:06 +0000 |
374 | +++ tests/autopilot/unity8/shell/tests/test_notifications.py 2014-10-31 10:46:25 +0000 |
375 | @@ -157,57 +157,6 @@ |
376 | |
377 | self.assert_notification_action_id_was_called('action_id') |
378 | |
379 | - def test_sd_incoming_call(self): |
380 | - """Rejecting a call should make notification expand and |
381 | - offer more options.""" |
382 | - unity_proxy = self.launch_unity() |
383 | - unlock_unity(unity_proxy) |
384 | - |
385 | - summary = "Incoming call" |
386 | - body = "Frank Zappa\n+44 (0)7736 027340" |
387 | - icon_path = self._get_icon_path('avatars/anna_olsson.png') |
388 | - hints = [ |
389 | - ("x-canonical-secondary-icon", "incoming-call"), |
390 | - ("x-canonical-snap-decisions", "true"), |
391 | - ("x-canonical-private-affirmative-tint", "true"), |
392 | - ("x-canonical-private-rejection-tint", "true"), |
393 | - ] |
394 | - |
395 | - actions = [ |
396 | - ('action_accept', 'Hold + Answer'), |
397 | - ('action_decline_1', 'End + Answer'), |
398 | - ('action_decline_2', 'Decline'), |
399 | - ('action_decline_3', 'message:I missed your call - can you call me now?'), |
400 | - ('action_decline_4', 'message:I\'m running late. I\'m on my way.'), |
401 | - ('action_decline_5', 'message:I\'m busy at the moment. I\'ll call later.'), |
402 | - ('action_decline_6', 'edit:Custom'), |
403 | - ] |
404 | - |
405 | - self._create_interactive_notification( |
406 | - summary, |
407 | - body, |
408 | - icon_path, |
409 | - "NORMAL", |
410 | - actions, |
411 | - hints |
412 | - ) |
413 | - |
414 | - notify_list = self._get_notifications_list() |
415 | - get_notification = lambda: notify_list.wait_select_single( |
416 | - 'Notification', objectName='notification1') |
417 | - notification = get_notification() |
418 | - self._assert_notification(notification, summary, body, True, True, 1.0) |
419 | - notification.pointing_device.click_object( |
420 | - notification.select_single(objectName="combobutton_dropdown")) |
421 | - self.assertThat( |
422 | - notification.select_single(objectName="notify_button2").expanded, |
423 | - Eventually(Equals(True))) |
424 | - time.sleep(2) |
425 | - notification.pointing_device.click_object( |
426 | - notification.select_single(objectName="notify_button4")) |
427 | - self.assert_notification_action_id_was_called("action_decline_4") |
428 | - |
429 | - |
430 | def test_sd_one_over_two_layout(self): |
431 | """Snap-decision with three actions should use one-over two button layout.""" |
432 | unity_proxy = self.launch_unity() |
433 | |
434 | === modified file 'tests/mocks/Unity/Notifications/CMakeLists.txt' |
435 | --- tests/mocks/Unity/Notifications/CMakeLists.txt 2014-05-02 23:27:02 +0000 |
436 | +++ tests/mocks/Unity/Notifications/CMakeLists.txt 2014-10-31 10:46:25 +0000 |
437 | @@ -1,1 +1,15 @@ |
438 | -add_unity8_mock(Unity.Notifications 1.0 Unity/Notifications) |
439 | +include_directories( |
440 | + ${CMAKE_CURRENT_SOURCE_DIR} |
441 | +) |
442 | + |
443 | +set(MockNotificationsPlugin_SOURCES |
444 | + plugin.cpp |
445 | + MockNotificationTypes.cpp |
446 | + MockActionModel.cpp |
447 | +) |
448 | + |
449 | +add_library(MockNotificationsPlugin MODULE ${MockNotificationsPlugin_SOURCES}) |
450 | + |
451 | +qt5_use_modules(MockNotificationsPlugin Core Quick) |
452 | + |
453 | +add_unity8_mock(Unity.Notifications 1.0 Unity/Notifications TARGETS MockNotificationsPlugin) |
454 | |
455 | === added file 'tests/mocks/Unity/Notifications/MockActionModel.cpp' |
456 | --- tests/mocks/Unity/Notifications/MockActionModel.cpp 1970-01-01 00:00:00 +0000 |
457 | +++ tests/mocks/Unity/Notifications/MockActionModel.cpp 2014-10-31 10:46:25 +0000 |
458 | @@ -0,0 +1,72 @@ |
459 | +/* |
460 | + * Copyright 2014 Canonical Ltd. |
461 | + * |
462 | + * This program is free software; you can redistribute it and/or modify |
463 | + * it under the terms of the GNU Lesser General Public License as published by |
464 | + * the Free Software Foundation; version 3. |
465 | + * |
466 | + * This program is distributed in the hope that it will be useful, |
467 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
468 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
469 | + * GNU Lesser General Public License for more details. |
470 | + * |
471 | + * You should have received a copy of the GNU Lesser General Public License |
472 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
473 | + * |
474 | + * Authors: |
475 | + * Mirco Mueller <mirco.mueller@canonical.com> |
476 | + */ |
477 | + |
478 | +#include "MockActionModel.h" |
479 | + |
480 | +struct ActionModelPrivate { |
481 | + QList<QString> labels; |
482 | + QList<QString> ids; |
483 | +}; |
484 | + |
485 | +ActionModel::ActionModel(QObject *parent) : QStringListModel(parent), p(new ActionModelPrivate) { |
486 | + insertAction("ok_id", "Ok"); |
487 | + insertAction("cancel_id", "Cancel"); |
488 | +} |
489 | + |
490 | +ActionModel::~ActionModel() { |
491 | +} |
492 | + |
493 | +int ActionModel::rowCount(const QModelIndex &index) const { |
494 | + return p->labels.size(); |
495 | +} |
496 | + |
497 | +QVariant ActionModel::data(const QModelIndex &index, int role) const { |
498 | + if (!index.isValid()) |
499 | + return QVariant(); |
500 | + |
501 | + switch(role) { |
502 | + case RoleActionLabel: |
503 | + return QVariant(p->labels[index.row()]); |
504 | + |
505 | + case RoleActionId: |
506 | + return QVariant(p->ids[index.row()]); |
507 | + |
508 | + default: |
509 | + return QVariant(); |
510 | + } |
511 | +} |
512 | + |
513 | +QHash<int, QByteArray> ActionModel::roleNames() const { |
514 | + QHash<int, QByteArray> roles; |
515 | + |
516 | + roles.insert(RoleActionLabel, "label"); |
517 | + roles.insert(RoleActionId, "id"); |
518 | + |
519 | + return roles; |
520 | +} |
521 | + |
522 | +Q_INVOKABLE QVariant ActionModel::data(int row, int role) const |
523 | +{ |
524 | + return data(index(row, 0), role); |
525 | +} |
526 | + |
527 | +void ActionModel::insertAction(const QString &id, const QString &label) { |
528 | + p->ids.push_back(id); |
529 | + p->labels.push_back(label); |
530 | +} |
531 | |
532 | === added file 'tests/mocks/Unity/Notifications/MockActionModel.h' |
533 | --- tests/mocks/Unity/Notifications/MockActionModel.h 1970-01-01 00:00:00 +0000 |
534 | +++ tests/mocks/Unity/Notifications/MockActionModel.h 2014-10-31 10:46:25 +0000 |
535 | @@ -0,0 +1,51 @@ |
536 | +/* |
537 | + * Copyright 2014 Canonical Ltd. |
538 | + * |
539 | + * This program is free software; you can redistribute it and/or modify |
540 | + * it under the terms of the GNU Lesser General Public License as published by |
541 | + * the Free Software Foundation; version 3. |
542 | + * |
543 | + * This program is distributed in the hope that it will be useful, |
544 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
545 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
546 | + * GNU Lesser General Public License for more details. |
547 | + * |
548 | + * You should have received a copy of the GNU Lesser General Public License |
549 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
550 | + * |
551 | + * Authors: |
552 | + * Mirco Mueller <mirco.mueller@canonical.com> |
553 | + */ |
554 | + |
555 | +#ifndef MOCK_ACTION_MODEL_H |
556 | +#define MOCK_ACTION_MODEL_H |
557 | + |
558 | +#include <QStringListModel> |
559 | + |
560 | +struct ActionModelPrivate; |
561 | + |
562 | +class ActionModel : public QStringListModel { |
563 | + Q_OBJECT |
564 | + |
565 | +public: |
566 | + ActionModel(QObject *parent=nullptr); |
567 | + virtual ~ActionModel(); |
568 | + |
569 | + virtual int rowCount(const QModelIndex &index) const; |
570 | + virtual QVariant data(const QModelIndex &index, int role) const; |
571 | + virtual QHash<int, QByteArray> roleNames() const; |
572 | + |
573 | + Q_ENUMS(ActionsRoles) |
574 | + enum ActionsRoles { |
575 | + RoleActionLabel = Qt::UserRole + 1, |
576 | + RoleActionId = Qt::UserRole + 2 |
577 | + }; |
578 | + Q_INVOKABLE QVariant data(int row, int role) const; |
579 | + |
580 | + void insertAction(const QString &id, const QString &label); |
581 | + |
582 | +private: |
583 | + QScopedPointer<ActionModelPrivate> p; |
584 | +}; |
585 | + |
586 | +#endif // MOCK_ACTION_MODEL_H |
587 | |
588 | === added file 'tests/mocks/Unity/Notifications/MockNotificationTypes.cpp' |
589 | --- tests/mocks/Unity/Notifications/MockNotificationTypes.cpp 1970-01-01 00:00:00 +0000 |
590 | +++ tests/mocks/Unity/Notifications/MockNotificationTypes.cpp 2014-10-31 10:46:25 +0000 |
591 | @@ -0,0 +1,26 @@ |
592 | +/* |
593 | + * Copyright 2014 Canonical Ltd. |
594 | + * |
595 | + * This program is free software; you can redistribute it and/or modify |
596 | + * it under the terms of the GNU Lesser General Public License as published by |
597 | + * the Free Software Foundation; version 3. |
598 | + * |
599 | + * This program is distributed in the hope that it will be useful, |
600 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
601 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
602 | + * GNU Lesser General Public License for more details. |
603 | + * |
604 | + * You should have received a copy of the GNU Lesser General Public License |
605 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
606 | + * |
607 | + * Authors: |
608 | + * Mirco Mueller <mirco.mueller@canonical.com> |
609 | + */ |
610 | + |
611 | +#include "MockNotificationTypes.h" |
612 | + |
613 | +MockNotification::MockNotification(QObject *parent) : QObject(parent) { |
614 | +} |
615 | + |
616 | +MockNotification::~MockNotification() { |
617 | +} |
618 | |
619 | === added file 'tests/mocks/Unity/Notifications/MockNotificationTypes.h' |
620 | --- tests/mocks/Unity/Notifications/MockNotificationTypes.h 1970-01-01 00:00:00 +0000 |
621 | +++ tests/mocks/Unity/Notifications/MockNotificationTypes.h 2014-10-31 10:46:25 +0000 |
622 | @@ -0,0 +1,36 @@ |
623 | +/* |
624 | + * Copyright 2014 Canonical Ltd. |
625 | + * |
626 | + * This program is free software; you can redistribute it and/or modify |
627 | + * it under the terms of the GNU Lesser General Public License as published by |
628 | + * the Free Software Foundation; version 3. |
629 | + * |
630 | + * This program is distributed in the hope that it will be useful, |
631 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
632 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
633 | + * GNU Lesser General Public License for more details. |
634 | + * |
635 | + * You should have received a copy of the GNU Lesser General Public License |
636 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
637 | + * |
638 | + * Authors: |
639 | + * Mirco Mueller <mirco.mueller@canonical.com> |
640 | + */ |
641 | + |
642 | +#ifndef MOCK_NOTIFICATION_TYPES_H |
643 | +#define MOCK_NOTIFICATION_TYPES_H |
644 | + |
645 | +#include <QObject> |
646 | + |
647 | +class MockNotification : public QObject { |
648 | + Q_OBJECT |
649 | + Q_ENUMS(Type) |
650 | + |
651 | +public: |
652 | + MockNotification(QObject *parent=nullptr); |
653 | + virtual ~MockNotification(); |
654 | + |
655 | + enum Type { PlaceHolder, Confirmation, Ephemeral, Interactive, SnapDecision }; |
656 | +}; |
657 | + |
658 | +#endif // MOCK_NOTIFICATION_TYPES_H |
659 | |
660 | === removed file 'tests/mocks/Unity/Notifications/notification.js' |
661 | --- tests/mocks/Unity/Notifications/notification.js 2013-06-19 10:24:31 +0000 |
662 | +++ tests/mocks/Unity/Notifications/notification.js 1970-01-01 00:00:00 +0000 |
663 | @@ -1,23 +0,0 @@ |
664 | -/* |
665 | - * Copyright (C) 2013 Canonical, Ltd. |
666 | - * |
667 | - * This program is free software; you can redistribute it and/or modify |
668 | - * it under the terms of the GNU General Public License as published by |
669 | - * the Free Software Foundation; version 3. |
670 | - * |
671 | - * This program is distributed in the hope that it will be useful, |
672 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
673 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
674 | - * GNU General Public License for more details. |
675 | - * |
676 | - * You should have received a copy of the GNU General Public License |
677 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
678 | - */ |
679 | - |
680 | -.pragma library |
681 | - |
682 | -var Confirmation = 0; |
683 | -var Ephemeral = 1; |
684 | -var Interactive = 2; |
685 | -var SnapDecision = 3; |
686 | -var PlaceHolder = 4; |
687 | |
688 | === added file 'tests/mocks/Unity/Notifications/plugin.cpp' |
689 | --- tests/mocks/Unity/Notifications/plugin.cpp 1970-01-01 00:00:00 +0000 |
690 | +++ tests/mocks/Unity/Notifications/plugin.cpp 2014-10-31 10:46:25 +0000 |
691 | @@ -0,0 +1,31 @@ |
692 | +/* |
693 | + * Copyright 2014 Canonical Ltd. |
694 | + * |
695 | + * This program is free software; you can redistribute it and/or modify |
696 | + * it under the terms of the GNU Lesser General Public License as published by |
697 | + * the Free Software Foundation; version 3. |
698 | + * |
699 | + * This program is distributed in the hope that it will be useful, |
700 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
701 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
702 | + * GNU Lesser General Public License for more details. |
703 | + * |
704 | + * You should have received a copy of the GNU Lesser General Public License |
705 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
706 | + * |
707 | + * Authors: |
708 | + * Mirco Mueller <mirco.mueller@canonical.com> |
709 | + */ |
710 | + |
711 | +#include "plugin.h" |
712 | +#include "MockActionModel.h" |
713 | +#include "MockNotificationTypes.h" |
714 | + |
715 | +#include <QtQml/qqml.h> |
716 | + |
717 | +void TestNotificationPlugin::registerTypes(const char* uri) |
718 | +{ |
719 | + // @uri Unity.Notifications |
720 | + qmlRegisterUncreatableType<MockNotification>(uri, 1, 0, "Notification", "Notification objects can only be created by the plugin"); |
721 | + qmlRegisterType<ActionModel>(uri, 1, 0, "ActionModel"); |
722 | +} |
723 | |
724 | === added file 'tests/mocks/Unity/Notifications/plugin.h' |
725 | --- tests/mocks/Unity/Notifications/plugin.h 1970-01-01 00:00:00 +0000 |
726 | +++ tests/mocks/Unity/Notifications/plugin.h 2014-10-31 10:46:25 +0000 |
727 | @@ -0,0 +1,35 @@ |
728 | +/* |
729 | + * Copyright 2014 Canonical Ltd. |
730 | + * |
731 | + * This program is free software; you can redistribute it and/or modify |
732 | + * it under the terms of the GNU Lesser General Public License as published by |
733 | + * the Free Software Foundation; version 3. |
734 | + * |
735 | + * This program is distributed in the hope that it will be useful, |
736 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
737 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
738 | + * GNU Lesser General Public License for more details. |
739 | + * |
740 | + * You should have received a copy of the GNU Lesser General Public License |
741 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
742 | + * |
743 | + * Authors: |
744 | + * Mirco Mueller <mirco.mueller@canonical.com> |
745 | + */ |
746 | + |
747 | + |
748 | +#ifndef TESTNOTIFICATION_PLUGIN_H |
749 | +#define TESTNOTIFICATION_PLUGIN_H |
750 | + |
751 | +#include <QtQml/QQmlExtensionPlugin> |
752 | + |
753 | +class TestNotificationPlugin : public QQmlExtensionPlugin |
754 | +{ |
755 | + Q_OBJECT |
756 | + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
757 | + |
758 | +public: |
759 | + void registerTypes(const char* uri); |
760 | +}; |
761 | + |
762 | +#endif // TESTNOTIFICATION_PLUGIN_H |
763 | |
764 | === modified file 'tests/mocks/Unity/Notifications/qmldir' |
765 | --- tests/mocks/Unity/Notifications/qmldir 2014-05-02 22:57:21 +0000 |
766 | +++ tests/mocks/Unity/Notifications/qmldir 2014-10-31 10:46:25 +0000 |
767 | @@ -1,3 +1,4 @@ |
768 | module Unity.Notifications |
769 | -Notification 1.0 notification.js |
770 | +plugin MockNotificationsPlugin |
771 | typeinfo Notifications.qmltypes |
772 | + |
773 | |
774 | === modified file 'tests/qmltests/CMakeLists.txt' |
775 | --- tests/qmltests/CMakeLists.txt 2014-10-13 09:23:34 +0000 |
776 | +++ tests/qmltests/CMakeLists.txt 2014-10-31 10:46:25 +0000 |
777 | @@ -70,6 +70,7 @@ |
778 | add_qml_test(Launcher Launcher) |
779 | add_qml_test(Notifications Notifications) |
780 | add_qml_test(Notifications VisualSnapDecisionsQueue) |
781 | +add_qml_test(Notifications SwipeToAct) |
782 | add_qml_test(Panel ActiveCallHint) |
783 | add_qml_test(Panel IndicatorItem) |
784 | add_qml_test(Panel IndicatorItemRow ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel") |
785 | |
786 | === modified file 'tests/qmltests/Notifications/tst_Notifications.qml' |
787 | --- tests/qmltests/Notifications/tst_Notifications.qml 2014-10-14 10:07:44 +0000 |
788 | +++ tests/qmltests/Notifications/tst_Notifications.qml 2014-10-31 10:46:25 +0000 |
789 | @@ -23,280 +23,51 @@ |
790 | import Unity.Notifications 1.0 |
791 | import QtMultimedia 5.0 |
792 | |
793 | -Row { |
794 | - id: rootRow |
795 | - |
796 | - Component { |
797 | - id: mockNotification |
798 | - |
799 | - QtObject { |
800 | - function invokeAction(actionId) { |
801 | - mockModel.actionInvoked(actionId) |
802 | - } |
803 | - } |
804 | - } |
805 | - |
806 | - ListModel { |
807 | - id: mockModel |
808 | - |
809 | - signal actionInvoked(string actionId) |
810 | - |
811 | - function getRaw(id) { |
812 | - return mockNotification.createObject(mockModel) |
813 | - } |
814 | - |
815 | - // add the default/PlaceHolder notification to the model |
816 | - Component.onCompleted: { |
817 | +Item { |
818 | + width: notificationsRect.width + interactiveControls.width |
819 | + height: notificationsRect.height |
820 | + |
821 | + Row { |
822 | + id: rootRow |
823 | + |
824 | + Component { |
825 | + id: mockNotification |
826 | + |
827 | + QtObject { |
828 | + function invokeAction(actionId) { |
829 | + mockModel.actionInvoked(actionId) |
830 | + } |
831 | + } |
832 | + } |
833 | + |
834 | + ListModel { |
835 | + id: mockModel |
836 | + dynamicRoles: true |
837 | + |
838 | + signal actionInvoked(string actionId) |
839 | + |
840 | + function getRaw(id) { |
841 | + return mockNotification.createObject(mockModel) |
842 | + } |
843 | + |
844 | + // add the default/PlaceHolder notification to the model |
845 | + Component.onCompleted: { |
846 | + var n = { |
847 | + type: Notification.PlaceHolder, |
848 | + hints: {}, |
849 | + summary: "", |
850 | + body: "", |
851 | + icon: "", |
852 | + secondaryIcon: "", |
853 | + actions: [] |
854 | + } |
855 | + |
856 | + append(n) |
857 | + } |
858 | + } |
859 | + |
860 | + function addSnapDecisionNotification() { |
861 | var n = { |
862 | - type: Notification.PlaceHolder, |
863 | - hints: {}, |
864 | - summary: "", |
865 | - body: "", |
866 | - icon: "", |
867 | - value: 0, |
868 | - secondaryIcon: "", |
869 | - actions: [] |
870 | - } |
871 | - |
872 | - append(n) |
873 | - } |
874 | - } |
875 | - |
876 | - function addSnapDecisionNotification() { |
877 | - var n = { |
878 | - type: Notification.SnapDecision, |
879 | - hints: {"x-canonical-private-affirmative-tint": "true"}, |
880 | - summary: "Tom Ato", |
881 | - body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.", |
882 | - icon: "../graphics/avatars/funky.png", |
883 | - secondaryIcon: "../graphics/applicationIcons/facebook.png", |
884 | - actions: [{ id: "ok_id", label: "Ok"}, |
885 | - { id: "cancel_id", label: "Cancel"}, |
886 | - { id: "notreally_id", label: "Not really"}, |
887 | - { id: "noway_id", label: "messages:No way"}, |
888 | - { id: "nada_id", label: "messages:Nada"}] |
889 | - } |
890 | - |
891 | - mockModel.append(n) |
892 | - } |
893 | - |
894 | - function add2over1SnapDecisionNotification() { |
895 | - var n = { |
896 | - type: Notification.SnapDecision, |
897 | - hints: {"x-canonical-private-affirmative-tint": "true",}, |
898 | - summary: "Theatre at Ferria Stadium", |
899 | - body: "at Ferria Stadium in Bilbao, Spain\n07578545317", |
900 | - icon: "", |
901 | - secondaryIcon: "", |
902 | - actions: [{ id: "ok_id", label: "Ok"}, |
903 | - { id: "snooze_id", label: "Snooze"}, |
904 | - { id: "view_id", label: "View"}] |
905 | - } |
906 | - |
907 | - mockModel.append(n) |
908 | - } |
909 | - |
910 | - function addEphemeralNotification() { |
911 | - var n = { |
912 | - type: Notification.Ephemeral, |
913 | - summary: "Cole Raby", |
914 | - body: "I did not expect it to be that late.", |
915 | - icon: "../graphics/avatars/amanda.png", |
916 | - secondaryIcon: "../graphics/applicationIcons/facebook.png", |
917 | - actions: [] |
918 | - } |
919 | - |
920 | - mockModel.append(n) |
921 | - } |
922 | - |
923 | - function addEphemeralNonShapedIconNotification() { |
924 | - var n = { |
925 | - type: Notification.Ephemeral, |
926 | - hints: {"x-canonical-non-shaped-icon": "true"}, |
927 | - summary: "Contacts", |
928 | - body: "Synchronised contacts-database with cloud-storage.", |
929 | - icon: "../graphics/applicationIcons/contacts-app.png", |
930 | - secondaryIcon: "", |
931 | - actions: [] |
932 | - } |
933 | - |
934 | - mockModel.append(n) |
935 | - } |
936 | - |
937 | - function addEphemeralIconSummaryNotification() { |
938 | - var n = { |
939 | - type: Notification.Ephemeral, |
940 | - hints: {"x-canonical-non-shaped-icon": "false"}, |
941 | - summary: "Photo upload completed", |
942 | - body: "", |
943 | - icon: "../graphics/applicationIcons/facebook.png", |
944 | - secondaryIcon: "", |
945 | - actions: [] |
946 | - } |
947 | - |
948 | - mockModel.append(n) |
949 | - } |
950 | - |
951 | - function addInteractiveNotification() { |
952 | - var n = { |
953 | - type: Notification.Interactive, |
954 | - summary: "Interactive notification", |
955 | - body: "This is a notification that can be clicked", |
956 | - icon: "../graphics/avatars/anna_olsson.png", |
957 | - secondaryIcon: "", |
958 | - actions: [{ id: "reply_id", label: "Dummy"}], |
959 | - } |
960 | - |
961 | - mockModel.append(n) |
962 | - } |
963 | - |
964 | - function addConfirmationNotification() { |
965 | - var n = { |
966 | - type: Notification.Confirmation, |
967 | - hints: {"x-canonical-non-shaped-icon": "true"}, |
968 | - summary: "Confirmation notification", |
969 | - body: "", |
970 | - icon: "image://theme/audio-volume-medium", |
971 | - secondaryIcon: "", |
972 | - value: 50, |
973 | - actions: [], |
974 | - } |
975 | - |
976 | - mockModel.append(n) |
977 | - } |
978 | - |
979 | - function add2ndConfirmationNotification() { |
980 | - var n = { |
981 | - type: Notification.Confirmation, |
982 | - hints: {"x-canonical-non-shaped-icon": "true", |
983 | - "x-canonical-value-bar-tint": "true"}, |
984 | - summary: "Confirmation notification", |
985 | - body: "High Volume", |
986 | - icon: "image://theme/audio-volume-high", |
987 | - secondaryIcon: "", |
988 | - value: 85, |
989 | - actions: [], |
990 | - } |
991 | - |
992 | - mockModel.append(n) |
993 | - } |
994 | - |
995 | - function clearNotifications() { |
996 | - while(mockModel.count > 1) { |
997 | - remove1stNotification() |
998 | - } |
999 | - } |
1000 | - |
1001 | - function remove1stNotification() { |
1002 | - if (mockModel.count > 1) |
1003 | - mockModel.remove(1) |
1004 | - } |
1005 | - |
1006 | - Rectangle { |
1007 | - id: notificationsRect |
1008 | - |
1009 | - width: units.gu(40) |
1010 | - height: units.gu(115) |
1011 | - |
1012 | - MouseArea{ |
1013 | - id: clickThroughCatcher |
1014 | - |
1015 | - anchors.fill: parent |
1016 | - } |
1017 | - |
1018 | - Notifications { |
1019 | - id: notifications |
1020 | - |
1021 | - margin: units.gu(1) |
1022 | - |
1023 | - anchors.fill: parent |
1024 | - model: mockModel |
1025 | - } |
1026 | - } |
1027 | - |
1028 | - Rectangle { |
1029 | - id: interactiveControls |
1030 | - |
1031 | - width: units.gu(30) |
1032 | - height: units.gu(115) |
1033 | - color: "grey" |
1034 | - |
1035 | - Column { |
1036 | - spacing: units.gu(1) |
1037 | - anchors.fill: parent |
1038 | - anchors.margins: units.gu(1) |
1039 | - |
1040 | - Button { |
1041 | - width: parent.width |
1042 | - text: "add a snap-decision" |
1043 | - onClicked: addSnapDecisionNotification() |
1044 | - } |
1045 | - |
1046 | - Button { |
1047 | - width: parent.width |
1048 | - text: "add a 2over1 snap-decision" |
1049 | - onClicked: add2over1SnapDecisionNotification() |
1050 | - } |
1051 | - |
1052 | - Button { |
1053 | - width: parent.width |
1054 | - text: "add an ephemeral" |
1055 | - onClicked: addEphemeralNotification() |
1056 | - } |
1057 | - |
1058 | - Button { |
1059 | - width: parent.width |
1060 | - text: "add an non-shaped-icon-summary-body" |
1061 | - onClicked: addEphemeralNonShapedIconNotification() |
1062 | - } |
1063 | - |
1064 | - Button { |
1065 | - width: parent.width |
1066 | - text: "add an icon-summary" |
1067 | - onClicked: addEphemeralIconSummaryNotification() |
1068 | - } |
1069 | - |
1070 | - Button { |
1071 | - width: parent.width |
1072 | - text: "add an interactive" |
1073 | - onClicked: addInteractiveNotification() |
1074 | - } |
1075 | - |
1076 | - Button { |
1077 | - width: parent.width |
1078 | - text: "add a confirmation" |
1079 | - onClicked: addConfirmationNotification() |
1080 | - } |
1081 | - |
1082 | - Button { |
1083 | - width: parent.width |
1084 | - text: "add a 2nd confirmation" |
1085 | - onClicked: add2ndConfirmationNotification() |
1086 | - } |
1087 | - |
1088 | - Button { |
1089 | - width: parent.width |
1090 | - text: "remove 1st notification" |
1091 | - onClicked: remove1stNotification() |
1092 | - } |
1093 | - |
1094 | - Button { |
1095 | - width: parent.width |
1096 | - text: "clear model" |
1097 | - onClicked: clearNotifications() |
1098 | - } |
1099 | - } |
1100 | - } |
1101 | - |
1102 | - UnityTestCase { |
1103 | - id: root |
1104 | - name: "NotificationRendererTest" |
1105 | - when: windowShown |
1106 | - |
1107 | - function test_NotificationRenderer_data() { |
1108 | - return [ |
1109 | - { |
1110 | - tag: "Snap Decision with secondary icon and button-tint", |
1111 | type: Notification.SnapDecision, |
1112 | hints: {"x-canonical-private-affirmative-tint": "true"}, |
1113 | summary: "Tom Ato", |
1114 | @@ -307,23 +78,14 @@ |
1115 | { id: "cancel_id", label: "Cancel"}, |
1116 | { id: "notreally_id", label: "Not really"}, |
1117 | { id: "noway_id", label: "messages:No way"}, |
1118 | - { id: "nada_id", label: "messages:Nada"}], |
1119 | - summaryVisible: true, |
1120 | - bodyVisible: true, |
1121 | - iconVisible: true, |
1122 | - centeredIconVisible: false, |
1123 | - shaped: true, |
1124 | - nonShaped: false, |
1125 | - secondaryIconVisible: true, |
1126 | - buttonRowVisible: true, |
1127 | - buttonTinted: true, |
1128 | - hasSound: false, |
1129 | - valueVisible: false, |
1130 | - valueLabelVisible: false, |
1131 | - valueTinted: false |
1132 | - }, |
1133 | - { |
1134 | - tag: "2-over-1 Snap Decision with button-tint", |
1135 | + { id: "nada_id", label: "messages:Nada"}] |
1136 | + } |
1137 | + |
1138 | + mockModel.append(n) |
1139 | + } |
1140 | + |
1141 | + function add2over1SnapDecisionNotification() { |
1142 | + var n = { |
1143 | type: Notification.SnapDecision, |
1144 | hints: {"x-canonical-private-affirmative-tint": "true"}, |
1145 | summary: "Theatre at Ferria Stadium", |
1146 | @@ -332,327 +94,573 @@ |
1147 | secondaryIcon: "", |
1148 | actions: [{ id: "ok_id", label: "Ok"}, |
1149 | { id: "snooze_id", label: "Snooze"}, |
1150 | - { id: "view_id", label: "View"}], |
1151 | - summaryVisible: true, |
1152 | - bodyVisible: true, |
1153 | - iconVisible: false, |
1154 | - centeredIconVisible: false, |
1155 | - shaped: false, |
1156 | - secondaryIconVisible: false, |
1157 | - buttonRowVisible: false, |
1158 | - buttonTinted: true, |
1159 | - hasSound: false, |
1160 | - valueVisible: false, |
1161 | - valueLabelVisible: false, |
1162 | - valueTinted: false |
1163 | - }, |
1164 | - { |
1165 | - tag: "Ephemeral notification - icon-summary layout", |
1166 | - type: Notification.Ephemeral, |
1167 | - hints: {}, |
1168 | + { id: "view_id", label: "View"}] |
1169 | + } |
1170 | + |
1171 | + mockModel.append(n) |
1172 | + } |
1173 | + |
1174 | + function addEphemeralNotification() { |
1175 | + var n = { |
1176 | + type: Notification.Ephemeral, |
1177 | + summary: "Cole Raby", |
1178 | + body: "I did not expect it to be that late.", |
1179 | + icon: "../graphics/avatars/amanda.png", |
1180 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1181 | + actions: [] |
1182 | + } |
1183 | + |
1184 | + mockModel.append(n) |
1185 | + } |
1186 | + |
1187 | + function addEphemeralNonShapedIconNotification() { |
1188 | + var n = { |
1189 | + type: Notification.Ephemeral, |
1190 | + hints: {"x-canonical-non-shaped-icon": "true"}, |
1191 | + summary: "Contacts", |
1192 | + body: "Synchronised contacts-database with cloud-storage.", |
1193 | + icon: "../graphics/applicationIcons/contacts-app.png", |
1194 | + secondaryIcon: "", |
1195 | + actions: [] |
1196 | + } |
1197 | + |
1198 | + mockModel.append(n) |
1199 | + } |
1200 | + |
1201 | + function addEphemeralIconSummaryNotification() { |
1202 | + var n = { |
1203 | + type: Notification.Ephemeral, |
1204 | + hints: {"x-canonical-non-shaped-icon": "false"}, |
1205 | summary: "Photo upload completed", |
1206 | body: "", |
1207 | icon: "../graphics/applicationIcons/facebook.png", |
1208 | secondaryIcon: "", |
1209 | - actions: [], |
1210 | - summaryVisible: true, |
1211 | - bodyVisible: false, |
1212 | - iconVisible: true, |
1213 | - centeredIconVisible: false, |
1214 | - shaped: true, |
1215 | - secondaryIconVisible: false, |
1216 | - buttonRowVisible: false, |
1217 | - buttonTinted: false, |
1218 | - hasSound: false, |
1219 | - valueVisible: false, |
1220 | - valueLabelVisible: false, |
1221 | - valueTinted: false |
1222 | - }, |
1223 | - { |
1224 | - tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout", |
1225 | - type: Notification.Ephemeral, |
1226 | - hints: {"x-canonical-private-affirmative-tint": "false", |
1227 | - "sound-file": "dummy.ogg", |
1228 | - "suppress-sound": "true"}, |
1229 | - summary: "New comment successfully published", |
1230 | - body: "", |
1231 | - icon: "", |
1232 | - secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1233 | - actions: [], |
1234 | - summaryVisible: true, |
1235 | - bodyVisible: false, |
1236 | - interactiveAreaEnabled: false, |
1237 | - iconVisible: false, |
1238 | - centeredIconVisible: false, |
1239 | - shaped: false, |
1240 | - secondaryIconVisible: true, |
1241 | - buttonRowVisible: false, |
1242 | - buttonTinted: false, |
1243 | - hasSound: false, |
1244 | - valueVisible: false, |
1245 | - valueLabelVisible: false, |
1246 | - valueTinted: false |
1247 | - }, |
1248 | - { |
1249 | - tag: "Interactive notification", |
1250 | + actions: [] |
1251 | + } |
1252 | + |
1253 | + mockModel.append(n) |
1254 | + } |
1255 | + |
1256 | + function addInteractiveNotification() { |
1257 | + var n = { |
1258 | type: Notification.Interactive, |
1259 | - hints: {"x-canonical-private-affirmative-tint": "false", |
1260 | - "sound-file": "dummy.ogg"}, |
1261 | summary: "Interactive notification", |
1262 | body: "This is a notification that can be clicked", |
1263 | - icon: "../graphics/avatars/amanda.png", |
1264 | + icon: "../graphics/avatars/anna_olsson.png", |
1265 | secondaryIcon: "", |
1266 | actions: [{ id: "reply_id", label: "Dummy"}], |
1267 | - summaryVisible: true, |
1268 | - bodyVisible: true, |
1269 | - iconVisible: true, |
1270 | - centeredIconVisible: false, |
1271 | - shaped: true, |
1272 | - secondaryIconVisible: false, |
1273 | - buttonRowVisible: false, |
1274 | - buttonTinted: false, |
1275 | - hasSound: true, |
1276 | - valueVisible: false, |
1277 | - valueLabelVisible: false, |
1278 | - valueTinted: false |
1279 | - }, |
1280 | - { |
1281 | - tag: "Snap Decision without secondary icon and no button-tint", |
1282 | - type: Notification.SnapDecision, |
1283 | - hints: {"x-canonical-private-affirmative-tint": "false", |
1284 | - "sound-file": "dummy.ogg"}, |
1285 | - summary: "Bro Coly", |
1286 | - 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.", |
1287 | - icon: "../graphics/avatars/anna_olsson.png", |
1288 | - secondaryIcon: "", |
1289 | - actions: [{ id: "accept_id", label: "Accept"}, |
1290 | - { id: "reject_id", label: "Reject"}], |
1291 | - summaryVisible: true, |
1292 | - bodyVisible: true, |
1293 | - iconVisible: true, |
1294 | - centeredIconVisible: false, |
1295 | - shaped: true, |
1296 | - secondaryIconVisible: false, |
1297 | - buttonRowVisible: true, |
1298 | - buttonTinted: false, |
1299 | - hasSound: true, |
1300 | - valueVisible: false, |
1301 | - valueLabelVisible: false, |
1302 | - valueTinted: false |
1303 | - }, |
1304 | - { |
1305 | - tag: "Ephemeral notification", |
1306 | - type: Notification.Ephemeral, |
1307 | - hints: {"x-canonical-private-affirmative-tint": "false", |
1308 | - "sound-file": "dummy.ogg"}, |
1309 | - summary: "Cole Raby", |
1310 | - body: "I did not expect it to be that late.", |
1311 | - icon: "../graphics/avatars/funky.png", |
1312 | - secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1313 | - actions: [], |
1314 | - summaryVisible: true, |
1315 | - bodyVisible: true, |
1316 | - iconVisible: true, |
1317 | - centeredIconVisible: false, |
1318 | - shaped: true, |
1319 | - secondaryIconVisible: true, |
1320 | - buttonRowVisible: false, |
1321 | - buttonTinted: false, |
1322 | - hasSound: true, |
1323 | - valueVisible: false, |
1324 | - valueLabelVisible: false, |
1325 | - valueTinted: false |
1326 | - }, |
1327 | - { |
1328 | - tag: "Ephemeral notification with non-shaped icon", |
1329 | - type: Notification.Ephemeral, |
1330 | - hints: {"x-canonical-private-affirmative-tint": "false", |
1331 | - "x-canonical-non-shaped-icon": "true"}, |
1332 | - summary: "Contacts", |
1333 | - body: "Synchronised contacts-database with cloud-storage.", |
1334 | - icon: "image://theme/contacts-app", |
1335 | - secondaryIcon: "", |
1336 | - actions: [], |
1337 | - summaryVisible: true, |
1338 | - bodyVisible: true, |
1339 | - iconVisible: true, |
1340 | - centeredIconVisible: false, |
1341 | - shaped: false, |
1342 | - secondaryIconVisible: false, |
1343 | - buttonRowVisible: false, |
1344 | - buttonTinted: false, |
1345 | - hasSound: false, |
1346 | - valueVisible: false, |
1347 | - valueLabelVisible: false, |
1348 | - valueTinted: false |
1349 | - }, |
1350 | - { |
1351 | - tag: "Confirmation notification with value", |
1352 | + } |
1353 | + |
1354 | + mockModel.append(n) |
1355 | + } |
1356 | + |
1357 | + function addConfirmationNotification() { |
1358 | + var n = { |
1359 | type: Notification.Confirmation, |
1360 | hints: {"x-canonical-non-shaped-icon": "true"}, |
1361 | - summary: "", |
1362 | + summary: "Confirmation notification", |
1363 | body: "", |
1364 | icon: "image://theme/audio-volume-medium", |
1365 | secondaryIcon: "", |
1366 | value: 50, |
1367 | actions: [], |
1368 | - summaryVisible: false, |
1369 | - bodyVisible: false, |
1370 | - iconVisible: false, |
1371 | - centeredIconVisible: true, |
1372 | - shaped: false, |
1373 | - secondaryIconVisible: false, |
1374 | - buttonRowVisible: false, |
1375 | - buttonTinted: false, |
1376 | - hasSound: false, |
1377 | - valueVisible: true, |
1378 | - valueLabelVisible: false, |
1379 | - valueTinted: false |
1380 | - }, |
1381 | - { |
1382 | - tag: "Confirmation notification with value, label and tint", |
1383 | + } |
1384 | + |
1385 | + mockModel.append(n) |
1386 | + } |
1387 | + |
1388 | + function add2ndConfirmationNotification() { |
1389 | + var n = { |
1390 | type: Notification.Confirmation, |
1391 | hints: {"x-canonical-non-shaped-icon": "true", |
1392 | - "x-canonical-value-bar-tint" : "true"}, |
1393 | - summary: "", |
1394 | + "x-canonical-value-bar-tint": "true"}, |
1395 | + summary: "Confirmation notification", |
1396 | body: "High Volume", |
1397 | icon: "image://theme/audio-volume-high", |
1398 | secondaryIcon: "", |
1399 | value: 85, |
1400 | actions: [], |
1401 | - summaryVisible: false, |
1402 | - bodyVisible: false, |
1403 | - iconVisible: false, |
1404 | - centeredIconVisible: true, |
1405 | - shaped: false, |
1406 | - secondaryIconVisible: false, |
1407 | - buttonRowVisible: false, |
1408 | - buttonTinted: false, |
1409 | - hasSound: false, |
1410 | - valueVisible: true, |
1411 | - valueLabelVisible: true, |
1412 | - valueTinted: true |
1413 | - } |
1414 | - ] |
1415 | - } |
1416 | - |
1417 | - SignalSpy { |
1418 | - id: clickThroughSpy |
1419 | - |
1420 | - target: clickThroughCatcher |
1421 | - signalName: "clicked" |
1422 | - } |
1423 | - |
1424 | - SignalSpy { |
1425 | - id: actionSpy |
1426 | - |
1427 | - target: mockModel |
1428 | - signalName: "actionInvoked" |
1429 | - } |
1430 | - |
1431 | - function cleanup() { |
1432 | - clickThroughSpy.clear() |
1433 | - actionSpy.clear() |
1434 | - } |
1435 | - |
1436 | - function test_NotificationRenderer(data) { |
1437 | - // populate model with some mock notifications |
1438 | - mockModel.append(data) |
1439 | - |
1440 | - // make sure the view is properly updated before going on |
1441 | - notifications.forceLayout(); |
1442 | - waitForRendering(notifications); |
1443 | - |
1444 | - var notification = findChild(notifications, "notification" + (mockModel.count - 1)) |
1445 | - verify(notification !== undefined, "notification wasn't found"); |
1446 | - |
1447 | - waitForRendering(notification); |
1448 | - |
1449 | - var icon = findChild(notification, "icon") |
1450 | - var centeredIcon = findChild(notification, "centeredIcon") |
1451 | - var interactiveArea = findChild(notification, "interactiveArea") |
1452 | - var secondaryIcon = findChild(notification, "secondaryIcon") |
1453 | - var summaryLabel = findChild(notification, "summaryLabel") |
1454 | - var bodyLabel = findChild(notification, "bodyLabel") |
1455 | - var buttonRow = findChild(notification, "buttonRow") |
1456 | - var valueIndicator = findChild(notification, "valueIndicator") |
1457 | - var valueLabel = findChild(notification, "valueLabel") |
1458 | - var innerBar = findChild(notification, "innerBar") |
1459 | - |
1460 | - compare(icon.visible, data.iconVisible, "avatar-icon visibility is incorrect") |
1461 | - if (icon.visible) { |
1462 | - compare(icon.shaped, data.shaped, "shaped-status is incorrect") |
1463 | - } |
1464 | - compare(centeredIcon.visible, data.centeredIconVisible, "centered-icon visibility is incorrect") |
1465 | - if (centeredIcon.visible) { |
1466 | - compare(centeredIcon.shaped, data.shaped, "shaped-status is incorrect") |
1467 | - } |
1468 | - compare(valueIndicator.visible, data.valueVisible, "value-indicator visibility is incorrect") |
1469 | - if (valueIndicator.visible) { |
1470 | - verify(innerBar.color === data.valueTinted ? UbuntuColors.orange : "white", "value-bar has the wrong color-tint") |
1471 | - } |
1472 | - compare(valueLabel.visible, data.valueLabelVisible, "value-label visibility is incorrect") |
1473 | - |
1474 | - // test input does not fall through |
1475 | - mouseClick(notification, notification.width / 2, notification.height / 2) |
1476 | - if(data.type == Notification.Interactive) { |
1477 | - actionSpy.wait() |
1478 | - compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action") |
1479 | - } |
1480 | - compare(clickThroughSpy.count, 0, "click on notification fell through") |
1481 | - |
1482 | - compare(secondaryIcon.visible, data.secondaryIconVisible, "secondary-icon visibility is incorrect") |
1483 | - compare(summaryLabel.visible, data.summaryVisible, "summary-text visibility is incorrect") |
1484 | - compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect") |
1485 | - compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect") |
1486 | - |
1487 | - var audioItem = findInvisibleChild(notification, "sound") |
1488 | - compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state") |
1489 | - |
1490 | - if(data.buttonRowVisible) { |
1491 | - var buttonCancel = findChild(buttonRow, "notify_button1") |
1492 | - var buttonAccept = findChild(buttonRow, "notify_button0") |
1493 | - |
1494 | - // only test the left/cancel-button if two actions have been passed in |
1495 | - if (data.actions.length == 2) { |
1496 | - tryCompareFunction(function() { mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1497 | - compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action") |
1498 | - actionSpy.clear() |
1499 | - } |
1500 | - |
1501 | - // check the tinting of the positive/right button |
1502 | - verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint") |
1503 | - |
1504 | - // click the positive/right button |
1505 | - tryCompareFunction(function() { mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1506 | - compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action") |
1507 | + } |
1508 | + |
1509 | + mockModel.append(n) |
1510 | + } |
1511 | + |
1512 | + function clearNotifications() { |
1513 | + while(mockModel.count > 1) { |
1514 | + remove1stNotification() |
1515 | + } |
1516 | + } |
1517 | + |
1518 | + function remove1stNotification() { |
1519 | + if (mockModel.count > 1) |
1520 | + mockModel.remove(1) |
1521 | + } |
1522 | + |
1523 | + Rectangle { |
1524 | + id: notificationsRect |
1525 | + |
1526 | + width: units.gu(40) |
1527 | + height: units.gu(115) |
1528 | + |
1529 | + MouseArea{ |
1530 | + id: clickThroughCatcher |
1531 | + |
1532 | + anchors.fill: parent |
1533 | + } |
1534 | + |
1535 | + Notifications { |
1536 | + id: notifications |
1537 | + |
1538 | + margin: units.gu(1) |
1539 | + |
1540 | + anchors.fill: parent |
1541 | + model: mockModel |
1542 | + } |
1543 | + } |
1544 | + |
1545 | + Rectangle { |
1546 | + id: interactiveControls |
1547 | + |
1548 | + width: units.gu(30) |
1549 | + height: units.gu(115) |
1550 | + color: "grey" |
1551 | + |
1552 | + Column { |
1553 | + spacing: units.gu(1) |
1554 | + anchors.fill: parent |
1555 | + anchors.margins: units.gu(1) |
1556 | + |
1557 | + Button { |
1558 | + width: parent.width |
1559 | + text: "add a snap-decision" |
1560 | + onClicked: rootRow.addSnapDecisionNotification() |
1561 | + } |
1562 | + |
1563 | + Button { |
1564 | + width: parent.width |
1565 | + text: "add a 2over1 snap-decision" |
1566 | + onClicked: rootRow.add2over1SnapDecisionNotification() |
1567 | + } |
1568 | + |
1569 | + Button { |
1570 | + width: parent.width |
1571 | + text: "add an ephemeral" |
1572 | + onClicked: rootRow.addEphemeralNotification() |
1573 | + } |
1574 | + |
1575 | + Button { |
1576 | + width: parent.width |
1577 | + text: "add an non-shaped-icon-summary-body" |
1578 | + onClicked: rootRow.addEphemeralNonShapedIconNotification() |
1579 | + } |
1580 | + |
1581 | + Button { |
1582 | + width: parent.width |
1583 | + text: "add an icon-summary" |
1584 | + onClicked: rootRow.addEphemeralIconSummaryNotification() |
1585 | + } |
1586 | + |
1587 | + Button { |
1588 | + width: parent.width |
1589 | + text: "add an interactive" |
1590 | + onClicked: rootRow.addInteractiveNotification() |
1591 | + } |
1592 | + |
1593 | + Button { |
1594 | + width: parent.width |
1595 | + text: "add a confirmation" |
1596 | + onClicked: rootRow.addConfirmationNotification() |
1597 | + } |
1598 | + |
1599 | + Button { |
1600 | + width: parent.width |
1601 | + text: "add a 2nd confirmation" |
1602 | + onClicked: rootRow.add2ndConfirmationNotification() |
1603 | + } |
1604 | + |
1605 | + Button { |
1606 | + width: parent.width |
1607 | + text: "remove 1st notification" |
1608 | + onClicked: rootRow.remove1stNotification() |
1609 | + } |
1610 | + |
1611 | + Button { |
1612 | + width: parent.width |
1613 | + text: "clear model" |
1614 | + onClicked: rootRow.clearNotifications() |
1615 | + } |
1616 | + } |
1617 | + } |
1618 | + |
1619 | + ActionModel { |
1620 | + id: myActionModel |
1621 | + } |
1622 | + |
1623 | + UnityTestCase { |
1624 | + id: root |
1625 | + name: "NotificationRendererTest" |
1626 | + when: windowShown |
1627 | + |
1628 | + function test_NotificationRenderer_data() { |
1629 | + return [ |
1630 | + { |
1631 | + tag: "Snap Decision with secondary icon and button-tint", |
1632 | + type: Notification.SnapDecision, |
1633 | + hints: {"x-canonical-private-affirmative-tint": "true"}, |
1634 | + summary: "Tom Ato", |
1635 | + body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.", |
1636 | + icon: "../graphics/avatars/funky.png", |
1637 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1638 | + actions: [{ id: "ok_id", label: "Ok"}, |
1639 | + { id: "cancel_id", label: "Cancel"}, |
1640 | + { id: "notreally_id", label: "Not really"}, |
1641 | + { id: "noway_id", label: "messages:No way"}, |
1642 | + { id: "nada_id", label: "messages:Nada"}], |
1643 | + summaryVisible: true, |
1644 | + bodyVisible: true, |
1645 | + iconVisible: true, |
1646 | + centeredIconVisible: false, |
1647 | + shaped: true, |
1648 | + secondaryIconVisible: true, |
1649 | + buttonRowVisible: true, |
1650 | + buttonTinted: true, |
1651 | + hasSound: false, |
1652 | + valueVisible: false, |
1653 | + valueLabelVisible: false, |
1654 | + valueTinted: false |
1655 | + }, |
1656 | + { |
1657 | + tag: "2-over-1 Snap Decision with button-tint", |
1658 | + type: Notification.SnapDecision, |
1659 | + hints: {"x-canonical-private-affirmative-tint": "true"}, |
1660 | + summary: "Theatre at Ferria Stadium", |
1661 | + body: "at Ferria Stadium in Bilbao, Spain\n07578545317", |
1662 | + icon: "", |
1663 | + secondaryIcon: "", |
1664 | + actions: [{ id: "ok_id", label: "Ok"}, |
1665 | + { id: "snooze_id", label: "Snooze"}, |
1666 | + { id: "view_id", label: "View"}], |
1667 | + summaryVisible: true, |
1668 | + bodyVisible: true, |
1669 | + iconVisible: false, |
1670 | + centeredIconVisible: false, |
1671 | + shaped: false, |
1672 | + secondaryIconVisible: false, |
1673 | + buttonRowVisible: false, |
1674 | + buttonTinted: true, |
1675 | + hasSound: false, |
1676 | + valueVisible: false, |
1677 | + valueLabelVisible: false, |
1678 | + valueTinted: false |
1679 | + }, |
1680 | + { |
1681 | + tag: "Ephemeral notification - icon-summary layout", |
1682 | + type: Notification.Ephemeral, |
1683 | + hints: {}, |
1684 | + summary: "Photo upload completed", |
1685 | + body: "", |
1686 | + icon: "../graphics/applicationIcons/facebook.png", |
1687 | + secondaryIcon: "", |
1688 | + actions: [], |
1689 | + summaryVisible: true, |
1690 | + bodyVisible: false, |
1691 | + iconVisible: true, |
1692 | + centeredIconVisible: false, |
1693 | + shaped: true, |
1694 | + secondaryIconVisible: false, |
1695 | + buttonRowVisible: false, |
1696 | + buttonTinted: false, |
1697 | + hasSound: false, |
1698 | + valueVisible: false, |
1699 | + valueLabelVisible: false, |
1700 | + valueTinted: false |
1701 | + }, |
1702 | + { |
1703 | + tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout", |
1704 | + type: Notification.Ephemeral, |
1705 | + hints: {"x-canonical-private-affirmative-tint": "false", |
1706 | + "sound-file": "dummy.ogg", |
1707 | + "suppress-sound": "true"}, |
1708 | + summary: "New comment successfully published", |
1709 | + body: "", |
1710 | + icon: "", |
1711 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1712 | + actions: [], |
1713 | + summaryVisible: true, |
1714 | + bodyVisible: false, |
1715 | + interactiveAreaEnabled: false, |
1716 | + iconVisible: false, |
1717 | + centeredIconVisible: false, |
1718 | + shaped: false, |
1719 | + secondaryIconVisible: true, |
1720 | + buttonRowVisible: false, |
1721 | + buttonTinted: false, |
1722 | + hasSound: false, |
1723 | + valueVisible: false, |
1724 | + valueLabelVisible: false, |
1725 | + valueTinted: false |
1726 | + }, |
1727 | + { |
1728 | + tag: "Interactive notification", |
1729 | + type: Notification.Interactive, |
1730 | + hints: {"x-canonical-private-affirmative-tint": "false", |
1731 | + "sound-file": "dummy.ogg"}, |
1732 | + summary: "Interactive notification", |
1733 | + body: "This is a notification that can be clicked", |
1734 | + icon: "../graphics/avatars/amanda.png", |
1735 | + secondaryIcon: "", |
1736 | + actions: [{ id: "reply_id", label: "Dummy"}], |
1737 | + summaryVisible: true, |
1738 | + bodyVisible: true, |
1739 | + iconVisible: true, |
1740 | + centeredIconVisible: false, |
1741 | + shaped: true, |
1742 | + secondaryIconVisible: false, |
1743 | + buttonRowVisible: false, |
1744 | + buttonTinted: false, |
1745 | + hasSound: true, |
1746 | + valueVisible: false, |
1747 | + valueLabelVisible: false, |
1748 | + valueTinted: false |
1749 | + }, |
1750 | + { |
1751 | + tag: "Snap Decision without secondary icon and no button-tint", |
1752 | + type: Notification.SnapDecision, |
1753 | + hints: {"x-canonical-private-affirmative-tint": "false", |
1754 | + "sound-file": "dummy.ogg"}, |
1755 | + summary: "Bro Coly", |
1756 | + 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.", |
1757 | + icon: "../graphics/avatars/anna_olsson.png", |
1758 | + secondaryIcon: "", |
1759 | + actions: [{ id: "accept_id", label: "Accept"}, |
1760 | + { id: "reject_id", label: "Reject"}], |
1761 | + summaryVisible: true, |
1762 | + bodyVisible: true, |
1763 | + iconVisible: true, |
1764 | + centeredIconVisible: false, |
1765 | + shaped: true, |
1766 | + secondaryIconVisible: false, |
1767 | + buttonRowVisible: true, |
1768 | + buttonTinted: false, |
1769 | + hasSound: true, |
1770 | + valueVisible: false, |
1771 | + valueLabelVisible: false, |
1772 | + valueTinted: false |
1773 | + }, |
1774 | + { |
1775 | + tag: "Ephemeral notification", |
1776 | + type: Notification.Ephemeral, |
1777 | + hints: {"x-canonical-private-affirmative-tint": "false", |
1778 | + "sound-file": "dummy.ogg"}, |
1779 | + summary: "Cole Raby", |
1780 | + body: "I did not expect it to be that late.", |
1781 | + icon: "../graphics/avatars/funky.png", |
1782 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
1783 | + actions: [], |
1784 | + summaryVisible: true, |
1785 | + bodyVisible: true, |
1786 | + iconVisible: true, |
1787 | + centeredIconVisible: false, |
1788 | + shaped: true, |
1789 | + secondaryIconVisible: true, |
1790 | + buttonRowVisible: false, |
1791 | + buttonTinted: false, |
1792 | + hasSound: true, |
1793 | + valueVisible: false, |
1794 | + valueLabelVisible: false, |
1795 | + valueTinted: false |
1796 | + }, |
1797 | + { |
1798 | + tag: "Ephemeral notification with non-shaped icon", |
1799 | + type: Notification.Ephemeral, |
1800 | + hints: {"x-canonical-private-affirmative-tint": "false", |
1801 | + "x-canonical-non-shaped-icon": "true"}, |
1802 | + summary: "Contacts", |
1803 | + body: "Synchronised contacts-database with cloud-storage.", |
1804 | + icon: "image://theme/contacts-app", |
1805 | + secondaryIcon: "", |
1806 | + actions: [], |
1807 | + summaryVisible: true, |
1808 | + bodyVisible: true, |
1809 | + iconVisible: true, |
1810 | + centeredIconVisible: false, |
1811 | + shaped: false, |
1812 | + secondaryIconVisible: false, |
1813 | + buttonRowVisible: false, |
1814 | + buttonTinted: false, |
1815 | + hasSound: false, |
1816 | + valueVisible: false, |
1817 | + valueLabelVisible: false, |
1818 | + valueTinted: false |
1819 | + }, |
1820 | + { |
1821 | + tag: "Confirmation notification with value", |
1822 | + type: Notification.Confirmation, |
1823 | + hints: {"x-canonical-non-shaped-icon": "true"}, |
1824 | + summary: "", |
1825 | + body: "", |
1826 | + icon: "image://theme/audio-volume-medium", |
1827 | + secondaryIcon: "", |
1828 | + value: 50, |
1829 | + actions: [], |
1830 | + summaryVisible: false, |
1831 | + bodyVisible: false, |
1832 | + iconVisible: false, |
1833 | + centeredIconVisible: true, |
1834 | + shaped: false, |
1835 | + secondaryIconVisible: false, |
1836 | + buttonRowVisible: false, |
1837 | + buttonTinted: false, |
1838 | + hasSound: false, |
1839 | + valueVisible: true, |
1840 | + valueLabelVisible: false, |
1841 | + valueTinted: false |
1842 | + }, |
1843 | + { |
1844 | + tag: "Confirmation notification with value, label and tint", |
1845 | + type: Notification.Confirmation, |
1846 | + hints: {"x-canonical-non-shaped-icon": "true", |
1847 | + "x-canonical-value-bar-tint" : "true"}, |
1848 | + summary: "", |
1849 | + body: "High Volume", |
1850 | + icon: "image://theme/audio-volume-high", |
1851 | + secondaryIcon: "", |
1852 | + value: 85, |
1853 | + actions: [], |
1854 | + summaryVisible: false, |
1855 | + bodyVisible: false, |
1856 | + iconVisible: false, |
1857 | + centeredIconVisible: true, |
1858 | + shaped: false, |
1859 | + secondaryIconVisible: false, |
1860 | + buttonRowVisible: false, |
1861 | + buttonTinted: false, |
1862 | + hasSound: false, |
1863 | + valueVisible: true, |
1864 | + valueLabelVisible: true, |
1865 | + valueTinted: true |
1866 | + } |
1867 | + ] |
1868 | + } |
1869 | + |
1870 | + SignalSpy { |
1871 | + id: clickThroughSpy |
1872 | + |
1873 | + target: clickThroughCatcher |
1874 | + signalName: "clicked" |
1875 | + } |
1876 | + |
1877 | + SignalSpy { |
1878 | + id: actionSpy |
1879 | + |
1880 | + target: mockModel |
1881 | + signalName: "actionInvoked" |
1882 | + } |
1883 | + |
1884 | + function cleanup() { |
1885 | + clickThroughSpy.clear() |
1886 | actionSpy.clear() |
1887 | - waitForRendering(notification) |
1888 | - |
1889 | - // check if there's a ComboButton created due to more actions being passed |
1890 | - if (data.actions.length > 2) { |
1891 | - var comboButton = findChild(notification, "notify_button2") |
1892 | - tryCompareFunction(function() { return comboButton.expanded == false; }, true); |
1893 | - |
1894 | - // click to expand |
1895 | - tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == true; }, true); |
1896 | - |
1897 | - // try clicking on choices in expanded comboList |
1898 | - var choiceButton1 = findChild(notification, "notify_button3") |
1899 | - tryCompareFunction(function() { mouseClick(choiceButton1, choiceButton1.width / 2, choiceButton1.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1900 | - compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1") |
1901 | - actionSpy.clear() |
1902 | - |
1903 | - var choiceButton2 = findChild(notification, "notify_button4") |
1904 | - tryCompareFunction(function() { mouseClick(choiceButton2, choiceButton2.width / 2, choiceButton2.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1905 | - compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2") |
1906 | - actionSpy.clear() |
1907 | - |
1908 | - // click to collapse |
1909 | - //tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == false; }, true); |
1910 | - } else { |
1911 | - mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2) |
1912 | - compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action") |
1913 | + } |
1914 | + |
1915 | + function test_NotificationRenderer(data) { |
1916 | + // populate model with some mock notifications |
1917 | + mockModel.append(data) |
1918 | + |
1919 | + // make sure the view is properly updated before going on |
1920 | + notifications.forceLayout(); |
1921 | + waitForRendering(notifications); |
1922 | + |
1923 | + var notification = findChild(notifications, "notification" + (mockModel.count - 1)) |
1924 | + verify(notification !== undefined, "notification wasn't found"); |
1925 | + |
1926 | + waitForRendering(notification); |
1927 | + |
1928 | + var icon = findChild(notification, "icon") |
1929 | + var centeredIcon = findChild(notification, "centeredIcon") |
1930 | + var interactiveArea = findChild(notification, "interactiveArea") |
1931 | + var secondaryIcon = findChild(notification, "secondaryIcon") |
1932 | + var summaryLabel = findChild(notification, "summaryLabel") |
1933 | + var bodyLabel = findChild(notification, "bodyLabel") |
1934 | + var buttonRow = findChild(notification, "buttonRow") |
1935 | + var valueIndicator = findChild(notification, "valueIndicator") |
1936 | + var valueLabel = findChild(notification, "valueLabel") |
1937 | + var innerBar = findChild(notification, "innerBar") |
1938 | + |
1939 | + compare(icon.visible, data.iconVisible, "avatar-icon visibility is incorrect") |
1940 | + if (icon.visible) { |
1941 | + compare(icon.shaped, data.shaped, "shaped-status is incorrect") |
1942 | + } |
1943 | + compare(centeredIcon.visible, data.centeredIconVisible, "centered-icon visibility is incorrect") |
1944 | + if (centeredIcon.visible) { |
1945 | + compare(centeredIcon.shaped, data.shaped, "shaped-status is incorrect") |
1946 | + } |
1947 | + compare(valueIndicator.visible, data.valueVisible, "value-indicator visibility is incorrect") |
1948 | + if (valueIndicator.visible) { |
1949 | + verify(innerBar.color === data.valueTinted ? UbuntuColors.orange : "white", "value-bar has the wrong color-tint") |
1950 | + } |
1951 | + compare(valueLabel.visible, data.valueLabelVisible, "value-label visibility is incorrect") |
1952 | + |
1953 | + // test input does not fall through |
1954 | + mouseClick(notification, notification.width / 2, notification.height / 2) |
1955 | + if(data.type == Notification.Interactive) { |
1956 | + actionSpy.wait() |
1957 | + compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action") |
1958 | + } |
1959 | + compare(clickThroughSpy.count, 0, "click on notification fell through") |
1960 | + |
1961 | + compare(secondaryIcon.visible, data.secondaryIconVisible, "secondary-icon visibility is incorrect") |
1962 | + compare(summaryLabel.visible, data.summaryVisible, "summary-text visibility is incorrect") |
1963 | + compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect") |
1964 | + compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect") |
1965 | + |
1966 | + var audioItem = findInvisibleChild(notification, "sound") |
1967 | + compare(audioItem.playbackState, data.hasSound ? Audio.PlayingState : Audio.StoppedState, "Audio has wrong state") |
1968 | + |
1969 | + if(data.buttonRowVisible) { |
1970 | + var buttonCancel = findChild(buttonRow, "notify_button1") |
1971 | + var buttonAccept = findChild(buttonRow, "notify_button0") |
1972 | + |
1973 | + // only test the left/cancel-button if two actions have been passed in |
1974 | + if (data.actions.length == 2) { |
1975 | + tryCompareFunction(function() { mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1976 | + compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action") |
1977 | + actionSpy.clear() |
1978 | + } |
1979 | + |
1980 | + // check the tinting of the positive/right button |
1981 | + verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint") |
1982 | + |
1983 | + // click the positive/right button |
1984 | + tryCompareFunction(function() { mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
1985 | + compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action") |
1986 | + actionSpy.clear() |
1987 | + waitForRendering (notification) |
1988 | + |
1989 | + // check if there's a ComboButton created due to more actions being passed |
1990 | + if (data.actions.length > 2) { |
1991 | + var comboButton = findChild(notification, "notify_button2") |
1992 | + tryCompareFunction(function() { return comboButton.expanded == false; }, true); |
1993 | + |
1994 | + // click to expand |
1995 | + tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == true; }, true); |
1996 | + |
1997 | + // try clicking on choices in expanded comboList |
1998 | + var choiceButton1 = findChild(notification, "notify_button3") |
1999 | + tryCompareFunction(function() { mouseClick(choiceButton1, choiceButton1.width / 2, choiceButton1.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
2000 | + compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1") |
2001 | + actionSpy.clear() |
2002 | + |
2003 | + var choiceButton2 = findChild(notification, "notify_button4") |
2004 | + tryCompareFunction(function() { mouseClick(choiceButton2, choiceButton2.width / 2, choiceButton2.height / 2); return actionSpy.signalArguments.length > 0; }, true); |
2005 | + compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2") |
2006 | + actionSpy.clear() |
2007 | + |
2008 | + // click to collapse |
2009 | + //tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == false; }, true); |
2010 | + } else { |
2011 | + mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2) |
2012 | + compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action") |
2013 | + } |
2014 | } |
2015 | } |
2016 | } |
2017 | |
2018 | === added file 'tests/qmltests/Notifications/tst_SwipeToAct.qml' |
2019 | --- tests/qmltests/Notifications/tst_SwipeToAct.qml 1970-01-01 00:00:00 +0000 |
2020 | +++ tests/qmltests/Notifications/tst_SwipeToAct.qml 2014-10-31 10:46:25 +0000 |
2021 | @@ -0,0 +1,276 @@ |
2022 | +/* |
2023 | + * Copyright (C) 2014 Canonical, Ltd. |
2024 | + * |
2025 | + * This program is free software; you can redistribute it and/or modify |
2026 | + * it under the terms of the GNU General Public License as published by |
2027 | + * the Free Software Foundation; version 3. |
2028 | + * |
2029 | + * This program is distributed in the hope that it will be useful, |
2030 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2031 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2032 | + * GNU General Public License for more details. |
2033 | + * |
2034 | + * You should have received a copy of the GNU General Public License |
2035 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2036 | + */ |
2037 | + |
2038 | +import QtQuick 2.0 |
2039 | +import QtTest 1.0 |
2040 | +import ".." |
2041 | +import "../../../qml/Notifications" |
2042 | +import Ubuntu.Components 0.1 |
2043 | +import Unity.Test 0.1 |
2044 | +import Unity.Notifications 1.0 |
2045 | + |
2046 | +Item { |
2047 | + width: notificationsRect.width + interactiveControls.width |
2048 | + height: notificationsRect.height |
2049 | + |
2050 | + Row { |
2051 | + id: rootRow |
2052 | + |
2053 | + Component { |
2054 | + id: mockNotification |
2055 | + |
2056 | + QtObject { |
2057 | + function invokeAction(actionId) { |
2058 | + mockModel.actionInvoked(actionId) |
2059 | + } |
2060 | + } |
2061 | + } |
2062 | + |
2063 | + ListModel { |
2064 | + id: mockModel |
2065 | + dynamicRoles: true |
2066 | + |
2067 | + signal actionInvoked(string actionId) |
2068 | + |
2069 | + function getRaw(id) { |
2070 | + return mockNotification.createObject(mockModel) |
2071 | + } |
2072 | + |
2073 | + // add the default/PlaceHolder notification to the model |
2074 | + Component.onCompleted: { |
2075 | + var n = { |
2076 | + type: Notification.PlaceHolder, |
2077 | + hints: {}, |
2078 | + summary: "", |
2079 | + body: "", |
2080 | + icon: "", |
2081 | + secondaryIcon: "", |
2082 | + actions: [] |
2083 | + } |
2084 | + |
2085 | + append(n) |
2086 | + } |
2087 | + } |
2088 | + |
2089 | + function addSwipeToActNotification() { |
2090 | + var n = { |
2091 | + type: Notification.SnapDecision, |
2092 | + hints: {"x-canonical-snap-decisions-swipe": "true"}, |
2093 | + summary: "Incoming call", |
2094 | + body: "Frank Zappa\n+44 (0)7736 027340", |
2095 | + icon: "../graphics/avatars/amanda.png", |
2096 | + secondaryIcon: "incoming-call", |
2097 | + actions: [{ id: "ok_id", label: "Ok"}, |
2098 | + { id: "cancel_id", label: "Cancel"}] |
2099 | + } |
2100 | + |
2101 | + mockModel.append(n) |
2102 | + } |
2103 | + |
2104 | + function clearNotifications() { |
2105 | + mockModel.clear() |
2106 | + } |
2107 | + |
2108 | + function remove1stNotification() { |
2109 | + if (mockModel.count > 0) |
2110 | + mockModel.remove(0) |
2111 | + } |
2112 | + |
2113 | + Rectangle { |
2114 | + id: notificationsRect |
2115 | + |
2116 | + width: units.gu(40) |
2117 | + height: units.gu(71) |
2118 | + |
2119 | + MouseArea{ |
2120 | + id: clickThroughCatcher |
2121 | + |
2122 | + anchors.fill: parent |
2123 | + } |
2124 | + |
2125 | + Notifications { |
2126 | + id: notifications |
2127 | + |
2128 | + margin: units.gu(1) |
2129 | + |
2130 | + anchors.fill: parent |
2131 | + model: mockModel |
2132 | + } |
2133 | + } |
2134 | + |
2135 | + Rectangle { |
2136 | + id: interactiveControls |
2137 | + |
2138 | + width: units.gu(30) |
2139 | + height: units.gu(81) |
2140 | + color: "grey" |
2141 | + |
2142 | + Column { |
2143 | + spacing: units.gu(1) |
2144 | + anchors.fill: parent |
2145 | + anchors.margins: units.gu(1) |
2146 | + |
2147 | + Button { |
2148 | + width: parent.width |
2149 | + text: "add a SwipeToAct snap-decision" |
2150 | + onClicked: rootRow.addSwipeToActNotification() |
2151 | + } |
2152 | + |
2153 | + Button { |
2154 | + width: parent.width |
2155 | + text: "remove 1st notification" |
2156 | + onClicked: rootRow.remove1stNotification() |
2157 | + } |
2158 | + |
2159 | + Button { |
2160 | + width: parent.width |
2161 | + text: "clear model" |
2162 | + onClicked: rootRow.clearNotifications() |
2163 | + } |
2164 | + } |
2165 | + } |
2166 | + |
2167 | + ActionModel { |
2168 | + id: myActionModel |
2169 | + } |
2170 | + |
2171 | + UnityTestCase { |
2172 | + id: root |
2173 | + name: "NotificationRendererTest" |
2174 | + when: windowShown |
2175 | + |
2176 | + function test_NotificationRenderer_data() { |
2177 | + return [ |
2178 | + { |
2179 | + tag: "Snap Decision with SwipeToAct-widget (accept)", |
2180 | + type: Notification.SnapDecision, |
2181 | + hints: {"x-canonical-snap-decisions-swipe": "true"}, |
2182 | + summary: "Incoming call", |
2183 | + body: "Frank Zappa\n+44 (0)7736 027340", |
2184 | + icon: "../graphics/avatars/amanda.png", |
2185 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
2186 | + actions: myActionModel, |
2187 | + summaryVisible: true, |
2188 | + bodyVisible: true, |
2189 | + iconVisible: true, |
2190 | + shaped: true, |
2191 | + secondaryIconVisible: true, |
2192 | + buttonRowVisible: true, |
2193 | + buttonTinted: false, |
2194 | + checkSwipeToActAccept: true, |
2195 | + checkSwipeToActReject: false |
2196 | + }, |
2197 | + { |
2198 | + tag: "Snap Decision with SwipeToAct-widget (reject)", |
2199 | + type: Notification.SnapDecision, |
2200 | + hints: {"x-canonical-snap-decisions-swipe": "true"}, |
2201 | + summary: "Incoming call", |
2202 | + body: "Bro Coly\n+49 (0)221 426973", |
2203 | + icon: "../graphics/avatars/funky.png", |
2204 | + secondaryIcon: "../graphics/applicationIcons/facebook.png", |
2205 | + actions: myActionModel, |
2206 | + summaryVisible: true, |
2207 | + bodyVisible: true, |
2208 | + iconVisible: true, |
2209 | + shaped: true, |
2210 | + secondaryIconVisible: true, |
2211 | + buttonRowVisible: true, |
2212 | + buttonTinted: false, |
2213 | + checkSwipeToActAccept: false, |
2214 | + checkSwipeToActReject: true |
2215 | + } |
2216 | + ] |
2217 | + } |
2218 | + |
2219 | + SignalSpy { |
2220 | + id: clickThroughSpy |
2221 | + |
2222 | + target: clickThroughCatcher |
2223 | + signalName: "clicked" |
2224 | + } |
2225 | + |
2226 | + SignalSpy { |
2227 | + id: actionSpy |
2228 | + |
2229 | + target: mockModel |
2230 | + signalName: "actionInvoked" |
2231 | + } |
2232 | + |
2233 | + function cleanup() { |
2234 | + clickThroughSpy.clear() |
2235 | + actionSpy.clear() |
2236 | + } |
2237 | + |
2238 | + function test_NotificationRenderer(data) { |
2239 | + // populate model with some mock notifications |
2240 | + mockModel.append(data) |
2241 | + |
2242 | + // make sure the view is properly updated before going on |
2243 | + notifications.forceLayout(); |
2244 | + waitForRendering(notifications); |
2245 | + |
2246 | + var notification = findChild(notifications, "notification" + (mockModel.count - 1)) |
2247 | + verify(notification !== undefined, "notification wasn't found"); |
2248 | + |
2249 | + waitForRendering(notification); |
2250 | + |
2251 | + var icon = findChild(notification, "icon") |
2252 | + var interactiveArea = findChild(notification, "interactiveArea") |
2253 | + var secondaryIcon = findChild(notification, "secondaryIcon") |
2254 | + var summaryLabel = findChild(notification, "summaryLabel") |
2255 | + var bodyLabel = findChild(notification, "bodyLabel") |
2256 | + var buttonRow = findChild(notification, "buttonRow") |
2257 | + |
2258 | + compare(icon.visible, data.iconVisible, "avatar-icon visibility is incorrect") |
2259 | + if (icon.visible) { |
2260 | + compare(icon.shaped, data.shaped, "shaped-status is incorrect") |
2261 | + } |
2262 | + |
2263 | + // test input does not fall through |
2264 | + mouseClick(notification, notification.width / 2, notification.height / 2) |
2265 | + if(data.type == Notification.Interactive) { |
2266 | + actionSpy.wait() |
2267 | + compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action") |
2268 | + } |
2269 | + compare(clickThroughSpy.count, 0, "click on notification fell through") |
2270 | + |
2271 | + compare(secondaryIcon.visible, data.secondaryIconVisible, "secondary-icon visibility is incorrect") |
2272 | + compare(summaryLabel.visible, data.summaryVisible, "summary-text visibility is incorrect") |
2273 | + compare(bodyLabel.visible, data.bodyVisible, "body-text visibility is incorrect") |
2274 | + compare(buttonRow.visible, data.buttonRowVisible, "button visibility is incorrect") |
2275 | + |
2276 | + if(data.buttonRowVisible) { |
2277 | + var swipeButton = findChild(buttonRow, "notify_swipe_button") |
2278 | + var slider = findChild(swipeButton, "slider") |
2279 | + var swipeMouseArea = findChild(swipeButton, "swipeMouseArea") |
2280 | + var x = swipeMouseArea.width / 2 |
2281 | + var y = swipeMouseArea.height / 2 |
2282 | + |
2283 | + if(data.checkSwipeToActReject) { |
2284 | + tryCompareFunction(function() { mouseDrag(slider, x, y, -(swipeMouseArea.width / 2), 0); return actionSpy.signalArguments.length > 0; }, true); |
2285 | + compare(actionSpy.signalArguments[0][0], data.actions.data(0, ActionModel.RoleActionId), "got wrong id for negative action") |
2286 | + actionSpy.clear() |
2287 | + } |
2288 | + if(data.checkSwipeToActAccept) { |
2289 | + tryCompareFunction(function() { mouseDrag(slider, x, y, (swipeMouseArea.width / 2) - slider.width, 0); return actionSpy.signalArguments.length > 0; }, true); |
2290 | + compare(actionSpy.signalArguments[0][0], data.actions.data(1, ActionModel.RoleActionId), "got wrong id for positive action") |
2291 | + actionSpy.clear() |
2292 | + } |
2293 | + } |
2294 | + } |
2295 | + } |
2296 | + } |
2297 | +} |
FAILED: Continuous integration, rev:1306 jenkins. qa.ubuntu. com/job/ unity8- ci/4758/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/6203/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- utopic/ 1744/console jenkins. qa.ubuntu. com/job/ unity8- utopic- amd64-ci/ 1854/console jenkins. qa.ubuntu. com/job/ unity8- utopic- i386-ci/ 1852/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/7455/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/4758/ rebuild
http://