Merge lp:~saviq/unity/phablet.notification-interface-tests into lp:unity/phablet

Proposed by Michał Sawicz
Status: Rejected
Rejected by: Michał Sawicz
Proposed branch: lp:~saviq/unity/phablet.notification-interface-tests
Merge into: lp:unity/phablet
Diff against target: 215 lines (+199/-0)
2 files modified
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/interfaces/tst_NotificationInterface.qml (+198/-0)
To merge this branch: bzr merge lp:~saviq/unity/phablet.notification-interface-tests
Reviewer Review Type Date Requested Status
Michał Sawicz Disapprove
PS Jenkins bot (community) continuous-integration Approve
Michi Henning Pending
Mirco Müller Pending
Jussi Pakkanen Pending
Thomas Voß architecture Pending
Michael Zanetti code Pending
Review via email: mp+155914@code.launchpad.net

Commit message

add Unity.Notifications interface tests

Description of the change

This is the first installment of our "let's drive the shell-facing interfaces with QML tests" approach.

This test is failing (hence skipped), but can be run by `make testNotificationInterface`, and is an acceptance factor for the Notifications backend.

Please look through to see if everything is clear and comment away.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Mirco Müller (macslow) wrote :

While the hint "synchronous" is implicitly know to be true, if a notification of Type.Confirmation is passed, we should still test for this particular hint.

Revision history for this message
Michał Sawicz (saviq) wrote :

I disagree, there's no value in passing that hint to the UI, it won't care about it, and if we move away from libnotify at some point, we'd have to artificially set that hint just for the sake of it being there.

Revision history for this message
kevin gunn (kgunn72) wrote :

maybe i'm early & this would be expected, but will there be additional failing tests added to determine what's valid? for instance, mutually exclusive typing enums, e.g. can a snap decision ever not have a button? or not contain text?...i would think not...e.g. its a requirement.

Revision history for this message
Michał Sawicz (saviq) wrote :

All the additional tests would happen on the C++ side. This set is only supposed to verify that the QML-exposed parts are working as expected.

Revision history for this message
Mirco Müller (macslow) wrote :

test_5_actions() should either check for Type.Interactive or have at least two actions defined. Going back to our discussion about the way how to define an interactive notification (and pass in the callback), we said we'd use actions too, but only a single one. Snap-decisions are meant to have at least two actions defined.

Revision history for this message
Michał Sawicz (saviq) wrote :

We have to balance out here, I'm not against adding such tests here, but then they have to be written as C++ tests anyway.

The idea is to have the smallest possible test suite in QML to ensure API is what we expect it to be. What, BTW, should happen when an app sends a SnapDecision with just one action? I know that's against the guidelines, but we might silently convert it to an Interactive notification.

BTW, what's the official naming? Ephemeral or Asynchronous?

522. By Michał Sawicz

rework most of the tests to fail, not only warn on mismatched interfaces

Revision history for this message
Michał Sawicz (saviq) wrote :

I reworked the tests to be a little more structured and a lot more robust.

523. By Michał Sawicz

fix comment

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
524. By Michał Sawicz

reorder the calls to wait for the dataChanged signal first, then verify the number of notifications

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Mirco Müller (macslow) wrote :

> We have to balance out here, I'm not against adding such tests here, but then
> they have to be written as C++ tests anyway.

I agree.

> The idea is to have the smallest possible test suite in QML to ensure API is
> what we expect it to be. What, BTW, should happen when an app sends a
> SnapDecision with just one action? I know that's against the guidelines, but
> we might silently convert it to an Interactive notification.

No, this could lead to odd side-effects in terms of behaviour. The request of a notification of a specific type should always be explicit. An interactive notification should always use the dedicated hint "x-canonical-switch-to-application". I agree that we can then allow the triggering application to pass the single action via the actions parameter. If an application issues a wrongly formed notification, the backend should simply reject it. We have 3rd-party developer documentation to educate people about such requirements. Of course these need to be updated once we're done with the new implementation to reflect all the additions and changes we made.

