Merge lp:~danilo/launchpad/bug-772754-other-subscribers-activity into lp:launchpad
- bug-772754-other-subscribers-activity
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Graham Binns |
Approved revision: | no longer in the source branch. |
Merged at revision: | 13243 |
Proposed branch: | lp:~danilo/launchpad/bug-772754-other-subscribers-activity |
Merge into: | lp:launchpad |
Prerequisite: | lp:~danilo/launchpad/bug-772754-other-subscribers-subscribers |
Diff against target: |
610 lines (+541/-3) 2 files modified
lib/lp/bugs/javascript/subscribers_list.js (+190/-2) lib/lp/bugs/javascript/tests/test_subscribers_list.js (+351/-1) |
To merge this branch: | bzr merge lp:~danilo/launchpad/bug-772754-other-subscribers-activity |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Graham Binns (community) | code | Approve | |
Review via email: mp+64180@code.launchpad.net |
Commit message
Description of the change
= Bug 772754: Other subscribers list, part 4 =
This is part of ongoing work for providing the "other subscribers" list as indicated in mockup https:/
This branch continues on the previous branches to provide methods to indicate either some global activity in the subscribers list (like "Loading subscribers") or some activity on a particular subscriber (eg. "Subscribing", "Unsubscribing", along with spinner).
It is comprehensively tested.
== Tests ==
lp/bugs/
== Demo and Q/A ==
N/A
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/
lib/lp/
Graham Binns (gmb) : | # |
Preview Diff
1 | === modified file 'lib/lp/bugs/javascript/subscribers_list.js' |
2 | --- lib/lp/bugs/javascript/subscribers_list.js 2011-06-15 11:08:30 +0000 |
3 | +++ lib/lp/bugs/javascript/subscribers_list.js 2011-06-15 11:08:35 +0000 |
4 | @@ -82,6 +82,9 @@ |
5 | list: 'subscribers-list', |
6 | subscriber: 'subscriber', |
7 | no_subscribers: 'no-subscribers-indicator', |
8 | + activity: 'global-activity-indicator', |
9 | + activity_text: 'global-activity-text', |
10 | + subscriber_activity: 'subscriber-activity-indicator', |
11 | actions: 'subscriber-actions', |
12 | unsubscribe: 'unsubscribe-action' |
13 | }; |
14 | @@ -152,12 +155,14 @@ |
15 | * of no subscribers. |
16 | * |
17 | * @method resetNoSubscribers |
18 | + * @param force_hide {Boolean} Whether to force hiding of the "no subscribers" |
19 | + * indication. |
20 | */ |
21 | -SubscribersList.prototype.resetNoSubscribers = function() { |
22 | +SubscribersList.prototype.resetNoSubscribers = function(force_hide) { |
23 | var has_sections = ( |
24 | this.container_node.one('.' + CSS_CLASSES.section) !== null); |
25 | var no_subs; |
26 | - if (has_sections) { |
27 | + if (has_sections || force_hide === true) { |
28 | // Make sure the indicator for no subscribers is not there. |
29 | no_subs = this.container_node.one('.' + CSS_CLASSES.no_subscribers); |
30 | if (no_subs !== null) { |
31 | @@ -172,6 +177,106 @@ |
32 | }; |
33 | |
34 | /** |
35 | + * Returns or creates a node for progress indication for the subscribers list. |
36 | + * |
37 | + * If node is not present, it is created and added to the beginning of |
38 | + * subscribers list container node. |
39 | + * |
40 | + * @method _ensureActivityNode |
41 | + * @return {Y.Node} A node with the spinner img node and a span text node. |
42 | + */ |
43 | +SubscribersList.prototype._ensureActivityNode = function() { |
44 | + var activity_node = this.container_node.one('.' + CSS_CLASSES.activity); |
45 | + if (activity_node === null) { |
46 | + activity_node = Y.Node.create('<div />') |
47 | + .addClass(CSS_CLASSES.activity); |
48 | + progress_icon = Y.Node.create('<img />') |
49 | + .set('src', '/@@/spinner'); |
50 | + activity_node.appendChild(progress_icon); |
51 | + activity_node.appendChild( |
52 | + Y.Node.create('<span />') |
53 | + .addClass(CSS_CLASSES.activity_text)); |
54 | + this.container_node.prepend(activity_node); |
55 | + } |
56 | + return activity_node; |
57 | +}; |
58 | + |
59 | +/** |
60 | + * Sets icon in the activity node to either 'error' or 'spinner' icon. |
61 | + * |
62 | + * @method _setActivityErrorIcon |
63 | + * @param node {Y.Node} An activity node as returned by _ensureActivityNode(). |
64 | + * @param error {Boolean} Whether to show an error icon. |
65 | + * Otherwise shows a spinner image. |
66 | + */ |
67 | +SubscribersList.prototype._setActivityErrorIcon = function(node, error) { |
68 | + var progress_icon = node.one('img'); |
69 | + if (error === true) { |
70 | + progress_icon.set('src', '/@@/error'); |
71 | + } else { |
72 | + progress_icon.set('src', '/@@/spinner'); |
73 | + } |
74 | +}; |
75 | + |
76 | +/** |
77 | + * Sets the activity text inside the activity node. |
78 | + * |
79 | + * @method _setActivityText |
80 | + * @param node {Y.Node} An activity node as returned by _ensureActivityNode(). |
81 | + * @param text {String} Description of the activity currently in progress. |
82 | + */ |
83 | +SubscribersList.prototype._setActivityText = function(node, text) { |
84 | + var text_node = node.one('.' + CSS_CLASSES.activity_text); |
85 | + text_node.set('text', ' ' + text); |
86 | +}; |
87 | + |
88 | +/** |
89 | + * Indicate some activity for the subscribers list with a progress spinner |
90 | + * and optionally some text. |
91 | + * |
92 | + * @method startActivity |
93 | + * @param text {String} Description of the action to indicate progress of. |
94 | + */ |
95 | +SubscribersList.prototype.startActivity = function(text) { |
96 | + // We don't ever want "No subscribers" to be shown when loading is in |
97 | + // progress. |
98 | + this.resetNoSubscribers(true); |
99 | + |
100 | + var activity_node = this._ensureActivityNode(); |
101 | + // Ensure the icon is back to the spinner. |
102 | + this._setActivityErrorIcon(activity_node, false); |
103 | + this._setActivityText(activity_node, text); |
104 | +}; |
105 | + |
106 | +/** |
107 | + * Stop any activity indication for the subscribers list and optionally |
108 | + * display an error message. |
109 | + * |
110 | + * @method stopActivity |
111 | + * @param error_text {String} Error message to display. If not a string, |
112 | + * it is considered that the operation was successful and no error |
113 | + * indication is added to the subscribers list. |
114 | + */ |
115 | +SubscribersList.prototype.stopActivity = function(error_text) { |
116 | + var activity_node = this.container_node.one('.' + CSS_CLASSES.activity); |
117 | + if (Y.Lang.isString(error_text)) { |
118 | + // There is an error message, keep the node visible with |
119 | + // the error message in. |
120 | + activity_node = this._ensureActivityNode(true); |
121 | + this._setActivityErrorIcon(activity_node, true); |
122 | + this._setActivityText(activity_node, error_text); |
123 | + this.resetNoSubscribers(true); |
124 | + } else { |
125 | + // No errors, remove the activity node if present. |
126 | + if (activity_node !== null) { |
127 | + activity_node.remove(); |
128 | + } |
129 | + // Restore "No subscribers" indication if needed. |
130 | + this.resetNoSubscribers(); |
131 | + } |
132 | +}; |
133 | + |
134 | +/** |
135 | * Get a CSS class to use for the section of the subscribers' list |
136 | * with subscriptions with the level `level`. |
137 | * |
138 | @@ -551,5 +656,88 @@ |
139 | this._removeSectionNodeIfEmpty(existing_section); |
140 | }; |
141 | |
142 | +/** |
143 | + * Indicates some activity for a subscriber in the subscribers list. |
144 | + * Uses a regular Launchpad progress spinner UI. |
145 | + * |
146 | + * If subscriber is not in the list already, it fails with an exception. |
147 | + * If there are any actions available for the subscriber (such as unsubscribe |
148 | + * action), they are hidden. |
149 | + * |
150 | + * @method indicateSubscriberActivity |
151 | + * @param subscriber {Object} Object containing at least `name` |
152 | + * for the subscriber. |
153 | + */ |
154 | +SubscribersList.prototype.indicateSubscriberActivity = function(subscriber) { |
155 | + var subscriber_node = this._getSubscriberNode(subscriber); |
156 | + var progress_node = subscriber_node.one( |
157 | + '.' + CSS_CLASSES.subscriber_activity); |
158 | + |
159 | + // No-op if there is already indication of progress, |
160 | + // and creates a new node with the spinner if there isn't. |
161 | + if (progress_node === null) { |
162 | + var actions_node = subscriber_node.one('.' + CSS_CLASSES.actions); |
163 | + if (actions_node !== null) { |
164 | + actions_node.setStyle('display', 'none'); |
165 | + } |
166 | + var progress_icon = Y.Node.create('<img />') |
167 | + .set('src', '/@@/spinner'); |
168 | + |
169 | + progress_node = Y.Node.create('<span />') |
170 | + .addClass(CSS_CLASSES.subscriber_activity) |
171 | + .setStyle('float', 'right'); |
172 | + progress_node.appendChild(progress_icon); |
173 | + subscriber_node.appendChild(progress_node); |
174 | + } |
175 | +}; |
176 | + |
177 | +/** |
178 | + * Stop any indication of activity for a subscriber in the subscribers list. |
179 | + * |
180 | + * If the spinner is present, it removes it. If `success` parameter is |
181 | + * passed in, it determines if success or failure animation will be shown |
182 | + * as well. |
183 | + * |
184 | + * If subscriber is not in the list already, it fails with an exception. |
185 | + * If there are any actions available for the subscriber (such as unsubscribe |
186 | + * action), they are re-displayed if hidden. |
187 | + * |
188 | + * @method stopSubscriberActivity |
189 | + * @param subscriber {Object} Object containing at least `name` |
190 | + * for the subscriber. |
191 | + * @param success {Boolean} Whether to indicate success (`success` == true, |
192 | + * flash green) or failure (false, red). Otherwise, perform no |
193 | + * animation. |
194 | + * @param callback {Function} Function to call if and when success/failure |
195 | + * animation completes. |
196 | + */ |
197 | +SubscribersList.prototype.stopSubscriberActivity = function(subscriber, |
198 | + success, |
199 | + callback) { |
200 | + var subscriber_node = this._getSubscriberNode(subscriber); |
201 | + var progress_node = subscriber_node.one( |
202 | + '.' + CSS_CLASSES.subscriber_activity); |
203 | + if (progress_node !== null) { |
204 | + // Remove and destroy the node if present. |
205 | + progress_node.remove(true); |
206 | + } |
207 | + // If actions node is present and hidden, show it. |
208 | + var actions_node = subscriber_node.one('.' + CSS_CLASSES.actions); |
209 | + if (actions_node !== null) { |
210 | + actions_node.setStyle('display', 'inline'); |
211 | + } |
212 | + |
213 | + if (success === true || success === false) { |
214 | + var anim; |
215 | + if (success === true) { |
216 | + anim = Y.lazr.anim.green_flash({ node: subscriber_node }); |
217 | + } else { |
218 | + anim = Y.lazr.anim.red_flash({ node: subscriber_node }); |
219 | + } |
220 | + anim.on('end', callback); |
221 | + anim.run(); |
222 | + } |
223 | +}; |
224 | + |
225 | |
226 | }, "0.1", {"requires": ["node", "lazr.anim", "lp.client", "lp.names"]}); |
227 | |
228 | === modified file 'lib/lp/bugs/javascript/tests/test_subscribers_list.js' |
229 | --- lib/lp/bugs/javascript/tests/test_subscribers_list.js 2011-06-15 11:08:30 +0000 |
230 | +++ lib/lp/bugs/javascript/tests/test_subscribers_list.js 2011-06-15 11:08:35 +0000 |
231 | @@ -430,6 +430,29 @@ |
232 | no_subs_nodes.item(0).get('text')); |
233 | }, |
234 | |
235 | + test_no_subscribers_force_hide: function() { |
236 | + // When resetNoSubscribers() is called on an empty |
237 | + // SubscribersList but with force_hide parameter set to true, |
238 | + // indication of no subscribers is not added. |
239 | + var subscribers_list = setUpSubscribersList(this.root); |
240 | + subscribers_list.resetNoSubscribers(true); |
241 | + var no_subs_nodes = this.root.all( |
242 | + '.no-subscribers-indicator'); |
243 | + Y.Assert.areEqual(0, no_subs_nodes.size()); |
244 | + }, |
245 | + |
246 | + test_no_subscribers_force_hide_removal: function() { |
247 | + // When resetNoSubscribers() is called on an empty |
248 | + // SubscribersList which already has a no-subscribers |
249 | + // indication shown, it is removed. |
250 | + var subscribers_list = setUpSubscribersList(this.root); |
251 | + subscribers_list.resetNoSubscribers(); |
252 | + subscribers_list.resetNoSubscribers(true); |
253 | + var no_subs_nodes = this.root.all( |
254 | + '.no-subscribers-indicator'); |
255 | + Y.Assert.areEqual(0, no_subs_nodes.size()); |
256 | + }, |
257 | + |
258 | test_subscribers_no_addition: function() { |
259 | // When resetNoSubscribers() is called on a SubscribersList |
260 | // with some subscribers, no indication of no subscribers is added. |
261 | @@ -474,6 +497,184 @@ |
262 | |
263 | |
264 | /** |
265 | + * Test activity/progress indication for the entire subscribers list. |
266 | + */ |
267 | +suite.add(new Y.Test.Case({ |
268 | + name: 'SubscribersList.startActivity() and stopActivity() test', |
269 | + |
270 | + _should: { |
271 | + error: { |
272 | + test_setActivityErrorIcon_error: true, |
273 | + test_setActivityText_error: true |
274 | + } |
275 | + }, |
276 | + |
277 | + setUp: function() { |
278 | + this.root = Y.Node.create('<div />'); |
279 | + Y.one('body').appendChild(this.root); |
280 | + }, |
281 | + |
282 | + tearDown: function() { |
283 | + this.root.remove(); |
284 | + }, |
285 | + |
286 | + test_ensureActivityNode: function() { |
287 | + // With no activity node present, one is created and put |
288 | + // into the subscribers list container node. |
289 | + var subscribers_list = setUpSubscribersList(this.root); |
290 | + var node = subscribers_list._ensureActivityNode(); |
291 | + Y.Assert.isNotNull(node); |
292 | + Y.Assert.isTrue(node.hasClass('global-activity-indicator')); |
293 | + Y.Assert.areSame( |
294 | + subscribers_list.container_node, node.get('parentNode')); |
295 | + }, |
296 | + |
297 | + test_ensureActivityNode_contents: function() { |
298 | + // Created node contains an img tag with the spinner icon |
299 | + // and a span tag for the text. |
300 | + var subscribers_list = setUpSubscribersList(this.root); |
301 | + var node = subscribers_list._ensureActivityNode(); |
302 | + var icon = node.one('img'); |
303 | + Y.Assert.isNotNull(icon); |
304 | + Y.Assert.areEqual('file:///@@/spinner', icon.get('src')); |
305 | + var text = node.one('span'); |
306 | + Y.Assert.isNotNull(text); |
307 | + Y.Assert.isTrue(text.hasClass('global-activity-text')); |
308 | + }, |
309 | + |
310 | + test_ensureActivityNode_existing: function() { |
311 | + // When activity node already exists, it is returned |
312 | + // and no new one is created. |
313 | + var subscribers_list = setUpSubscribersList(this.root); |
314 | + var existing_node = subscribers_list._ensureActivityNode(); |
315 | + var new_node = subscribers_list._ensureActivityNode(); |
316 | + Y.Assert.areSame(existing_node, new_node); |
317 | + Y.Assert.areEqual( |
318 | + 1, |
319 | + subscribers_list |
320 | + .container_node |
321 | + .all('.global-activity-indicator') |
322 | + .size()); |
323 | + }, |
324 | + |
325 | + test_setActivityErrorIcon_error_icon: function() { |
326 | + // With the activity node passed in, error icon is set |
327 | + // when desired. |
328 | + var subscribers_list = setUpSubscribersList(this.root); |
329 | + var node = subscribers_list._ensureActivityNode(); |
330 | + var icon_node = node.one('img'); |
331 | + subscribers_list._setActivityErrorIcon(node, true); |
332 | + Y.Assert.areEqual('file:///@@/error', icon_node.get('src')); |
333 | + }, |
334 | + |
335 | + test_setActivityErrorIcon_spinner_icon: function() { |
336 | + // With the activity node passed in, spinner icon is restored |
337 | + // when requested (error parameter !== true). |
338 | + var subscribers_list = setUpSubscribersList(this.root); |
339 | + var node = subscribers_list._ensureActivityNode(); |
340 | + var icon_node = node.one('img'); |
341 | + subscribers_list._setActivityErrorIcon(node, false); |
342 | + Y.Assert.areEqual('file:///@@/spinner', icon_node.get('src')); |
343 | + }, |
344 | + |
345 | + test_setActivityErrorIcon_error: function() { |
346 | + // With non-activity node passed in, it fails. |
347 | + var subscribers_list = setUpSubscribersList(this.root); |
348 | + var node = Y.Node.create('<div />'); |
349 | + subscribers_list._setActivityErrorIcon(node, true); |
350 | + }, |
351 | + |
352 | + test_setActivityText: function() { |
353 | + // With activity node and text passed in, proper |
354 | + // text is set in the activity text node. |
355 | + var subscribers_list = setUpSubscribersList(this.root); |
356 | + var node = subscribers_list._ensureActivityNode(); |
357 | + subscribers_list._setActivityText(node, "Blah"); |
358 | + // Single whitespace is prepended to better separate |
359 | + // icon from the text. |
360 | + Y.Assert.areEqual(" Blah", node.one('span').get('text')); |
361 | + }, |
362 | + |
363 | + test_setActivityText_error: function() { |
364 | + // With non-activity node passed in, it fails. |
365 | + var subscribers_list = setUpSubscribersList(this.root); |
366 | + var node = Y.Node.create('<div />'); |
367 | + subscribers_list._setActivityText(node, "Blah"); |
368 | + }, |
369 | + |
370 | + test_startActivity: function() { |
371 | + // startActivity adds the spinner icon and sets the appropriate text. |
372 | + var subscribers_list = setUpSubscribersList(this.root); |
373 | + subscribers_list.startActivity("Blah"); |
374 | + |
375 | + var node = subscribers_list._ensureActivityNode(); |
376 | + |
377 | + Y.Assert.areEqual('file:///@@/spinner', node.one('img').get('src')); |
378 | + Y.Assert.areEqual(" Blah", node.one('span').get('text')); |
379 | + }, |
380 | + |
381 | + test_startActivity_restores_state: function() { |
382 | + // startActivity removes the no-subscribers indicator if present |
383 | + // and restores the activity node icon. |
384 | + var subscribers_list = setUpSubscribersList(this.root); |
385 | + // Add a no-subscribers indication. |
386 | + subscribers_list.resetNoSubscribers(); |
387 | + // Create an activity node and set the error icon. |
388 | + var node = subscribers_list._ensureActivityNode(); |
389 | + subscribers_list._setActivityErrorIcon(node, true); |
390 | + |
391 | + // Call startActivity() and see how it restores everything. |
392 | + subscribers_list.startActivity(); |
393 | + Y.Assert.areEqual('file:///@@/spinner', node.one('img').get('src')); |
394 | + Y.Assert.isNull( |
395 | + subscribers_list.container_node.one('.no-subscribers-indicator')); |
396 | + }, |
397 | + |
398 | + test_stopActivity: function() { |
399 | + // stopActivity without parameters assumes a successful completion |
400 | + // of the activity, so it removes the activity node and restores |
401 | + // no-subscribers indication if needed. |
402 | + var subscribers_list = setUpSubscribersList(this.root); |
403 | + subscribers_list.startActivity("Blah"); |
404 | + subscribers_list.stopActivity(); |
405 | + |
406 | + var node = subscribers_list.container_node.one( |
407 | + '.global-activity-indicator'); |
408 | + Y.Assert.isNull(node); |
409 | + // Indication of no subscribers is restored. |
410 | + Y.Assert.isNotNull( |
411 | + subscribers_list.container_node.one('.no-subscribers-indicator')); |
412 | + }, |
413 | + |
414 | + test_stopActivity_noop: function() { |
415 | + // stopActivity without parameters assumes a successful completion |
416 | + // of the activity. If no activity was in progress, nothing happens. |
417 | + var subscribers_list = setUpSubscribersList(this.root); |
418 | + subscribers_list.stopActivity(); |
419 | + |
420 | + var node = subscribers_list.container_node.one( |
421 | + '.global-activity-indicator'); |
422 | + Y.Assert.isNull(node); |
423 | + }, |
424 | + |
425 | + test_stopActivity_with_error_message: function() { |
426 | + // stopActivity with error message passed in creates an activity |
427 | + // node even if activity was not in progress and sets the error |
428 | + // icon and error text to the passed in message.. |
429 | + var subscribers_list = setUpSubscribersList(this.root); |
430 | + subscribers_list.stopActivity("Problem!"); |
431 | + var node = subscribers_list._ensureActivityNode(); |
432 | + Y.Assert.areEqual('file:///@@/error', node.one('img').get('src')); |
433 | + Y.Assert.areEqual(" Problem!", node.one('span').get('text')); |
434 | + |
435 | + // Indication of no subscribers is not added. |
436 | + Y.Assert.isNull( |
437 | + subscribers_list.container_node.one('.no-subscribers-indicator')); |
438 | + } |
439 | +})); |
440 | + |
441 | + |
442 | +/** |
443 | * Function to get a list of all the sections present in the |
444 | * subscribers_list (a SubscribersList object). |
445 | */ |
446 | @@ -815,7 +1016,6 @@ |
447 | })); |
448 | |
449 | |
450 | - |
451 | /** |
452 | * Test adding of subscribers and relevant helper methods. |
453 | */ |
454 | @@ -1235,6 +1435,156 @@ |
455 | })); |
456 | |
457 | |
458 | +/** |
459 | + * Test showing/stopping indication of activity for a subscriber. |
460 | + */ |
461 | +suite.add(new Y.Test.Case({ |
462 | + name: 'SubscribersList.indicateSubscriberActivity() and ' + |
463 | + 'SubscribersList.stopSubscriberActivity() test', |
464 | + |
465 | + setUp: function() { |
466 | + this.root = Y.Node.create('<div />'); |
467 | + Y.one('body').appendChild(this.root); |
468 | + }, |
469 | + |
470 | + tearDown: function() { |
471 | + this.root.remove(); |
472 | + }, |
473 | + |
474 | + _should: { |
475 | + error: { |
476 | + test_indicateSubscriberActivity_error: |
477 | + new Error('Subscriber is not present in the subscribers list. ' + |
478 | + 'Please call addSubscriber(subscriber) first.'), |
479 | + test_stopSubscriberActivity_error: |
480 | + new Error('Subscriber is not present in the subscribers list. ' + |
481 | + 'Please call addSubscriber(subscriber) first.') |
482 | + } |
483 | + }, |
484 | + |
485 | + test_indicateSubscriberActivity_error: function() { |
486 | + // When subscriber is not in the list, fails with an exception. |
487 | + var subscribers_list = setUpSubscribersList(this.root); |
488 | + var subscriber = { name: 'user' }; |
489 | + subscribers_list.indicateSubscriberActivity(subscriber); |
490 | + }, |
491 | + |
492 | + test_indicateSubscriberActivity_node: function() { |
493 | + // Creates a node with spinner image in it. |
494 | + var subscribers_list = setUpSubscribersList(this.root); |
495 | + var subscriber = { name: 'user' }; |
496 | + var node = subscribers_list.addSubscriber(subscriber, 'Details'); |
497 | + subscribers_list.indicateSubscriberActivity(subscriber); |
498 | + |
499 | + // This is the created node. |
500 | + var progress_node = node.one('.subscriber-activity-indicator'); |
501 | + Y.Assert.isNotNull(progress_node); |
502 | + var progress_icon = progress_node.one('img'); |
503 | + // We get an absolute URI, instead of the relative one which |
504 | + // the code sets. Since the test runs from the local file system, |
505 | + // that means "file://". |
506 | + Y.Assert.areEqual('file:///@@/spinner', progress_icon.get('src')); |
507 | + }, |
508 | + |
509 | + test_indicateSubscriberActivity_actions_hidden: function() { |
510 | + // If there are any actions (in an actions node), they are |
511 | + // all hidden. |
512 | + var subscribers_list = setUpSubscribersList(this.root); |
513 | + var subscriber = { name: 'user' }; |
514 | + var node = subscribers_list.addSubscriber(subscriber, 'Details'); |
515 | + var actions_node = subscribers_list._getOrCreateActionsNode(node); |
516 | + |
517 | + subscribers_list.indicateSubscriberActivity(subscriber); |
518 | + Y.Assert.areEqual('none', actions_node.getStyle('display')); |
519 | + }, |
520 | + |
521 | + test_stopSubscriberActivity_error: function() { |
522 | + // When subscriber is not in the list, fails with an exception. |
523 | + var subscribers_list = setUpSubscribersList(this.root); |
524 | + var subscriber = { name: 'user' }; |
525 | + subscribers_list.stopSubscriberActivity(subscriber); |
526 | + }, |
527 | + |
528 | + test_stopSubscriberActivity_noop: function() { |
529 | + // When there's no activity in progress, nothing happens. |
530 | + var subscribers_list = setUpSubscribersList(this.root); |
531 | + var subscriber = { name: 'user' }; |
532 | + var node = subscribers_list.addSubscriber(subscriber, 'Details'); |
533 | + subscribers_list.stopSubscriberActivity(subscriber); |
534 | + }, |
535 | + |
536 | + test_stopSubscriberActivity_spinner_removed: function() { |
537 | + // When there is some activity in progress, spinner is removed. |
538 | + var subscribers_list = setUpSubscribersList(this.root); |
539 | + var subscriber = { name: 'user' }; |
540 | + var node = subscribers_list.addSubscriber(subscriber, 'Details'); |
541 | + // Create the spinner. |
542 | + subscribers_list.indicateSubscriberActivity(subscriber); |
543 | + // And remove it. |
544 | + subscribers_list.stopSubscriberActivity(subscriber); |
545 | + Y.Assert.isNull(node.one('.subscriber-activity-indicator')); |
546 | + }, |
547 | + |
548 | + test_stopSubscriberActivity_actions_restored: function() { |
549 | + // When there is some activity in progress, spinner is removed. |
550 | + var subscribers_list = setUpSubscribersList(this.root); |
551 | + var subscriber = { name: 'user' }; |
552 | + var node = subscribers_list.addSubscriber(subscriber, 'Details'); |
553 | + var actions_node = subscribers_list._getOrCreateActionsNode(node); |
554 | + // Hide actions. |
555 | + actions_node.setStyle('display', 'none'); |
556 | + // And restore actions. |
557 | + subscribers_list.stopSubscriberActivity(subscriber); |
558 | + Y.Assert.areEqual('inline', actions_node.getStyle('display')); |
559 | + }, |
560 | + |
561 | + test_stopSubscriberActivity_success_callback: function() { |
562 | + // When we are indicating successful/failed operation, |
563 | + // green_flash/red_flash animation is executed and callback |
564 | + // function is called when it ends. |
565 | + var subscribers_list = setUpSubscribersList(this.root); |
566 | + var subscriber = { name: 'user' }; |
567 | + subscribers_list.addSubscriber(subscriber, 'Details'); |
568 | + var callback_called = false; |
569 | + var callback = function() { |
570 | + callback_called = true; |
571 | + }; |
572 | + |
573 | + subscribers_list.stopSubscriberActivity( |
574 | + subscriber, true, callback); |
575 | + // Callback is not called immediatelly. |
576 | + Y.Assert.isFalse(callback_called); |
577 | + this.wait(function() { |
578 | + // But after waiting for animation to complete, |
579 | + // callback is called. |
580 | + Y.Assert.isTrue(callback_called); |
581 | + }, 1100); |
582 | + }, |
583 | + |
584 | + test_stopSubscriberActivity_no_callback: function() { |
585 | + // When we pass the callback in, but success is neither |
586 | + // 'true' nor 'false', callback is not called. |
587 | + var subscribers_list = setUpSubscribersList(this.root); |
588 | + var subscriber = { name: 'user' }; |
589 | + subscribers_list.addSubscriber(subscriber, 'Details'); |
590 | + var callback_called = false; |
591 | + var callback = function() { |
592 | + callback_called = true; |
593 | + }; |
594 | + |
595 | + subscribers_list.stopSubscriberActivity( |
596 | + subscriber, "no-callback", callback); |
597 | + // Callback is not called. |
598 | + Y.Assert.isFalse(callback_called); |
599 | + this.wait(function() { |
600 | + // Nor is it called after any potential animations complete. |
601 | + Y.Assert.isFalse(callback_called); |
602 | + }, 1100); |
603 | + } |
604 | + |
605 | +})); |
606 | + |
607 | + |
608 | var handle_complete = function(data) { |
609 | window.status = '::::' + JSON.stringify(data); |
610 | }; |