Merge lp:~rharding/launchpad/lpclient_fix into lp:launchpad
- lpclient_fix
- Merge into devel
Status: | Merged |
---|---|
Approved by: | j.c.sackett |
Approved revision: | no longer in the source branch. |
Merged at revision: | 15685 |
Proposed branch: | lp:~rharding/launchpad/lpclient_fix |
Merge into: | lp:launchpad |
Prerequisite: | lp:~rharding/launchpad/garden_client |
Diff against target: |
1471 lines (+651/-597) 6 files modified
lib/lp/app/javascript/client.js (+63/-55) lib/lp/app/javascript/tests/test_lp_client.html (+0/-6) lib/lp/app/javascript/tests/test_lp_client.js (+583/-518) lib/lp/app/javascript/tests/test_lp_client_integration.js (+2/-15) lib/lp/registry/javascript/tests/test_structural_subscription.js (+1/-1) lib/lp/soyuz/javascript/lp_dynamic_dom_updater.js (+2/-2) |
To merge this branch: | bzr merge lp:~rharding/launchpad/lpclient_fix |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
j.c.sackett (community) | Approve | ||
Review via email:
|
Commit message
Fix client.js to maintain uri on PATCH requests so that web_link:changed event fires off LP.cache updates.
Description of the change
= Summary =
Fixes bug #1004248 introduced by attempting to fix bug #911973. That fix only
considered named_post/get methods and not patch methods.
== Pre Implementation ==
Talked a bunch with Aaron and Deryck while working on issue and best way to
fix.
== Implementation Notes ==
The big fix is to only reassign the uri when the request method is not a
patch. #89 of the diff.
This required letting the wrapper method know what the method was so we pass
that along in the args.
Tests were added to verify that this is not altered during a patch, but is
during a named_get/post. See #776.
The test suite was updated to the new standard format and thus was indented
for the big line change there. No other tests were modified or adjusted.
Since the entry/resource lp_original_uri no longer makes sense, it's just
changed to uri. It's used in other methods that the instance makes so they
were updated to match.
There are a few other small drive by lints to fix spacing and such. See
#8/25/etc.
== Tests ==
xvfb-run ./bin/test -x -cvv --layer=
== LoC Qualification ==
Need 54 LoC
Worked on cleaning up the client.js, removing the original bug test that isn't
required and isn't run.
See:
https:/
https:/
https:/
Preview Diff
1 | === modified file 'lib/lp/app/javascript/client.js' | |||
2 | --- lib/lp/app/javascript/client.js 2012-07-23 18:06:49 +0000 | |||
3 | +++ lib/lp/app/javascript/client.js 2012-07-24 16:58:23 +0000 | |||
4 | @@ -43,11 +43,11 @@ | |||
5 | 43 | 'lp:' + cache_name + ':' + name + ':changed'; | 43 | 'lp:' + cache_name + ':' + name + ':changed'; |
6 | 44 | var new_value_html = entry.getHTML(name); | 44 | var new_value_html = entry.getHTML(name); |
7 | 45 | var event = { | 45 | var event = { |
13 | 46 | 'name': name, | 46 | name: name, |
14 | 47 | 'old_value': old_value, | 47 | old_value: old_value, |
15 | 48 | 'new_value': new_value, | 48 | new_value: new_value, |
16 | 49 | 'new_value_html': new_value_html, | 49 | new_value_html: new_value_html, |
17 | 50 | 'entry': entry | 50 | entry: entry |
18 | 51 | }; | 51 | }; |
19 | 52 | Y.fire(field_updated_event_name, event); | 52 | Y.fire(field_updated_event_name, event); |
20 | 53 | } | 53 | } |
21 | @@ -66,17 +66,16 @@ | |||
22 | 66 | } | 66 | } |
23 | 67 | 67 | ||
24 | 68 | if (fields_changed.length > 0) { | 68 | if (fields_changed.length > 0) { |
31 | 69 | var event_name = 'lp:' + cache_name + ':changed'; | 69 | var event_name = 'lp:' + cache_name + ':changed'; |
32 | 70 | var event_ = { | 70 | var event_ = { |
33 | 71 | 'fields_changed': fields_changed, | 71 | fields_changed: fields_changed, |
34 | 72 | 'entry': entry | 72 | entry: entry |
35 | 73 | }; | 73 | }; |
36 | 74 | Y.fire(event_name, event_); | 74 | Y.fire(event_name, event_); |
37 | 75 | } | 75 | } |
38 | 76 | }; | 76 | }; |
39 | 77 | 77 | ||
40 | 78 | 78 | ||
41 | 79 | |||
42 | 80 | var module = Y.namespace('lp.client'); | 79 | var module = Y.namespace('lp.client'); |
43 | 81 | 80 | ||
44 | 82 | module.HTTP_CREATED = 201; | 81 | module.HTTP_CREATED = 201; |
45 | @@ -84,6 +83,9 @@ | |||
46 | 84 | module.HTTP_NOT_FOUND = 404; | 83 | module.HTTP_NOT_FOUND = 404; |
47 | 85 | 84 | ||
48 | 86 | module.XHTML = 'application/xhtml+xml'; | 85 | module.XHTML = 'application/xhtml+xml'; |
49 | 86 | module.GET = 'get'; | ||
50 | 87 | module.POST = 'post'; | ||
51 | 88 | module.PATCH = 'patch'; | ||
52 | 87 | 89 | ||
53 | 88 | /* Log the normal attributes accessible via o[key], and if it is a | 90 | /* Log the normal attributes accessible via o[key], and if it is a |
54 | 89 | * YUI node, log all of the attributes accessible via o.get(key). | 91 | * YUI node, log all of the attributes accessible via o.get(key). |
55 | @@ -328,7 +330,7 @@ | |||
56 | 328 | if (!entry) { | 330 | if (!entry) { |
57 | 329 | return; | 331 | return; |
58 | 330 | } | 332 | } |
60 | 331 | var original_uri = entry.lp_original_uri; | 333 | var original_uri = entry.uri; |
61 | 332 | var full_uri = module.get_absolute_uri(original_uri); | 334 | var full_uri = module.get_absolute_uri(original_uri); |
62 | 333 | var name; | 335 | var name; |
63 | 334 | var cached_object; | 336 | var cached_object; |
64 | @@ -349,14 +351,29 @@ | |||
65 | 349 | 351 | ||
66 | 350 | module.wrap_resource_on_success = function(ignore, response, args) { | 352 | module.wrap_resource_on_success = function(ignore, response, args) { |
67 | 351 | var client = args[0]; | 353 | var client = args[0]; |
68 | 354 | // The original uri of the caller. | ||
69 | 352 | var uri = args[1]; | 355 | var uri = args[1]; |
71 | 353 | var old_on_success = args[2]; | 356 | var callback = args[2]; |
72 | 354 | var update_cache = args[3]; | 357 | var update_cache = args[3]; |
73 | 358 | var method = args[4]; | ||
74 | 355 | var representation, wrapped; | 359 | var representation, wrapped; |
76 | 356 | if (old_on_success) { | 360 | |
77 | 361 | if (callback) { | ||
78 | 357 | var media_type = response.getResponseHeader('Content-Type'); | 362 | var media_type = response.getResponseHeader('Content-Type'); |
79 | 358 | if (media_type.substring(0,16) === 'application/json') { | 363 | if (media_type.substring(0,16) === 'application/json') { |
80 | 359 | representation = Y.JSON.parse(response.responseText); | 364 | representation = Y.JSON.parse(response.responseText); |
81 | 365 | |||
82 | 366 | // If the object fetched has a self_link, make that the object's | ||
83 | 367 | // uri for use in other api methods off of that object. | ||
84 | 368 | // During a PATCH request the caller is the object. Leave the | ||
85 | 369 | // original_uri alone. Otherwise make the uri the object | ||
86 | 370 | // coming back. | ||
87 | 371 | if (Y.Lang.isValue(representation) && | ||
88 | 372 | Y.Lang.isValue(representation.self_link) && | ||
89 | 373 | method !== module.PATCH) { | ||
90 | 374 | uri = representation.self_link; | ||
91 | 375 | } | ||
92 | 376 | |||
93 | 360 | // If the response contains a notification header, display the | 377 | // If the response contains a notification header, display the |
94 | 361 | // notifications. | 378 | // notifications. |
95 | 362 | var notifications = response.getResponseHeader( | 379 | var notifications = response.getResponseHeader( |
96 | @@ -364,18 +381,14 @@ | |||
97 | 364 | if (notifications !== null && notifications !== "") { | 381 | if (notifications !== null && notifications !== "") { |
98 | 365 | module.display_notifications(notifications); | 382 | module.display_notifications(notifications); |
99 | 366 | } | 383 | } |
100 | 367 | if (Y.Lang.isValue(representation) && | ||
101 | 368 | Y.Lang.isValue(representation.self_link)) { | ||
102 | 369 | uri = representation.self_link; | ||
103 | 370 | } | ||
104 | 371 | wrapped = client.wrap_resource(uri, representation); | 384 | wrapped = client.wrap_resource(uri, representation); |
106 | 372 | var result = old_on_success(wrapped); | 385 | var result = callback(wrapped); |
107 | 373 | if (update_cache) { | 386 | if (update_cache) { |
109 | 374 | module.update_cache(wrapped); | 387 | module.update_cache(wrapped); |
110 | 375 | } | 388 | } |
111 | 376 | return result; | 389 | return result; |
112 | 377 | } else { | 390 | } else { |
114 | 378 | return old_on_success(response.responseText); | 391 | return callback(response.responseText); |
115 | 379 | } | 392 | } |
116 | 380 | } | 393 | } |
117 | 381 | }; | 394 | }; |
118 | @@ -501,7 +514,7 @@ | |||
119 | 501 | 'init': function(client, representation, uri) { | 514 | 'init': function(client, representation, uri) { |
120 | 502 | /* Initialize a resource with its representation and URI. */ | 515 | /* Initialize a resource with its representation and URI. */ |
121 | 503 | this.lp_client = client; | 516 | this.lp_client = client; |
123 | 504 | this.lp_original_uri = uri; | 517 | this.uri = uri; |
124 | 505 | var key; | 518 | var key; |
125 | 506 | for (key in representation) { | 519 | for (key in representation) { |
126 | 507 | if (representation.hasOwnProperty(key)) { | 520 | if (representation.hasOwnProperty(key)) { |
127 | @@ -548,15 +561,13 @@ | |||
128 | 548 | 561 | ||
129 | 549 | 'named_get': function(operation_name, config) { | 562 | 'named_get': function(operation_name, config) { |
130 | 550 | /* Get the result of a named GET operation on this resource. */ | 563 | /* Get the result of a named GET operation on this resource. */ |
133 | 551 | return this.lp_client.named_get(this.lp_original_uri, | 564 | return this.lp_client.named_get(this.uri, operation_name, |
132 | 552 | operation_name, | ||
134 | 553 | config); | 565 | config); |
135 | 554 | }, | 566 | }, |
136 | 555 | 567 | ||
137 | 556 | 'named_post': function(operation_name, config) { | 568 | 'named_post': function(operation_name, config) { |
138 | 557 | /* Trigger a named POST operation on this resource. */ | 569 | /* Trigger a named POST operation on this resource. */ |
141 | 558 | return this.lp_client.named_post(this.lp_original_uri, | 570 | return this.lp_client.named_post(this.uri, operation_name, |
140 | 559 | operation_name, | ||
142 | 560 | config); | 571 | config); |
143 | 561 | } | 572 | } |
144 | 562 | }; | 573 | }; |
145 | @@ -588,14 +599,14 @@ | |||
146 | 588 | :param start: Where in the collection to start serving entries. | 599 | :param start: Where in the collection to start serving entries. |
147 | 589 | :param size: How many entries to serve. | 600 | :param size: How many entries to serve. |
148 | 590 | */ | 601 | */ |
150 | 591 | return this.lp_client.get(this.lp_original_uri, | 602 | return this.lp_client.get(this.uri, |
151 | 592 | {on: on, start: start, size: size}); | 603 | {on: on, start: start, size: size}); |
152 | 593 | }; | 604 | }; |
153 | 594 | 605 | ||
154 | 595 | module.Entry = function(client, representation, uri) { | 606 | module.Entry = function(client, representation, uri) { |
155 | 596 | /* A single object from the Launchpad web service. */ | 607 | /* A single object from the Launchpad web service. */ |
156 | 597 | this.lp_client = client; | 608 | this.lp_client = client; |
158 | 598 | this.lp_original_uri = uri; | 609 | this.uri = uri; |
159 | 599 | this.dirty_attributes = []; | 610 | this.dirty_attributes = []; |
160 | 600 | var entry = this; | 611 | var entry = this; |
161 | 601 | 612 | ||
162 | @@ -644,21 +655,21 @@ | |||
163 | 644 | }; | 655 | }; |
164 | 645 | 656 | ||
165 | 646 | module.Entry.prototype.getHTML = function(key) { | 657 | module.Entry.prototype.getHTML = function(key) { |
181 | 647 | var lp_html = this.get('lp_html'); | 658 | var lp_html = this.get('lp_html'); |
182 | 648 | if (lp_html) { | 659 | if (lp_html) { |
183 | 649 | // First look for the key. | 660 | // First look for the key. |
184 | 650 | var value = lp_html[key]; | 661 | var value = lp_html[key]; |
185 | 651 | if (value === undefined) { | 662 | if (value === undefined) { |
186 | 652 | // now look for key_link | 663 | // now look for key_link |
187 | 653 | value = lp_html[key + '_link']; | 664 | value = lp_html[key + '_link']; |
188 | 654 | } | 665 | } |
189 | 655 | if (value !== undefined) { | 666 | if (value !== undefined) { |
190 | 656 | var result = Y.Node.create("<span/>"); | 667 | var result = Y.Node.create("<span/>"); |
191 | 657 | result.setContent(value); | 668 | result.setContent(value); |
192 | 658 | return result; | 669 | return result; |
193 | 659 | } | 670 | } |
194 | 660 | } | 671 | } |
195 | 661 | return null; | 672 | return null; |
196 | 662 | }; | 673 | }; |
197 | 663 | 674 | ||
198 | 664 | // The Launchpad client itself. | 675 | // The Launchpad client itself. |
199 | @@ -690,7 +701,8 @@ | |||
200 | 690 | var client = this; | 701 | var client = this; |
201 | 691 | var y_config = { | 702 | var y_config = { |
202 | 692 | on: on, | 703 | on: on, |
204 | 693 | 'arguments': [client, uri, old_on_success, update_cache], | 704 | 'arguments': [ |
205 | 705 | client, uri, old_on_success, update_cache, module.GET], | ||
206 | 694 | 'headers': headers, | 706 | 'headers': headers, |
207 | 695 | data: data, | 707 | data: data, |
208 | 696 | sync: this.sync | 708 | sync: this.sync |
209 | @@ -737,9 +749,8 @@ | |||
210 | 737 | { on: { success: old_on_success, | 749 | { on: { success: old_on_success, |
211 | 738 | failure: on.failure } }); | 750 | failure: on.failure } }); |
212 | 739 | } | 751 | } |
216 | 740 | return module.wrap_resource_on_success(undefined, | 752 | return module.wrap_resource_on_success( |
217 | 741 | response, | 753 | undefined, response, args, module.POST); |
215 | 742 | args); | ||
218 | 743 | }; | 754 | }; |
219 | 744 | var client = this; | 755 | var client = this; |
220 | 745 | var update_cache = false; | 756 | var update_cache = false; |
221 | @@ -761,12 +772,12 @@ | |||
222 | 761 | var old_on_success = on.success; | 772 | var old_on_success = on.success; |
223 | 762 | var update_cache = true; | 773 | var update_cache = true; |
224 | 763 | on.success = module.wrap_resource_on_success; | 774 | on.success = module.wrap_resource_on_success; |
226 | 764 | args = [this, uri, old_on_success, update_cache]; | 775 | var args = [this, uri, old_on_success, update_cache, module.PATCH]; |
227 | 765 | 776 | ||
228 | 766 | var extra_headers = { | 777 | var extra_headers = { |
232 | 767 | "X-HTTP-Method-Override": "PATCH", | 778 | "X-HTTP-Method-Override": "PATCH", |
233 | 768 | "Content-Type": "application/json", | 779 | "Content-Type": "application/json", |
234 | 769 | "X-Content-Type-Override": "application/json" | 780 | "X-Content-Type-Override": "application/json" |
235 | 770 | }; | 781 | }; |
236 | 771 | var name; | 782 | var name; |
237 | 772 | if (headers !== undefined) { | 783 | if (headers !== undefined) { |
238 | @@ -1027,14 +1038,12 @@ | |||
239 | 1027 | } | 1038 | } |
240 | 1028 | }); | 1039 | }); |
241 | 1029 | 1040 | ||
242 | 1030 | |||
243 | 1031 | }, "0.1", { | 1041 | }, "0.1", { |
244 | 1032 | requires: ["attribute", "base", "io", "querystring", "json-parse", | 1042 | requires: ["attribute", "base", "io", "querystring", "json-parse", |
245 | 1033 | "json-stringify", "lp"] | 1043 | "json-stringify", "lp"] |
246 | 1034 | }); | 1044 | }); |
247 | 1035 | 1045 | ||
248 | 1036 | YUI.add('lp.client.plugins', function (Y) { | 1046 | YUI.add('lp.client.plugins', function (Y) { |
249 | 1037 | |||
250 | 1038 | /** | 1047 | /** |
251 | 1039 | * A collection of plugins to hook lp.client into widgets. | 1048 | * A collection of plugins to hook lp.client into widgets. |
252 | 1040 | * | 1049 | * |
253 | @@ -1245,7 +1254,6 @@ | |||
254 | 1245 | } | 1254 | } |
255 | 1246 | } | 1255 | } |
256 | 1247 | }); | 1256 | }); |
257 | 1248 | |||
258 | 1249 | }, "0.1", { | 1257 | }, "0.1", { |
259 | 1250 | requires: ["base", "plugin", "dump", "lazr.editor", "lp.client"] | 1258 | requires: ["base", "plugin", "dump", "lazr.editor", "lp.client"] |
260 | 1251 | }); | 1259 | }); |
261 | 1252 | 1260 | ||
262 | === modified file 'lib/lp/app/javascript/tests/test_lp_client.html' | |||
263 | --- lib/lp/app/javascript/tests/test_lp_client.html 2012-03-27 04:36:24 +0000 | |||
264 | +++ lib/lp/app/javascript/tests/test_lp_client.html 2012-07-24 16:58:23 +0000 | |||
265 | @@ -3,7 +3,6 @@ | |||
266 | 3 | Copyright 2012 Canonical Ltd. This software is licensed under the | 3 | Copyright 2012 Canonical Ltd. This software is licensed under the |
267 | 4 | GNU Affero General Public License version 3 (see the file LICENSE). | 4 | GNU Affero General Public License version 3 (see the file LICENSE). |
268 | 5 | --> | 5 | --> |
269 | 6 | |||
270 | 7 | <html> | 6 | <html> |
271 | 8 | <head> | 7 | <head> |
272 | 9 | <title>Test client</title> | 8 | <title>Test client</title> |
273 | @@ -30,20 +29,15 @@ | |||
274 | 30 | <script type="text/javascript" | 29 | <script type="text/javascript" |
275 | 31 | src="../../../../../build/js/lp/app/lp.js"></script> | 30 | src="../../../../../build/js/lp/app/lp.js"></script> |
276 | 32 | 31 | ||
277 | 33 | |||
278 | 34 | <!-- The module under test. --> | 32 | <!-- The module under test. --> |
279 | 35 | <script type="text/javascript" src="../client.js"></script> | 33 | <script type="text/javascript" src="../client.js"></script> |
280 | 36 | 34 | ||
281 | 37 | <!-- Placeholder for any css asset for this module. --> | ||
282 | 38 | <!-- <link rel="stylesheet" href="../assets/client-core.css" /> --> | ||
283 | 39 | |||
284 | 40 | <!-- The test suite. --> | 35 | <!-- The test suite. --> |
285 | 41 | <script type="text/javascript" src="test_lp_client.js"></script> | 36 | <script type="text/javascript" src="test_lp_client.js"></script> |
286 | 42 | 37 | ||
287 | 43 | </head> | 38 | </head> |
288 | 44 | <body class="yui3-skin-sam"> | 39 | <body class="yui3-skin-sam"> |
289 | 45 | <ul id="suites"> | 40 | <ul id="suites"> |
290 | 46 | <!-- <li>lp.large_indicator.test</li> --> | ||
291 | 47 | <li>lp.client.test</li> | 41 | <li>lp.client.test</li> |
292 | 48 | </ul> | 42 | </ul> |
293 | 49 | <div class="context-publication"> | 43 | <div class="context-publication"> |
294 | 50 | 44 | ||
295 | === modified file 'lib/lp/app/javascript/tests/test_lp_client.js' | |||
296 | --- lib/lp/app/javascript/tests/test_lp_client.js 2012-06-26 17:16:34 +0000 | |||
297 | +++ lib/lp/app/javascript/tests/test_lp_client.js 2012-07-24 16:58:23 +0000 | |||
298 | @@ -1,522 +1,587 @@ | |||
542 | 1 | /* Copyright (c) 2011, Canonical Ltd. All rights reserved. */ | 1 | /* Copyright (c) 2011-2012 Canonical Ltd. All rights reserved. */ |
543 | 2 | 2 | YUI.add('lp.client.test', function (Y) { | |
544 | 3 | YUI().use('lp.testing.runner', 'lp.testing.mockio', 'test', 'console', | 3 | var Assert = Y.Assert; |
545 | 4 | 'lp.client', 'escape', function(Y) { | 4 | var tests = Y.namespace('lp.client.test'); |
546 | 5 | 5 | tests.suite = new Y.Test.Suite('client Tests'); | |
547 | 6 | var Assert = Y.Assert; // For easy access to isTrue(), etc. | 6 | tests.suite.add(new Y.Test.Case({ |
548 | 7 | 7 | name: "lp.client", | |
549 | 8 | var suite = new Y.Test.Suite("lp.client Tests"); | 8 | |
550 | 9 | 9 | setUp: function() { | |
551 | 10 | suite.add(new Y.Test.Case({ | 10 | }, |
552 | 11 | name: "lp.client", | 11 | |
553 | 12 | 12 | test_normalize_uri: function() { | |
554 | 13 | setUp: function() { | 13 | var normalize = Y.lp.client.normalize_uri; |
555 | 14 | }, | 14 | Assert.areEqual( |
556 | 15 | 15 | normalize("http://www.example.com/api/devel/foo"), | |
557 | 16 | test_normalize_uri: function() { | 16 | "/api/devel/foo"); |
558 | 17 | var normalize = Y.lp.client.normalize_uri; | 17 | Assert.areEqual( |
559 | 18 | Assert.areEqual( | 18 | normalize("http://www.example.com/foo/bar"), "/foo/bar"); |
560 | 19 | normalize("http://www.example.com/api/devel/foo"), | 19 | Assert.areEqual( |
561 | 20 | "/api/devel/foo"); | 20 | normalize("/foo/bar"), "/api/devel/foo/bar"); |
562 | 21 | Assert.areEqual( | 21 | Assert.areEqual( |
563 | 22 | normalize("http://www.example.com/foo/bar"), "/foo/bar"); | 22 | normalize("/api/devel/foo/bar"), "/api/devel/foo/bar"); |
564 | 23 | Assert.areEqual( | 23 | Assert.areEqual( |
565 | 24 | normalize("/foo/bar"), "/api/devel/foo/bar"); | 24 | normalize("foo/bar"), "/api/devel/foo/bar"); |
566 | 25 | Assert.areEqual( | 25 | Assert.areEqual( |
567 | 26 | normalize("/api/devel/foo/bar"), "/api/devel/foo/bar"); | 26 | normalize("api/devel/foo/bar"), "/api/devel/foo/bar"); |
568 | 27 | Assert.areEqual( | 27 | }, |
569 | 28 | normalize("foo/bar"), "/api/devel/foo/bar"); | 28 | |
570 | 29 | Assert.areEqual( | 29 | test_get_io_provider__default: function() { |
571 | 30 | normalize("api/devel/foo/bar"), "/api/devel/foo/bar"); | 30 | var undefined_provider, |
572 | 31 | }, | 31 | io_provider = Y.lp.client.get_io_provider(undefined_provider); |
573 | 32 | 32 | Assert.areSame(Y, io_provider); | |
574 | 33 | test_get_io_provider__default: function() { | 33 | }, |
575 | 34 | var undefined_provider, | 34 | |
576 | 35 | io_provider = Y.lp.client.get_io_provider(undefined_provider); | 35 | test_get_io_provider__mockio: function() { |
577 | 36 | Assert.areSame(Y, io_provider); | 36 | // If a mock provider is provided, it is picked as the io_provider. |
578 | 37 | }, | 37 | var mockio = new Y.lp.testing.mockio.MockIo(), |
579 | 38 | 38 | io_provider = Y.lp.client.get_io_provider(mockio); | |
580 | 39 | test_get_io_provider__mockio: function() { | 39 | Assert.areSame(mockio, io_provider); |
581 | 40 | // If a mock provider is provided, it is picked as the io_provider. | 40 | }, |
582 | 41 | var mockio = new Y.lp.testing.mockio.MockIo(), | 41 | |
583 | 42 | io_provider = Y.lp.client.get_io_provider(mockio); | 42 | test_get_configured_io_provider__default: function() { |
584 | 43 | Assert.areSame(mockio, io_provider); | 43 | // If no io_provider is configured, Y is the io_provider. |
585 | 44 | }, | 44 | var io_provider = Y.lp.client.get_configured_io_provider({}); |
586 | 45 | 45 | Assert.areSame(Y, io_provider); | |
587 | 46 | test_get_configured_io_provider__default: function() { | 46 | }, |
588 | 47 | // If no io_provider is configured, Y is the io_provider. | 47 | |
589 | 48 | var io_provider = Y.lp.client.get_configured_io_provider({}); | 48 | test_get_configured_io_provider__default_undefined: function() { |
590 | 49 | Assert.areSame(Y, io_provider); | 49 | // If no configuration is provided, Y is the io_provider. |
591 | 50 | }, | 50 | var io_provider = Y.lp.client.get_configured_io_provider(); |
592 | 51 | 51 | Assert.areSame(Y, io_provider); | |
593 | 52 | test_get_configured_io_provider__default_undefined: function() { | 52 | }, |
594 | 53 | // If no configuration is provided, Y is the io_provider. | 53 | |
595 | 54 | var io_provider = Y.lp.client.get_configured_io_provider(); | 54 | test_get_configured_io_provider__mockio: function() { |
596 | 55 | Assert.areSame(Y, io_provider); | 55 | // If an io_provider is configured, it is picked as the |
597 | 56 | }, | 56 | // io_provider. |
598 | 57 | 57 | var mockio = new Y.lp.testing.mockio.MockIo(), | |
599 | 58 | test_get_configured_io_provider__mockio: function() { | 58 | io_provider = Y.lp.client.get_configured_io_provider( |
600 | 59 | // If an io_provider is configured, it is picked as the io_provider. | 59 | {io_provider: mockio}); |
601 | 60 | var mockio = new Y.lp.testing.mockio.MockIo(), | 60 | Assert.areSame(mockio, io_provider); |
602 | 61 | io_provider = Y.lp.client.get_configured_io_provider( | 61 | }, |
603 | 62 | {io_provider: mockio}); | 62 | |
604 | 63 | Assert.areSame(mockio, io_provider); | 63 | test_get_configured_io_provider__different_key: function() { |
605 | 64 | }, | 64 | // The io_provider can be stored with a different key. |
606 | 65 | 65 | var mockio = new Y.lp.testing.mockio.MockIo(), | |
607 | 66 | test_get_configured_io_provider__different_key: function() { | 66 | io_provider = Y.lp.client.get_configured_io_provider( |
608 | 67 | // The io_provider can be stored with a different key. | 67 | {my_io: mockio}, 'my_io'); |
609 | 68 | var mockio = new Y.lp.testing.mockio.MockIo(), | 68 | Assert.areSame(mockio, io_provider); |
610 | 69 | io_provider = Y.lp.client.get_configured_io_provider( | 69 | }, |
611 | 70 | {my_io: mockio}, 'my_io'); | 70 | |
612 | 71 | Assert.areSame(mockio, io_provider); | 71 | test_append_qs: function() { |
613 | 72 | }, | 72 | var qs = ""; |
614 | 73 | 73 | qs = Y.lp.client.append_qs(qs, "Pöllä", "Perelló"); | |
615 | 74 | test_append_qs: function() { | 74 | Assert.areEqual( |
616 | 75 | var qs = ""; | 75 | "P%C3%83%C2%B6ll%C3%83%C2%A4=Perell%C3%83%C2%B3", qs, |
617 | 76 | qs = Y.lp.client.append_qs(qs, "Pöllä", "Perelló"); | 76 | 'This tests is known to fail in Chrome.'); |
618 | 77 | Assert.areEqual( | 77 | }, |
619 | 78 | "P%C3%83%C2%B6ll%C3%83%C2%A4=Perell%C3%83%C2%B3", qs, | 78 | |
620 | 79 | 'This tests is known to fail in Chrome, it is browser specific.'); | 79 | test_append_qs_with_array: function() { |
621 | 80 | }, | 80 | // append_qs() appends multiple arguments to the query string |
622 | 81 | 81 | // when a parameter value is an array. | |
623 | 82 | test_append_qs_with_array: function() { | 82 | var qs = ""; |
624 | 83 | // append_qs() appends multiple arguments to the query string | 83 | qs = Y.lp.client.append_qs(qs, "foo", ["bar", "baz"]); |
625 | 84 | // when a parameter value is an array. | 84 | Assert.areEqual("foo=bar&foo=baz", qs); |
626 | 85 | var qs = ""; | 85 | // All values in the array are encoded correctly too. |
627 | 86 | qs = Y.lp.client.append_qs(qs, "foo", ["bar", "baz"]); | 86 | qs = Y.lp.client.append_qs(qs, "a&b", ["a+b"]); |
628 | 87 | Assert.areEqual("foo=bar&foo=baz", qs); | 87 | Assert.areEqual("foo=bar&foo=baz&a%26b=a%2Bb", qs); |
629 | 88 | // All values in the array are encoded correctly too. | 88 | }, |
630 | 89 | qs = Y.lp.client.append_qs(qs, "a&b", ["a+b"]); | 89 | |
631 | 90 | Assert.areEqual("foo=bar&foo=baz&a%26b=a%2Bb", qs); | 90 | test_field_uri: function() { |
632 | 91 | }, | 91 | var get_field_uri = Y.lp.client.get_field_uri; |
633 | 92 | 92 | Assert.areEqual( | |
634 | 93 | test_field_uri: function() { | 93 | get_field_uri("http://www.example.com/api/devel/foo", "field"), |
635 | 94 | var get_field_uri = Y.lp.client.get_field_uri; | 94 | "/api/devel/foo/field"); |
636 | 95 | Assert.areEqual( | 95 | Assert.areEqual( |
637 | 96 | get_field_uri("http://www.example.com/api/devel/foo", "field"), | 96 | get_field_uri("/no/slash", "field"), |
638 | 97 | "/api/devel/foo/field"); | 97 | "/api/devel/no/slash/field"); |
639 | 98 | Assert.areEqual( | 98 | Assert.areEqual( |
640 | 99 | get_field_uri("/no/slash", "field"), | 99 | get_field_uri("/has/slash/", "field"), |
641 | 100 | "/api/devel/no/slash/field"); | 100 | "/api/devel/has/slash/field"); |
642 | 101 | Assert.areEqual( | 101 | }, |
643 | 102 | get_field_uri("/has/slash/", "field"), | 102 | test_view_url: function() { |
644 | 103 | "/api/devel/has/slash/field"); | 103 | entry_repr = {web_link: 'http://example.com/context'}; |
645 | 104 | }, | 104 | var context = new Y.lp.client.Entry(null, entry_repr, null); |
646 | 105 | test_view_url: function() { | 105 | expected = '/context/+myview/++mynamespace++'; |
647 | 106 | entry_repr = {web_link: 'http://example.com/context'}; | 106 | actual = Y.lp.client.get_view_url( |
648 | 107 | var context = new Y.lp.client.Entry(null, entry_repr, null); | 107 | context, '+myview', 'mynamespace'); |
649 | 108 | expected = '/context/+myview/++mynamespace++'; | 108 | Assert.areEqual(expected, actual); |
650 | 109 | actual = Y.lp.client.get_view_url(context, '+myview', 'mynamespace'); | 109 | }, |
651 | 110 | Assert.areEqual(expected, actual); | 110 | test_get_form_url: function() { |
652 | 111 | }, | 111 | entry_repr = {web_link: 'http://example.com/context'}; |
653 | 112 | test_get_form_url: function() { | 112 | var context = new Y.lp.client.Entry(null, entry_repr, null); |
654 | 113 | entry_repr = {web_link: 'http://example.com/context'}; | 113 | expected = '/context/+myview/++form++'; |
655 | 114 | var context = new Y.lp.client.Entry(null, entry_repr, null); | 114 | actual = Y.lp.client.get_form_url(context, '+myview'); |
656 | 115 | expected = '/context/+myview/++form++'; | 115 | Assert.areEqual(expected, actual); |
657 | 116 | actual = Y.lp.client.get_form_url(context, '+myview'); | 116 | }, |
658 | 117 | Assert.areEqual(expected, actual); | 117 | test_load_model: function(){ |
659 | 118 | }, | 118 | var mockio = new Y.lp.testing.mockio.MockIo(); |
660 | 119 | test_load_model: function(){ | 119 | Assert.areEqual(0, mockio.requests.length); |
661 | 120 | var mockio = new Y.lp.testing.mockio.MockIo(); | 120 | var mylist = []; |
662 | 121 | Assert.areEqual(0, mockio.requests.length); | 121 | var config = { |
663 | 122 | var mylist = []; | 122 | io_provider: mockio, |
664 | 123 | var config = { | 123 | on: { |
665 | 124 | io_provider: mockio, | 124 | success: Y.bind(mylist.push, mylist) |
666 | 125 | on: { | 125 | } |
667 | 126 | success: Y.bind(mylist.push, mylist) | 126 | }; |
668 | 127 | } | 127 | var entry_repr = {web_link: 'http://example.com/context'}; |
669 | 128 | }; | 128 | var client = new Y.lp.client.Launchpad(); |
670 | 129 | var entry_repr = {web_link: 'http://example.com/context'}; | 129 | var context = new Y.lp.client.Entry(client, entry_repr, null); |
671 | 130 | var client = new Y.lp.client.Launchpad(); | 130 | Y.lp.client.load_model(context, '+myview', config); |
672 | 131 | var context = new Y.lp.client.Entry(client, entry_repr, null); | 131 | Assert.areEqual( |
673 | 132 | Y.lp.client.load_model(context, '+myview', config); | 132 | '/context/+myview/++model++', mockio.last_request.url); |
674 | 133 | Assert.areEqual( | 133 | mockio.success({ |
675 | 134 | '/context/+myview/++model++', mockio.last_request.url); | 134 | responseText: |
676 | 135 | mockio.success({ | 135 | '{"boolean": true, "entry": {"resource_type_link": "foo"}}', |
677 | 136 | responseText: | 136 | responseHeaders: {'Content-Type': 'application/json'} |
678 | 137 | '{"boolean": true, "entry": {"resource_type_link": "foo"}}', | 137 | }); |
679 | 138 | responseHeaders: {'Content-Type': 'application/json'} | 138 | var result = mylist[0]; |
680 | 139 | }); | 139 | Assert.areSame(true, result.boolean); |
681 | 140 | var result = mylist[0]; | 140 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); |
682 | 141 | Assert.areSame(true, result.boolean); | 141 | Assert.areSame('foo', result.entry.get('resource_type_link')); |
683 | 142 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); | 142 | }, |
684 | 143 | Assert.areSame('foo', result.entry.get('resource_type_link')); | 143 | test_get_success_callback: function() { |
685 | 144 | }, | 144 | var mockio = new Y.lp.testing.mockio.MockIo(); |
686 | 145 | test_get_success_callback: function() { | 145 | var mylist = []; |
687 | 146 | var mockio = new Y.lp.testing.mockio.MockIo(); | 146 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); |
688 | 147 | var mylist = []; | 147 | client.get('/people', {on:{success: Y.bind(mylist.push, mylist)}}); |
689 | 148 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); | 148 | Assert.areEqual('/api/devel/people', mockio.last_request.url); |
690 | 149 | client.get('/people', {on:{success: Y.bind(mylist.push, mylist)}}); | 149 | mockio.success({ |
691 | 150 | Assert.areEqual('/api/devel/people', mockio.last_request.url); | 150 | responseText: |
692 | 151 | mockio.success({ | 151 | '{"entry": {"resource_type_link": "foo"}}', |
693 | 152 | responseText: | 152 | responseHeaders: {'Content-Type': 'application/json'} |
694 | 153 | '{"entry": {"resource_type_link": "foo"}}', | 153 | }); |
695 | 154 | responseHeaders: {'Content-Type': 'application/json'} | 154 | var result = mylist[0]; |
696 | 155 | }); | 155 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); |
697 | 156 | var result = mylist[0]; | 156 | Assert.areSame('foo', result.entry.get('resource_type_link')); |
698 | 157 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); | 157 | }, |
699 | 158 | Assert.areSame('foo', result.entry.get('resource_type_link')); | 158 | test_get_failure_callback: function() { |
700 | 159 | }, | 159 | var mockio = new Y.lp.testing.mockio.MockIo(); |
701 | 160 | test_get_failure_callback: function() { | 160 | var mylist = []; |
702 | 161 | var mockio = new Y.lp.testing.mockio.MockIo(); | 161 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); |
703 | 162 | var mylist = []; | 162 | client.get( |
704 | 163 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); | 163 | '/people', |
705 | 164 | client.get( | 164 | {on: { |
706 | 165 | '/people', | 165 | failure: function(){ |
707 | 166 | {on: { | 166 | mylist.push(Array.prototype.slice.call(arguments)); |
708 | 167 | failure: function(){ | 167 | }}}); |
709 | 168 | mylist.push(Array.prototype.slice.call(arguments)); | 168 | mockio.failure({status: 503}); |
710 | 169 | }}}); | 169 | var result = mylist[0]; |
711 | 170 | mockio.failure({status: 503}); | 170 | Assert.areSame(503, result[1].status); |
712 | 171 | var result = mylist[0]; | 171 | Assert.areSame('/api/devel/people', result[2][1]); |
713 | 172 | Assert.areSame(503, result[1].status); | 172 | }, |
714 | 173 | Assert.areSame('/api/devel/people', result[2][1]); | 173 | test_named_post_success_callback: function() { |
715 | 174 | }, | 174 | var mockio = new Y.lp.testing.mockio.MockIo(); |
716 | 175 | test_named_post_success_callback: function() { | 175 | var mylist = []; |
717 | 176 | var mockio = new Y.lp.testing.mockio.MockIo(); | 176 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); |
718 | 177 | var mylist = []; | 177 | client.named_post( |
719 | 178 | var client = new Y.lp.client.Launchpad({io_provider: mockio}); | 178 | '/people', 'newTeam', {on:{success: Y.bind(mylist.push, mylist)}}); |
720 | 179 | client.named_post( | 179 | Assert.areEqual('/api/devel/people', mockio.last_request.url); |
721 | 180 | '/people', 'newTeam', {on:{success: Y.bind(mylist.push, mylist)}}); | 180 | Assert.areEqual('ws.op=newTeam', mockio.last_request.config.data); |
722 | 181 | Assert.areEqual('/api/devel/people', mockio.last_request.url); | 181 | Assert.areEqual('POST', mockio.last_request.config.method); |
723 | 182 | Assert.areEqual('ws.op=newTeam', mockio.last_request.config.data); | 182 | mockio.success({ |
724 | 183 | Assert.areEqual('POST', mockio.last_request.config.method); | 183 | responseText: |
725 | 184 | mockio.success({ | 184 | '{"entry": {"resource_type_link": "foo"}}', |
726 | 185 | responseText: | 185 | responseHeaders: {'Content-Type': 'application/json'} |
727 | 186 | '{"entry": {"resource_type_link": "foo"}}', | 186 | }); |
728 | 187 | responseHeaders: {'Content-Type': 'application/json'} | 187 | var result = mylist[0]; |
729 | 188 | }); | 188 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); |
730 | 189 | var result = mylist[0]; | 189 | Assert.areSame('foo', result.entry.get('resource_type_link')); |
731 | 190 | Assert.isInstanceOf(Y.lp.client.Entry, result.entry); | 190 | }, |
732 | 191 | Assert.areSame('foo', result.entry.get('resource_type_link')); | 191 | test_wrap_resource_nested_mapping: function() { |
733 | 192 | }, | 192 | // wrap_resource produces mappings of plain object literals. These |
734 | 193 | test_wrap_resource_nested_mapping: function() { | 193 | // can be nested and have Entries in them. |
735 | 194 | // wrap_resource produces mappings of plain object literals. These can | 194 | var foo = { |
736 | 195 | // be nested and have Entries in them. | 195 | baa: {}, |
737 | 196 | var foo = { | 196 | bar: { |
738 | 197 | baa: {}, | 197 | baz: { |
739 | 198 | bar: { | 198 | resource_type_link: 'qux'} |
740 | 199 | baz: { | 199 | } |
741 | 200 | resource_type_link: 'qux'} | 200 | }; |
742 | 201 | } | 201 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); |
743 | 202 | }; | 202 | Assert.isInstanceOf(Y.lp.client.Entry, foo.bar.baz); |
744 | 203 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); | 203 | }, |
745 | 204 | Y.Assert.isInstanceOf(Y.lp.client.Entry, foo.bar.baz); | 204 | test_wrap_resource_nested_array: function() { |
746 | 205 | }, | 205 | // wrap_resource produces arrays of array literals. These can |
747 | 206 | test_wrap_resource_nested_array: function() { | 206 | // be nested and have Entries in them. |
748 | 207 | // wrap_resource produces arrays of array literals. These can | 207 | var foo = [[{resource_type_link: 'qux'}]]; |
749 | 208 | // be nested and have Entries in them. | 208 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); |
750 | 209 | var foo = [[{resource_type_link: 'qux'}]]; | 209 | Assert.isInstanceOf(Y.lp.client.Entry, foo[0][0]); |
751 | 210 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); | 210 | }, |
752 | 211 | Y.Assert.isInstanceOf(Y.lp.client.Entry, foo[0][0]); | 211 | test_wrap_resource_creates_array: function() { |
753 | 212 | }, | 212 | // wrap_resource creates new arrays, rather than reusing the |
754 | 213 | test_wrap_resource_creates_array: function() { | 213 | // existing one. |
755 | 214 | // wrap_resource creates new arrays, rather than reusing the existing | 214 | var foo = ['a']; |
756 | 215 | // one. | 215 | var bar = new Y.lp.client.Launchpad().wrap_resource(null, foo); |
757 | 216 | var foo = ['a']; | 216 | Assert.areNotSame(foo, bar); |
758 | 217 | var bar = new Y.lp.client.Launchpad().wrap_resource(null, foo); | 217 | }, |
759 | 218 | Y.Assert.areNotSame(foo, bar); | 218 | test_wrap_resource_creates_mapping: function() { |
760 | 219 | }, | 219 | // wrap_resource creates new mappings, rather than reusing the |
761 | 220 | test_wrap_resource_creates_mapping: function() { | 220 | // existing one. |
762 | 221 | // wrap_resource creates new mappings, rather than reusing the | 221 | var foo = {a: 'b'}; |
763 | 222 | // existing one. | 222 | var bar = new Y.lp.client.Launchpad().wrap_resource(null, foo); |
764 | 223 | var foo = {a: 'b'}; | 223 | Assert.areNotSame(foo, bar); |
765 | 224 | var bar = new Y.lp.client.Launchpad().wrap_resource(null, foo); | 224 | }, |
766 | 225 | Y.Assert.areNotSame(foo, bar); | 225 | test_wrap_resource_null: function() { |
767 | 226 | }, | 226 | // wrap_resource handles null correctly. |
768 | 227 | test_wrap_resource_null: function() { | 227 | var foo = { |
769 | 228 | // wrap_resource handles null correctly. | 228 | bar: null |
770 | 229 | var foo = { | 229 | }; |
771 | 230 | bar: null | 230 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); |
772 | 231 | }; | 231 | Assert.isNull(foo.bar); |
773 | 232 | foo = new Y.lp.client.Launchpad().wrap_resource(null, foo); | 232 | } |
774 | 233 | Y.Assert.isNull(foo.bar); | 233 | })); |
775 | 234 | } | 234 | |
776 | 235 | })); | 235 | tests.suite.add(new Y.Test.Case({ |
777 | 236 | 236 | name: "lp.wrap_on_success", | |
778 | 237 | suite.add(new Y.Test.Case({ | 237 | original_uri: 'http://launchpad.net/original_uri', |
779 | 238 | name: "update cache", | 238 | updated_uri: 'http://launchpad.net/object_uri', |
780 | 239 | 239 | ||
781 | 240 | setUp: function() { | 240 | setUp: function() { |
782 | 241 | window.LP = { | 241 | window.LP = {}; |
783 | 242 | cache: { | 242 | this.called = false; |
784 | 243 | context: { | 243 | }, |
785 | 244 | |||
786 | 245 | tearDown: function () { | ||
787 | 246 | delete window.LP; | ||
788 | 247 | delete this.called; | ||
789 | 248 | }, | ||
790 | 249 | |||
791 | 250 | _gen_callback: function (uri) { | ||
792 | 251 | var that = this; | ||
793 | 252 | return function (wrapped) { | ||
794 | 253 | that.called = true; | ||
795 | 254 | Assert.areEqual(wrapped.uri, uri); | ||
796 | 255 | }; | ||
797 | 256 | }, | ||
798 | 257 | |||
799 | 258 | _fake_response: function () { | ||
800 | 259 | return { | ||
801 | 260 | responseText: Y.JSON.stringify({ | ||
802 | 261 | self_link: this.updated_uri, | ||
803 | 262 | resource_type_link: 'object' | ||
804 | 263 | }), | ||
805 | 264 | getResponseHeader: function (key) { | ||
806 | 265 | var headers = {'Content-Type': 'application/json'}; | ||
807 | 266 | return headers[key]; | ||
808 | 267 | } | ||
809 | 268 | }; | ||
810 | 269 | }, | ||
811 | 270 | |||
812 | 271 | test_wrap_resource_patch_link: function () { | ||
813 | 272 | // wrap_resource_on_success will not modify the uri on a patch | ||
814 | 273 | // request and keep the original value. | ||
815 | 274 | var callback = this._gen_callback(this.original_uri); | ||
816 | 275 | Y.lp.client.wrap_resource_on_success(10, this._fake_response(), [ | ||
817 | 276 | new Y.lp.client.Launchpad(), this.original_uri, callback, | ||
818 | 277 | true, 'patch'] | ||
819 | 278 | ); | ||
820 | 279 | Assert.isTrue(this.called); | ||
821 | 280 | }, | ||
822 | 281 | |||
823 | 282 | test_wrap_resource_patch_named: function () { | ||
824 | 283 | // wrap_resource_on_success will modify the uri on a | ||
825 | 284 | // named_get/post methods to the value that came back in | ||
826 | 285 | // self_link. | ||
827 | 286 | var callback = this._gen_callback(this.updated_uri); | ||
828 | 287 | Y.lp.client.wrap_resource_on_success(10, this._fake_response(), [ | ||
829 | 288 | new Y.lp.client.Launchpad(), this.original_uri, callback, | ||
830 | 289 | true, 'post'] | ||
831 | 290 | ); | ||
832 | 291 | Assert.isTrue(this.called); | ||
833 | 292 | } | ||
834 | 293 | })); | ||
835 | 294 | |||
836 | 295 | tests.suite.add(new Y.Test.Case({ | ||
837 | 296 | name: "update cache", | ||
838 | 297 | |||
839 | 298 | setUp: function() { | ||
840 | 299 | window.LP = { | ||
841 | 300 | cache: { | ||
842 | 301 | context: { | ||
843 | 302 | 'first': "Hello", | ||
844 | 303 | 'second': true, | ||
845 | 304 | 'third': 42, | ||
846 | 305 | 'fourth': "Unaltered", | ||
847 | 306 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") | ||
848 | 307 | } | ||
849 | 308 | }}; | ||
850 | 309 | }, | ||
851 | 310 | |||
852 | 311 | tearDown: function() { | ||
853 | 312 | delete window.LP; | ||
854 | 313 | }, | ||
855 | 314 | |||
856 | 315 | test_update_cache: function() { | ||
857 | 316 | // Make sure that the cached objects are in fact updated. | ||
858 | 317 | var entry_repr = { | ||
859 | 318 | 'first': "World", | ||
860 | 319 | 'second': false, | ||
861 | 320 | 'third': 24, | ||
862 | 321 | 'fourth': "Unaltered", | ||
863 | 322 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") | ||
864 | 323 | }; | ||
865 | 324 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | ||
866 | 325 | Y.lp.client.update_cache(entry); | ||
867 | 326 | Assert.areEqual("World", LP.cache.context.first); | ||
868 | 327 | Assert.areEqual(false, LP.cache.context.second); | ||
869 | 328 | Assert.areEqual(24, LP.cache.context.third); | ||
870 | 329 | Assert.areEqual("Unaltered", LP.cache.context.fourth); | ||
871 | 330 | }, | ||
872 | 331 | |||
873 | 332 | test_getHTML: function() { | ||
874 | 333 | // Make sure that the getHTML method works as expected. | ||
875 | 334 | var entry_repr = { | ||
876 | 244 | 'first': "Hello", | 335 | 'first': "Hello", |
879 | 245 | 'second': true, | 336 | 'second': "World", |
880 | 246 | 'third': 42, | 337 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link"), |
881 | 338 | 'lp_html': {'first': "<p>Hello</p><p>World</p>"} | ||
882 | 339 | }; | ||
883 | 340 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | ||
884 | 341 | Assert.areEqual( | ||
885 | 342 | "<p>Hello</p><p>World</p>", | ||
886 | 343 | entry.getHTML('first').get('innerHTML')); | ||
887 | 344 | // If there is no html representation, null is returned. | ||
888 | 345 | Assert.areEqual(null, entry.getHTML('second')); | ||
889 | 346 | }, | ||
890 | 347 | |||
891 | 348 | test_update_cache_raises_events: function() { | ||
892 | 349 | // Check that the object changed event is raised. | ||
893 | 350 | var raised_event = null; | ||
894 | 351 | var handle = Y.on('lp:context:changed', function(e) { | ||
895 | 352 | raised_event = e; | ||
896 | 353 | }); | ||
897 | 354 | var entry_repr = { | ||
898 | 355 | 'first': "World", | ||
899 | 356 | 'second': false, | ||
900 | 357 | 'third': 24, | ||
901 | 247 | 'fourth': "Unaltered", | 358 | 'fourth': "Unaltered", |
902 | 248 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") | 359 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") |
1176 | 249 | } | 360 | }; |
1177 | 250 | }}; | 361 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); |
1178 | 251 | }, | 362 | Y.lp.client.update_cache(entry); |
1179 | 252 | 363 | handle.detach(); | |
1180 | 253 | tearDown: function() { | 364 | Y.ArrayAssert.itemsAreEqual( |
1181 | 254 | delete window.LP; | 365 | ['first','second','third'], raised_event.fields_changed); |
1182 | 255 | }, | 366 | Assert.areEqual(entry, raised_event.entry); |
1183 | 256 | 367 | }, | |
1184 | 257 | test_update_cache: function() { | 368 | |
1185 | 258 | // Make sure that the cached objects are in fact updated. | 369 | test_update_cache_raises_attribute_events: function() { |
1186 | 259 | var entry_repr = { | 370 | // Check that the object attribute changed events are raised. |
1187 | 260 | 'first': "World", | 371 | var first_event = null; |
1188 | 261 | 'second': false, | 372 | var second_event = null; |
1189 | 262 | 'third': 24, | 373 | var third_event = null; |
1190 | 263 | 'fourth': "Unaltered", | 374 | var fourth_event = null; |
1191 | 264 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") | 375 | var first_handle = Y.on('lp:context:first:changed', function(e) { |
1192 | 265 | }; | 376 | first_event = e; |
1193 | 266 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | 377 | }); |
1194 | 267 | Y.lp.client.update_cache(entry); | 378 | var second_handle = Y.on('lp:context:second:changed', function(e) { |
1195 | 268 | Assert.areEqual("World", LP.cache.context.first); | 379 | second_event = e; |
1196 | 269 | Assert.areEqual(false, LP.cache.context.second); | 380 | }); |
1197 | 270 | Assert.areEqual(24, LP.cache.context.third); | 381 | var third_handle = Y.on('lp:context:third:changed', function(e) { |
1198 | 271 | Assert.areEqual("Unaltered", LP.cache.context.fourth); | 382 | third_event = e; |
1199 | 272 | }, | 383 | }); |
1200 | 273 | 384 | var fourth_handle = Y.on('lp:context:fourth:changed', function(e) { | |
1201 | 274 | test_getHTML: function() { | 385 | fourth_event = e; |
1202 | 275 | // Make sure that the getHTML method works as expected. | 386 | }); |
1203 | 276 | var entry_repr = { | 387 | var entry_repr = { |
1204 | 277 | 'first': "Hello", | 388 | 'first': "World<boo/>", |
1205 | 278 | 'second': "World", | 389 | 'second': false, |
1206 | 279 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link"), | 390 | 'third': 24, |
1207 | 280 | 'lp_html': {'first': "<p>Hello</p><p>World</p>"} | 391 | 'fourth': "Unaltered", |
1208 | 281 | }; | 392 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link"), |
1209 | 282 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | 393 | 'lp_html': {'first': "<p>World html<boo/></p>"} |
1210 | 283 | Assert.areEqual( | 394 | }; |
1211 | 284 | "<p>Hello</p><p>World</p>", | 395 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); |
1212 | 285 | entry.getHTML('first').get('innerHTML')); | 396 | Y.lp.client.update_cache(entry); |
1213 | 286 | // If there is no html representation, null is returned. | 397 | first_handle.detach(); |
1214 | 287 | Assert.areEqual(null, entry.getHTML('second')); | 398 | second_handle.detach(); |
1215 | 288 | }, | 399 | third_handle.detach(); |
1216 | 289 | 400 | fourth_handle.detach(); | |
1217 | 290 | test_update_cache_raises_events: function() { | 401 | |
1218 | 291 | // Check that the object changed event is raised. | 402 | Assert.areEqual('first', first_event.name); |
1219 | 292 | var raised_event = null; | 403 | Assert.areEqual('Hello', first_event.old_value); |
1220 | 293 | var handle = Y.on('lp:context:changed', function(e) { | 404 | Assert.areEqual('World<boo/>', first_event.new_value); |
1221 | 294 | raised_event = e; | 405 | Assert.areEqual( |
1222 | 295 | }); | 406 | '<p>World html<boo></boo></p>', |
1223 | 296 | var entry_repr = { | 407 | first_event.new_value_html.get('innerHTML')); |
1224 | 297 | 'first': "World", | 408 | Assert.areEqual(entry, first_event.entry); |
1225 | 298 | 'second': false, | 409 | |
1226 | 299 | 'third': 24, | 410 | Assert.areEqual('second', second_event.name); |
1227 | 300 | 'fourth': "Unaltered", | 411 | Assert.areEqual(true, second_event.old_value); |
1228 | 301 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link") | 412 | Assert.areEqual(false, second_event.new_value); |
1229 | 302 | }; | 413 | Assert.areEqual(entry, second_event.entry); |
1230 | 303 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | 414 | |
1231 | 304 | Y.lp.client.update_cache(entry); | 415 | Assert.areEqual('third', third_event.name); |
1232 | 305 | handle.detach(); | 416 | Assert.areEqual(42, third_event.old_value); |
1233 | 306 | Y.ArrayAssert.itemsAreEqual( | 417 | Assert.areEqual(24, third_event.new_value); |
1234 | 307 | ['first','second','third'], raised_event.fields_changed); | 418 | Assert.areEqual(entry, third_event.entry); |
1235 | 308 | Assert.areEqual(entry, raised_event.entry); | 419 | |
1236 | 309 | }, | 420 | Assert.isNull(fourth_event); |
1237 | 310 | 421 | }, | |
1238 | 311 | test_update_cache_raises_attribute_events: function() { | 422 | |
1239 | 312 | // Check that the object attribute changed events are raised. | 423 | test_update_cache_different_object: function() { |
1240 | 313 | var first_event = null; | 424 | // Check that the object is not modified if the entry has a |
1241 | 314 | var second_event = null; | 425 | // different link. |
1242 | 315 | var third_event = null; | 426 | var entry_repr = { |
1243 | 316 | var fourth_event = null; | 427 | 'first': "World", |
1244 | 317 | var first_handle = Y.on('lp:context:first:changed', function(e) { | 428 | 'second': false, |
1245 | 318 | first_event = e; | 429 | 'third': 24, |
1246 | 319 | }); | 430 | 'fourth': "Unaltered", |
1247 | 320 | var second_handle = Y.on('lp:context:second:changed', function(e) { | 431 | 'self_link': Y.lp.client.get_absolute_uri("different_link") |
1248 | 321 | second_event = e; | 432 | }; |
1249 | 322 | }); | 433 | var entry = new Y.lp.client.Entry( |
1250 | 323 | var third_handle = Y.on('lp:context:third:changed', function(e) { | 434 | null, entry_repr, "different_link"); |
1251 | 324 | third_event = e; | 435 | Y.lp.client.update_cache(entry); |
1252 | 325 | }); | 436 | Assert.areEqual("Hello", LP.cache.context.first); |
1253 | 326 | var fourth_handle = Y.on('lp:context:fourth:changed', function(e) { | 437 | Assert.areEqual(true, LP.cache.context.second); |
1254 | 327 | fourth_event = e; | 438 | Assert.areEqual(42, LP.cache.context.third); |
1255 | 328 | }); | 439 | Assert.areEqual("Unaltered", LP.cache.context.fourth); |
1256 | 329 | var entry_repr = { | 440 | } |
1257 | 330 | 'first': "World<boo/>", | 441 | })); |
1258 | 331 | 'second': false, | 442 | |
1259 | 332 | 'third': 24, | 443 | tests.suite.add(new Y.Test.Case({ |
1260 | 333 | 'fourth': "Unaltered", | 444 | name: "lp.client.notifications", |
1261 | 334 | 'self_link': Y.lp.client.get_absolute_uri("a_self_link"), | 445 | |
1262 | 335 | 'lp_html': {'first': "<p>World html<boo/></p>"} | 446 | setUp: function() { |
1263 | 336 | }; | 447 | this.client = new Y.lp.client.Launchpad(); |
1264 | 337 | var entry = new Y.lp.client.Entry(null, entry_repr, "a_self_link"); | 448 | this.args=[this.client, null, this._on_success, false]; |
1265 | 338 | Y.lp.client.update_cache(entry); | 449 | this.response = new Y.lp.testing.mockio.MockHttpResponse(); |
1266 | 339 | first_handle.detach(); | 450 | this.response.setResponseHeader('Content-Type', 'application/json'); |
1267 | 340 | second_handle.detach(); | 451 | }, |
1268 | 341 | third_handle.detach(); | 452 | |
1269 | 342 | fourth_handle.detach(); | 453 | _on_success: function(entry) { |
1270 | 343 | 454 | }, | |
1271 | 344 | Assert.areEqual('first', first_event.name); | 455 | |
1272 | 345 | Assert.areEqual('Hello', first_event.old_value); | 456 | _checkNotificationNode: function(node_class, node_text) { |
1273 | 346 | Assert.areEqual('World<boo/>', first_event.new_value); | 457 | var node = Y.one('div#request-notifications div'+node_class); |
1274 | 347 | Assert.areEqual( | 458 | Assert.areEqual(node_text, node.get("innerHTML")); |
1275 | 348 | '<p>World html<boo></boo></p>', | 459 | }, |
1276 | 349 | first_event.new_value_html.get('innerHTML')); | 460 | |
1277 | 350 | Assert.areEqual(entry, first_event.entry); | 461 | _checkNoNotificationNode: function(node_class) { |
1278 | 351 | 462 | var node = Y.one('div#request-notifications div'+node_class); | |
1279 | 352 | Assert.areEqual('second', second_event.name); | 463 | Assert.isNull(node); |
1280 | 353 | Assert.areEqual(true, second_event.old_value); | 464 | }, |
1281 | 354 | Assert.areEqual(false, second_event.new_value); | 465 | |
1282 | 355 | Assert.areEqual(entry, second_event.entry); | 466 | test_display_notifications: function() { |
1283 | 356 | 467 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; | |
1284 | 357 | Assert.areEqual('third', third_event.name); | 468 | this.response.setResponseHeader( |
1285 | 358 | Assert.areEqual(42, third_event.old_value); | 469 | 'X-Lazr-Notifications', notifications); |
1286 | 359 | Assert.areEqual(24, third_event.new_value); | 470 | Y.lp.client.wrap_resource_on_success( |
1287 | 360 | Assert.areEqual(entry, third_event.entry); | 471 | null, this.response, this.args); |
1288 | 361 | 472 | this._checkNotificationNode('.debug.message', 'A debug'); | |
1289 | 362 | Assert.isNull(fourth_event); | 473 | this._checkNotificationNode('.informational.message', 'An info'); |
1290 | 363 | }, | 474 | |
1291 | 364 | 475 | // Any subsequent request should preserve existing notifications. | |
1292 | 365 | test_update_cache_different_object: function() { | 476 | var new_notifications = '[ [30, "A warning"], [40, "An error"] ]'; |
1293 | 366 | // Check that the object is not modified if the entry has a different | 477 | this.response.setResponseHeader( |
1294 | 367 | // link. | 478 | 'X-Lazr-Notifications', new_notifications); |
1295 | 368 | var entry_repr = { | 479 | Y.lp.client.wrap_resource_on_success( |
1296 | 369 | 'first': "World", | 480 | null, this.response, this.args); |
1297 | 370 | 'second': false, | 481 | this._checkNotificationNode('.debug.message', 'A debug'); |
1298 | 371 | 'third': 24, | 482 | this._checkNotificationNode('.informational.message', 'An info'); |
1299 | 372 | 'fourth': "Unaltered", | 483 | this._checkNotificationNode('.warning.message', 'A warning'); |
1300 | 373 | 'self_link': Y.lp.client.get_absolute_uri("different_link") | 484 | this._checkNotificationNode('.error.message', 'An error'); |
1301 | 374 | }; | 485 | }, |
1302 | 375 | var entry = new Y.lp.client.Entry(null, entry_repr, "different_link"); | 486 | |
1303 | 376 | Y.lp.client.update_cache(entry); | 487 | test_remove_notifications: function() { |
1304 | 377 | Assert.areEqual("Hello", LP.cache.context.first); | 488 | // Make some notifications that will be removed. |
1305 | 378 | Assert.areEqual(true, LP.cache.context.second); | 489 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; |
1306 | 379 | Assert.areEqual(42, LP.cache.context.third); | 490 | this.response.setResponseHeader( |
1307 | 380 | Assert.areEqual("Unaltered", LP.cache.context.fourth); | 491 | 'X-Lazr-Notifications', notifications); |
1308 | 381 | } | 492 | Y.lp.client.wrap_resource_on_success( |
1309 | 382 | })); | 493 | null, this.response, this.args); |
1310 | 383 | 494 | ||
1311 | 384 | suite.add(new Y.Test.Case({ | 495 | // If the notifications header is just the string "null", then the |
1312 | 385 | name: "lp.client.notifications", | 496 | // current notifications are removed. |
1313 | 386 | 497 | this.response.setResponseHeader('X-Lazr-Notifications', "null"); | |
1314 | 387 | setUp: function() { | 498 | Y.lp.client.wrap_resource_on_success( |
1315 | 388 | this.client = new Y.lp.client.Launchpad(); | 499 | null, this.response, this.args); |
1316 | 389 | this.args=[this.client, null, this._on_success, false]; | 500 | this._checkNoNotificationNode('.debug.message'); |
1317 | 390 | this.response = new Y.lp.testing.mockio.MockHttpResponse(); | 501 | this._checkNoNotificationNode('.informational.message'); |
1318 | 391 | this.response.setResponseHeader('Content-Type', 'application/json'); | 502 | }, |
1319 | 392 | }, | 503 | |
1320 | 393 | 504 | test_notifications_not_removed: function() { | |
1321 | 394 | _on_success: function(entry) { | 505 | // Make some notifications that will be removed. |
1322 | 395 | }, | 506 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; |
1323 | 396 | 507 | this.response.setResponseHeader( | |
1324 | 397 | _checkNotificationNode: function(node_class, node_text) { | 508 | 'X-Lazr-Notifications', notifications); |
1325 | 398 | var node = Y.one('div#request-notifications div'+node_class); | 509 | Y.lp.client.wrap_resource_on_success( |
1326 | 399 | Assert.areEqual(node_text, node.get("innerHTML")); | 510 | null, this.response, this.args); |
1327 | 400 | }, | 511 | |
1328 | 401 | 512 | // If the response does not include a notifications header, then | |
1329 | 402 | _checkNoNotificationNode: function(node_class) { | 513 | // any pre-existing notifiactions are not removed. |
1330 | 403 | var node = Y.one('div#request-notifications div'+node_class); | 514 | this.response.setResponseHeader('X-Lazr-Notifications', null); |
1331 | 404 | Assert.isNull(node); | 515 | Y.lp.client.wrap_resource_on_success( |
1332 | 405 | }, | 516 | null, this.response, this.args); |
1333 | 406 | 517 | this._checkNotificationNode('.debug.message', 'A debug'); | |
1334 | 407 | test_display_notifications: function() { | 518 | this._checkNotificationNode('.informational.message', 'An info'); |
1335 | 408 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; | 519 | } |
1336 | 409 | this.response.setResponseHeader( | 520 | })); |
1337 | 410 | 'X-Lazr-Notifications', notifications); | 521 | |
1338 | 411 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 522 | tests.suite.add(new Y.Test.Case({ |
1339 | 412 | this._checkNotificationNode('.debug.message', 'A debug'); | 523 | name: "lp.client.forms", |
1340 | 413 | this._checkNotificationNode('.informational.message', 'An info'); | 524 | |
1341 | 414 | 525 | setUp: function() { | |
1342 | 415 | // Any subsequent request should preserve existing notifications. | 526 | var form = Y.one("#testform"); |
1343 | 416 | var new_notifications = '[ [30, "A warning"], [40, "An error"] ]'; | 527 | this.error_handler = new Y.lp.client.FormErrorHandler({ |
1344 | 417 | this.response.setResponseHeader( | 528 | form: form |
1345 | 418 | 'X-Lazr-Notifications', new_notifications); | 529 | }); |
1346 | 419 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 530 | }, |
1347 | 420 | this._checkNotificationNode('.debug.message', 'A debug'); | 531 | |
1348 | 421 | this._checkNotificationNode('.informational.message', 'An info'); | 532 | tearDown: function() { |
1349 | 422 | this._checkNotificationNode('.warning.message', 'A warning'); | 533 | this.error_handler.clearFormErrors(); |
1350 | 423 | this._checkNotificationNode('.error.message', 'An error'); | 534 | }, |
1351 | 424 | }, | 535 | |
1352 | 425 | 536 | test_form_error_handler_ignores_other_responses: function() { | |
1353 | 426 | test_remove_notifications: function() { | 537 | // Only XHR responses not containing validation data are ignored. |
1354 | 427 | // Make some notifications that will be removed. | 538 | var result = this.error_handler.handleError(0, { |
1355 | 428 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; | 539 | status: 400, |
1356 | 429 | this.response.setResponseHeader( | 540 | statusText: 'Not Validation' |
1357 | 430 | 'X-Lazr-Notifications', notifications); | 541 | }); |
1358 | 431 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 542 | Assert.isFalse(result); |
1359 | 432 | 543 | }, | |
1360 | 433 | // If the notifications header is just the string "null", then the | 544 | |
1361 | 434 | // current notifications are removed. | 545 | test_form_error_handler_handles_responses: function() { |
1362 | 435 | this.response.setResponseHeader('X-Lazr-Notifications', "null"); | 546 | // XHR responses containing validation data are processed. |
1363 | 436 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 547 | var error_data = { |
1364 | 437 | this._checkNoNotificationNode('.debug.message'); | 548 | 'error_summary': 'Some errors', |
1365 | 438 | this._checkNoNotificationNode('.informational.message'); | 549 | 'form_wide_errors': ['Form error'], |
1366 | 439 | }, | 550 | errors: {'field.test': 'Field error'} |
1367 | 440 | 551 | }; | |
1368 | 441 | test_notifications_not_removed: function() { | 552 | var result = this.error_handler.handleError(0, { |
1369 | 442 | // Make some notifications that will be removed. | 553 | status: 400, |
1370 | 443 | var notifications = '[ [10, "A debug"], [20, "An info"] ]'; | 554 | statusText: 'Validation', |
1371 | 444 | this.response.setResponseHeader( | 555 | responseText: Y.JSON.stringify(error_data) |
1372 | 445 | 'X-Lazr-Notifications', notifications); | 556 | }); |
1373 | 446 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 557 | Assert.isTrue(result); |
1374 | 447 | 558 | this._assert_error_rendering(); | |
1375 | 448 | // If the response does not include a notifications header, then any | 559 | }, |
1376 | 449 | // pre-existing notifiactions are not removed. | 560 | |
1377 | 450 | this.response.setResponseHeader('X-Lazr-Notifications', null); | 561 | _assert_error_rendering: function() { |
1378 | 451 | Y.lp.client.wrap_resource_on_success(null, this.response, this.args); | 562 | var label = Y.one('label[for="field.test"]'); |
1379 | 452 | this._checkNotificationNode('.debug.message', 'A debug'); | 563 | var field_error = label.next('div').next('.message'); |
1380 | 453 | this._checkNotificationNode('.informational.message', 'An info'); | 564 | Assert.isTrue(Y.one('#field_div').hasClass('error'), |
1381 | 454 | } | 565 | 'Field div has class error'); |
1382 | 455 | })); | 566 | Assert.areEqual('Field error', field_error.getContent()); |
1383 | 456 | 567 | Y.all('.error.message').each(function(error_node) { | |
1384 | 457 | suite.add(new Y.Test.Case({ | 568 | var error_message = error_node.getContent(); |
1385 | 458 | name: "lp.client.forms", | 569 | Assert.isTrue( |
1386 | 459 | 570 | error_message === '<p>Form error</p>' || | |
1387 | 460 | setUp: function() { | 571 | error_message === 'Some errors', |
1388 | 461 | var form = Y.one("#testform"); | 572 | 'Each error message has the correct content.'); |
1389 | 462 | this.error_handler = new Y.lp.client.FormErrorHandler({ | 573 | }); |
1390 | 463 | form: form | 574 | }, |
1391 | 464 | }); | 575 | |
1392 | 465 | }, | 576 | test_form_error_handler_renders_errors: function() { |
1393 | 466 | 577 | // Form errors are rendered correctly. | |
1394 | 467 | tearDown: function() { | 578 | this.error_handler.handleFormValidationError( |
1395 | 468 | this.error_handler.clearFormErrors(); | 579 | "Some errors", ["Form error"], |
1396 | 469 | }, | 580 | {'field.test': "Field error"}); |
1397 | 470 | 581 | this._assert_error_rendering(); | |
1398 | 471 | test_form_error_handler_ignores_other_responses: function() { | 582 | } |
1399 | 472 | // Only XHR responses not containing validation data are ignored. | 583 | })); |
1400 | 473 | var result = this.error_handler.handleError(0, { | 584 | }, '0.1', { |
1401 | 474 | status: 400, | 585 | requires: ['test', 'lp.testing.helpers', 'console', 'lp.client', |
1402 | 475 | statusText: 'Not Validation' | 586 | 'lp.testing.mockio', 'lp.client', 'escape'] |
1130 | 476 | }); | ||
1131 | 477 | Y.Assert.isFalse(result); | ||
1132 | 478 | }, | ||
1133 | 479 | |||
1134 | 480 | test_form_error_handler_handles_responses: function() { | ||
1135 | 481 | // XHR responses containing validation data are processed. | ||
1136 | 482 | var error_data = { | ||
1137 | 483 | 'error_summary': 'Some errors', | ||
1138 | 484 | 'form_wide_errors': ['Form error'], | ||
1139 | 485 | errors: {'field.test': 'Field error'} | ||
1140 | 486 | }; | ||
1141 | 487 | var result = this.error_handler.handleError(0, { | ||
1142 | 488 | status: 400, | ||
1143 | 489 | statusText: 'Validation', | ||
1144 | 490 | responseText: Y.JSON.stringify(error_data) | ||
1145 | 491 | }); | ||
1146 | 492 | Y.Assert.isTrue(result); | ||
1147 | 493 | this._assert_error_rendering(); | ||
1148 | 494 | }, | ||
1149 | 495 | |||
1150 | 496 | _assert_error_rendering: function() { | ||
1151 | 497 | var label = Y.one('label[for="field.test"]'); | ||
1152 | 498 | var field_error = label.next('div').next('.message'); | ||
1153 | 499 | Y.Assert.isTrue(Y.one('#field_div').hasClass('error'), | ||
1154 | 500 | 'Field div has class error'); | ||
1155 | 501 | Y.Assert.areEqual('Field error', field_error.getContent()); | ||
1156 | 502 | Y.all('.error.message').each(function(error_node) { | ||
1157 | 503 | var error_message = error_node.getContent(); | ||
1158 | 504 | Y.Assert.isTrue( | ||
1159 | 505 | error_message === '<p>Form error</p>' || | ||
1160 | 506 | error_message === 'Some errors', | ||
1161 | 507 | 'Each error message has the correct content.'); | ||
1162 | 508 | }); | ||
1163 | 509 | }, | ||
1164 | 510 | |||
1165 | 511 | test_form_error_handler_renders_errors: function() { | ||
1166 | 512 | // Form errors are rendered correctly. | ||
1167 | 513 | this.error_handler.handleFormValidationError( | ||
1168 | 514 | "Some errors", ["Form error"], | ||
1169 | 515 | {'field.test': "Field error"}); | ||
1170 | 516 | this._assert_error_rendering(); | ||
1171 | 517 | } | ||
1172 | 518 | })); | ||
1173 | 519 | |||
1174 | 520 | Y.lp.testing.Runner.run(suite); | ||
1175 | 521 | |||
1403 | 522 | }); | 587 | }); |
1404 | 523 | 588 | ||
1405 | === modified file 'lib/lp/app/javascript/tests/test_lp_client_integration.js' | |||
1406 | --- lib/lp/app/javascript/tests/test_lp_client_integration.js 2012-01-10 14:24:19 +0000 | |||
1407 | +++ lib/lp/app/javascript/tests/test_lp_client_integration.js 2012-07-24 16:58:23 +0000 | |||
1408 | @@ -1,4 +1,5 @@ | |||
1409 | 1 | YUI({ | 1 | YUI({ |
1410 | 2 | |||
1411 | 2 | base: '/+icing/yui/', | 3 | base: '/+icing/yui/', |
1412 | 3 | filter: 'raw', combine: false, fetchCSS: false | 4 | filter: 'raw', combine: false, fetchCSS: false |
1413 | 4 | }).use('test', | 5 | }).use('test', |
1414 | @@ -127,20 +128,6 @@ | |||
1415 | 127 | Y.Assert.areSame(1, config.result.total_size); | 128 | Y.Assert.areSame(1, config.result.total_size); |
1416 | 128 | }, | 129 | }, |
1417 | 129 | 130 | ||
1418 | 130 | test_named_get_uri: function() { | ||
1419 | 131 | var data = serverfixture.setup( | ||
1420 | 132 | this, 'create_product_with_milestone_and_login'); | ||
1421 | 133 | var client = new Y.lp.client.Launchpad({sync: true}); | ||
1422 | 134 | var config = makeTestConfig({parameters: {name: data.milestone.name}}); | ||
1423 | 135 | var product = new Y.lp.client.Entry( | ||
1424 | 136 | client, data.product, data.product.self_link); | ||
1425 | 137 | product.named_get('getMilestone', config); | ||
1426 | 138 | Y.Assert.isTrue(config.successful, 'Getting milestone failed'); | ||
1427 | 139 | var milestone = config.result; | ||
1428 | 140 | Y.Assert.isInstanceOf(Y.lp.client.Entry, milestone); | ||
1429 | 141 | Y.Assert.areSame(data.milestone_self_link, milestone.lp_original_uri); | ||
1430 | 142 | }, | ||
1431 | 143 | |||
1432 | 144 | test_named_post_integration: function() { | 131 | test_named_post_integration: function() { |
1433 | 145 | var data = serverfixture.setup(this, 'create_bug_and_login'); | 132 | var data = serverfixture.setup(this, 'create_bug_and_login'); |
1434 | 146 | var client = new Y.lp.client.Launchpad({sync: true}); | 133 | var client = new Y.lp.client.Launchpad({sync: true}); |
1435 | @@ -321,7 +308,7 @@ | |||
1436 | 321 | var team = config.result; | 308 | var team = config.result; |
1437 | 322 | Y.Assert.isInstanceOf(Y.lp.client.Entry, team); | 309 | Y.Assert.isInstanceOf(Y.lp.client.Entry, team); |
1438 | 323 | Y.Assert.areEqual('My lpclient team', team.get('display_name')); | 310 | Y.Assert.areEqual('My lpclient team', team.get('display_name')); |
1440 | 324 | Y.Assert.isTrue(/\~newlpclientteam$/.test(team.lp_original_uri)); | 311 | Y.Assert.isTrue(/\~newlpclientteam$/.test(team.uri)); |
1441 | 325 | }, | 312 | }, |
1442 | 326 | 313 | ||
1443 | 327 | test_collection_paged_named_get: function() { | 314 | test_collection_paged_named_get: function() { |
1444 | 328 | 315 | ||
1445 | === modified file 'lib/lp/registry/javascript/tests/test_structural_subscription.js' | |||
1446 | --- lib/lp/registry/javascript/tests/test_structural_subscription.js 2012-07-20 22:48:23 +0000 | |||
1447 | +++ lib/lp/registry/javascript/tests/test_structural_subscription.js 2012-07-24 16:58:23 +0000 | |||
1448 | @@ -234,7 +234,7 @@ | |||
1449 | 234 | Y.one('body').appendChild(this.content_node); | 234 | Y.one('body').appendChild(this.content_node); |
1450 | 235 | 235 | ||
1451 | 236 | this.bug_filter = { | 236 | this.bug_filter = { |
1453 | 237 | lp_original_uri: | 237 | uri: |
1454 | 238 | '/api/devel/firefox/+subscription/mark/+filter/28' | 238 | '/api/devel/firefox/+subscription/mark/+filter/28' |
1455 | 239 | }; | 239 | }; |
1456 | 240 | this.form_data = { | 240 | this.form_data = { |
1457 | 241 | 241 | ||
1458 | === modified file 'lib/lp/soyuz/javascript/lp_dynamic_dom_updater.js' | |||
1459 | --- lib/lp/soyuz/javascript/lp_dynamic_dom_updater.js 2012-07-05 14:28:57 +0000 | |||
1460 | +++ lib/lp/soyuz/javascript/lp_dynamic_dom_updater.js 2012-07-24 16:58:23 +0000 | |||
1461 | @@ -266,8 +266,8 @@ | |||
1462 | 266 | } | 266 | } |
1463 | 267 | 267 | ||
1464 | 268 | // Finally, call the LP api method as required... | 268 | // Finally, call the LP api method as required... |
1467 | 269 | if (uri){ | 269 | if (uri) { |
1468 | 270 | if (api_method_name){ | 270 | if (api_method_name) { |
1469 | 271 | this.get("lp_client").named_get(uri, | 271 | this.get("lp_client").named_get(uri, |
1470 | 272 | api_method_name, this._lp_api_config); | 272 | api_method_name, this._lp_api_config); |
1471 | 273 | } | 273 | } |
Looks good.