> BTW, what's the official naming? Ephemeral or Asynchronous?

"Ephemeral" is official. "Asynchronous" is the internal/legacy term.

525. By Michał Sawicz

make Notifications.Model a registered singleton instead of a context property

526. By Michał Sawicz

remove numbers from tests

527. By Michał Sawicz

add documentation for the tests

528. By Michał Sawicz

fix references to enumerations

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
529. By Michał Sawicz

fix two remaining test comments

530. By Michał Sawicz

two more comment fixes

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
531. By Michał Sawicz

fix enum references, verify there's no notifications on init

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Ending test functions with _data() has a special meaning in QML. While this might still work, its very confusing to someone who knows the meaning of _data() functions for tests. I'd vote for either removing the _data() or change it in a way that it actually makes use of that mechanism.

532. By Michał Sawicz

rename _data tests to avoid confusion with data-driven tests

Revision history for this message
Michał Sawicz (saviq) wrote :

Indeed, fixed.

533. By Michał Sawicz

merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

coding style: some lines are too long. I think we should strive for a maximum of around 90 chars so that having windows with code side-by-side is possible.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

147 + compare(repeater.itemAt(1).data.type, Notifications.Ephemeral, "the second notification should be of Ephemeral type");

Was that a typo?
s/Notifications.Ephemeral/Notifications.Type.Ephemeral

534. By Michał Sawicz

missed a .Type

535. By Michał Sawicz

wrap the code to 90 lines

Revision history for this message
Michał Sawicz (saviq) wrote :

Fixed on both accounts.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
536. By Michał Sawicz

merge trunk

537. By Michał Sawicz

add copyright header to tst_NotificationInterface.qml

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
538. By Michał Sawicz

add missing CMakeLists.txt

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

coding style: Wrapping lines at 90 chars makes half of my screen empty while making it clumsy to read being squeezed on the left side.

Jokes aside... I think all editors nowadays support automatically wrapping lines. But there is no editor that supports automatic removal of newlines even though there is plenty of space on the screen. Also we have screens with 2880x1800 pixels and 30 inches of space - as a developer, usually multiple of those side by side.

IMO we should not follow 1980's style guides and manually wrap lines.

Revision history for this message
Michi Henning (michihenning) wrote :

I don't think this is an issue of technology. It's more about ergonomics. Long lines are harder to read than short ones. But I wouldn't get too obsessive about it. Somewhere around 120-130 columns is probably where things start to go out of hand, and two lines of 65 characters each would be easier to read.

Somewhere around 180 columns, we are definitely crossing over into insanity…

539. By Michał Sawicz

merge trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
540. By Michał Sawicz

merge trunk

541. By Michał Sawicz

relax column limit, don't expect Notification::completed to be available to QML, s/int/number/

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

This has now been "converted" to lp:~saviq/unity-api/add-shell-notifications-api for merging into the separate lp:unity-api project, and mock plugins implemented to make sure that these pass.

review: Disapprove

Unmerged revisions

541. By Michał Sawicz

relax column limit, don't expect Notification::completed to be available to QML, s/int/number/

540. By Michał Sawicz

merge trunk

539. By Michał Sawicz

merge trunk

538. By Michał Sawicz

add missing CMakeLists.txt

537. By Michał Sawicz

add copyright header to tst_NotificationInterface.qml

536. By Michał Sawicz

merge trunk

535. By Michał Sawicz

wrap the code to 90 lines

534. By Michał Sawicz

missed a .Type

533. By Michał Sawicz

merge trunk

532. By Michał Sawicz

rename _data tests to avoid confusion with data-driven tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/qmltests/CMakeLists.txt'
--- tests/qmltests/CMakeLists.txt 2013-04-22 09:57:23 +0000
+++ tests/qmltests/CMakeLists.txt 2013-04-22 12:17:29 +0000
@@ -27,6 +27,7 @@
27add_qml_test(Greeter Clock)27add_qml_test(Greeter Clock)
28add_qml_test(Panel IndicatorItem)28add_qml_test(Panel IndicatorItem)
29add_qml_test(utils/Unity/Test UnityTest)29add_qml_test(utils/Unity/Test UnityTest)
30add_qml_test(interfaces NotificationInterface NO_ADD_TEST NO_TARGETS)
3031
31set(qmltest_DEFAULT_TARGETS qmluitests qmltests)32set(qmltest_DEFAULT_TARGETS qmluitests qmltests)
32set(qmltest_DEFAULT_NO_ADD_TEST TRUE)33set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
3334
=== added directory 'tests/qmltests/interfaces'
=== added file 'tests/qmltests/interfaces/tst_NotificationInterface.qml'
--- tests/qmltests/interfaces/tst_NotificationInterface.qml 1970-01-01 00:00:00 +0000
+++ tests/qmltests/interfaces/tst_NotificationInterface.qml 2013-04-22 12:17:29 +0000
@@ -0,0 +1,198 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
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
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import QtTest 1.0
19import Unity.Notifications 0.1 as Notifications
20import Unity.Notifications.Mocks 0.1 as NotificationMocks
21
22TestCase {
23
24 NotificationMocks.Source {
25 id: source
26 }
27
28 Repeater {
29 id: repeater
30 model: Notifications.Model
31 delegate: Item {
32 property var data: model
33 property Repeater actionRepeater
34
35 actionRepeater: Repeater {
36 model: parent.data.actions
37 delegate: Item {
38 property var data: model
39 }
40 }
41 }
42 }
43
44 SignalSpy {
45 id: dataSpy
46 target: Notifications.Model
47 signalName: "dataChanged"
48 }
49
50 function initTestCase() {
51 Notifications.Model.source = source;
52 }
53
54 function init() {
55 Notifications.Model.confirmationPlaceholder = false;
56 tryCompare(repeater, "count", "0", "There should be no notifications")
57 }
58
59 function cleanup() {
60 // dismiss all Notifications
61 for (var i = 0; i < repeater.count; i++) {
62 repeater.itemAt(i).data.notification.dismissed()
63 }
64 dataSpy.clear()
65 }
66
67 /* make sure all the required types are registered */
68 function test_types() {
69 compare(typeof Notifications.Urgency.Low, "number",
70 "there should be an Urgency::Low enum");
71 compare(typeof Notifications.Urgency.Normal, "number",
72 "there should be an Urgency::Normal enum");
73 compare(typeof Notifications.Urgency.Critical, "number",
74 "there should be an Urgency::Critical enum");
75 compare(typeof Notifications.Type.Confirmation, "number",
76 "there should be a Type::Confirmation enum");
77 compare(typeof Notifications.Type.Ephemeral, "number",
78 "there should be a Type::Ephemeral enum");
79 compare(typeof Notifications.Type.Interactive, "number",
80 "there should be a Type::Interactive enum");
81 compare(typeof Notifications.Type.SnapDecision, "number",
82 "there should be a Type::SnapDecision enum");
83 compare(typeof Notifications.Type.Placeholder, "number",
84 "there should be a Type::Placeholder enum");
85 compare(typeof Notifications.Hint.ButtonTint, "number",
86 "there should be a Hint::ButtonTint enum");
87 compare(typeof Notifications.Hint.IconOnly, "number",
88 "there should be a Hint::IconOnly enum");
89 compare(typeof Notifications.Notification, "object",
90 "Notification should be a registered type");
91 compare(typeof Notifications.Action, "object",
92 "Action should be a registered type");
93 compare(typeof Notifications.Model, "object",
94 "Notifications.Model should be a registered singleton");
95 compare(typeof Notifications.Model.source, "object",
96 "Notifications.Model should have a source property");
97 compare(typeof Notifications.Model.confirmationPlaceholder, "boolean",
98 "Notifications.Model should have a confirmationPlaceholder property");
99 }
100
101 /* make sure all the required roles and methods of Notification are exposed */
102 function test_notification_members() {
103 source.send({
104 "type": Notifications.Type.Interactive,
105 });
106 tryCompare(repeater, "count", 1, "there should be one notification");
107
108 var data = repeater.itemAt(0).data;
109 compare(typeof data.type, "number",
110 "NotificationModel should expose a \"type\" role of type Type");
111 compare(typeof data.urgency, "number",
112 "NotificationModel should expose a \"urgency\" role of type Urgency");
113 compare(typeof data.id, "number",
114 "NotificationModel should expose a \"id\" role of type int");
115 compare(typeof data.summary, "string",
116 "NotificationModel should expose a \"summary\" role of type QString");
117 compare(typeof data.body, "string",
118 "NotificationModel should expose a \"body\" role of type QString");
119 compare(typeof data.value, "number",
120 "NotificationModel should expose a \"value\" role of type int");
121 compare(typeof data.icon, "object",
122 "NotificationModel should expose an \"icon\" role of type QUrl");
123 compare(typeof data.secondaryIcon, "object",
124 "NotificationModel should expose a \"secondaryIcon\" role of type QUrl");
125 compare(typeof data.actions, "object",
126 "NotificationModel should expose an \"actions\" role of type QQmlListProperty");
127 compare(typeof data.hints, "number",
128 "NotificationModel should expose a \"hints\" role of type Hints");
129 compare(typeof data.notification, "object",
130 "NotificationModel should expose a \"notification\" role of type Notification");
131
132 var notification = data.notification;
133 compare(typeof notification.dismissed, "function",
134 "Notification::dismissed should be a signal");
135 compare(typeof notification.onHovered, "function",
136 "Notification::onHovered should be a slot");
137 compare(typeof notification.onDisplayed, "function",
138 "Notification::onDisplayed should be a slot");
139 }
140
141 /* make sure all the required roles and methods of Action are exposed */
142 function test_action_members() {
143 source.send({
144 "type": Notifications.Type.Interactive,
145 "actions": [
146 {"label": "test"}
147 ]
148 });
149 tryCompare(repeater, "count", 1, "there should be one notification");
150
151 var data = repeater.itemAt(0).data;
152 data = repeater.itemAt(0).actionRepeater.itemAt(0).data;
153 compare(typeof data.label, "string",
154 "Notification::actions should expose a \"label\" role of type QString");
155 compare(typeof data.action, "object",
156 "Notification::actions should expose an \"action\" role of type Action");
157
158 var action = data.action;
159 compare(typeof action.invoke, "function", "Action::invoke should be a function");
160 }
161
162 /* make sure the model is empty by default */
163 function test_empty() {
164 tryCompare(repeater, "count", 0, "there should be no notifications");
165 }
166
167 /* make sure there is a placeholder item used as the first item when
168 confirmationPlaceholder is true and that any additional notification is added
169 after it */
170 function test_placeholder() {
171 Notifications.Model.confirmationPlaceholder = true;
172 tryCompare(repeater, "count", 1, "there should be one notification");
173 compare(repeater.itemAt(0).data.type, Notifications.Type.Placeholder,
174 "the notification should be of Placeholder type");
175 source.send({
176 "type": Notifications.Type.Ephemeral
177 })
178 tryCompare(repeater, "count", 2, "second notification was added");
179 compare(repeater.itemAt(0).data.type, Notifications.Type.Placeholder,
180 "the first notification should be of Placeholder type");
181 compare(repeater.itemAt(1).data.type, Notifications.Type.Ephemeral,
182 "the second notification should be of Ephemeral type");
183 }
184
185 /* make sure the placeholder item is updated with data incoming in a Confirmation
186 notification */
187 function test_confirmation() {
188 Notifications.Model.confirmationPlaceholder = true;
189 tryCompare(repeater, "count", 1, "there should be only one notification");
190 source.send({
191 "type": Notifications.Type.Confirmation
192 });
193 tryCompare(dataSpy, "count", 1, "notification data should have been updated");
194 compare(repeater.count, 1, "there should be only one notification");
195 compare(repeater.itemAt(0).type, Notifications.Type.Confirmation,
196 "the first notification should be of Confirmation type");
197 }
198}

Subscribers

People subscribed via source and target branches