Merge lp:~allenap/launchpad/localpackagediffs-filter-by-package-set-bug-809786-refactor into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 13461
Proposed branch: lp:~allenap/launchpad/localpackagediffs-filter-by-package-set-bug-809786-refactor
Merge into: lp:launchpad
Diff against target: 518 lines (+171/-88)
6 files modified
Makefile (+11/-5)
lib/lp/app/javascript/testing/testrunner.js (+29/-0)
lib/lp/registry/browser/distroseries.py (+4/-0)
lib/lp/registry/javascript/distroseries.initseries.js (+55/-30)
lib/lp/registry/javascript/tests/test_distroseries.initseries.html (+29/-16)
lib/lp/registry/javascript/tests/test_distroseries.initseries.js (+43/-37)
To merge this branch: bzr merge lp:~allenap/launchpad/localpackagediffs-filter-by-package-set-bug-809786-refactor
Reviewer Review Type Date Requested Status
Benji York (community) code Approve
Review via email: mp+68233@code.launchpad.net

Commit message

[r=benji][bug=809786] Refactor some DistroSeries JavaScript and add a declarative approach for running YUI tests.

Description of the change

This moves a few DistroSeries related bits of JavaScript around and
fixes some lint. The only thing that really needs reviewing is the new
code in lib/lp/app/javascript/testing/testrunner.js. Its doc comment:

/**
 * Merely loading this script into a page will cause it to look for a
 * list of suites in the document using the selector ul#suites>li. If
 * found, the text within each node is considered to be a test module
 * name. This is then loaded, and its "suite" property passed to
 * Runner.run().
 *
 * Here's how to declare the suites to run:
 *
 * <ul id="suites">
 * <li>lp.registry.distroseries.initseries.test</li>
 * </ul>
 *
 */

The test is then declared as a regular YUI module instead of
containing test run code.

To post a comment you must log in.
Revision history for this message
Benji York (benji) wrote :

This branch looks good.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2011-07-15 15:55:34 +0000
3+++ Makefile 2011-07-18 11:54:37 +0000
4@@ -25,11 +25,15 @@
5 JS_BUILD := min
6 endif
7
8-JS_SOURCE_PATHS = -path './lib/lp/*/javascript/*' ! -path '*/tests/*' \
9- ! -path '*/testing/*' ! -path './lib/lp/services/*'
10+define JS_LP_PATHS
11+lib -path 'lib/lp/*/javascript/*' \
12+! -path '*/tests/*' ! -path '*/testing/*' \
13+! -path 'lib/lp/services/*'
14+endef
15+
16 JS_YUI := $(shell utilities/yui-deps.py $(JS_BUILD:raw=))
17 JS_OTHER := $(wildcard lib/canonical/launchpad/javascript/*/*.js)
18-JS_LP := $(shell find $(JS_SOURCE_PATHS) -name '*.js' ! -name '.*.js' )
19+JS_LP := $(shell find $(JS_LP_PATHS) -name '*.js')
20 JS_ALL := $(JS_YUI) $(JS_OTHER) $(JS_LP)
21 JS_OUT := $(LP_BUILT_JS_ROOT)/launchpad.js
22
23@@ -164,7 +168,7 @@
24
25 jsbuild_widget_css: bin/jsbuild
26 ${SHHH} bin/jsbuild \
27- --srcdir lib/lp/app/javascript \
28+ --srcdir lib/lp/app/javascript \
29 --builddir $(LP_BUILT_JS_ROOT)
30
31 $(JS_LP): jsbuild_widget_css
32@@ -425,7 +429,9 @@
33 copy-apache-config:
34 # We insert the absolute path to the branch-rewrite script
35 # into the Apache config as we copy the file into position.
36- sed -e 's,%BRANCH_REWRITE%,$(shell pwd)/scripts/branch-rewrite.py,' configs/development/local-launchpad-apache > /etc/apache2/sites-available/local-launchpad
37+ sed -e 's,%BRANCH_REWRITE%,$(shell pwd)/scripts/branch-rewrite.py,' \
38+ configs/development/local-launchpad-apache > \
39+ /etc/apache2/sites-available/local-launchpad
40 cp configs/development/local-vostok-apache \
41 /etc/apache2/sites-available/local-vostok
42 touch /var/tmp/bazaar.launchpad.dev/rewrite.log
43
44=== modified file 'lib/lp/app/javascript/testing/testrunner.js'
45--- lib/lp/app/javascript/testing/testrunner.js 2011-07-08 06:06:15 +0000
46+++ lib/lp/app/javascript/testing/testrunner.js 2011-07-18 11:54:37 +0000
47@@ -39,3 +39,32 @@
48 };
49
50 }, "0.1", {"requires": ["oop", "test", "console"]});
51+
52+
53+/**
54+ * Merely loading this script into a page will cause it to look for a
55+ * list of suites in the document using the selector ul#suites>li. If
56+ * found, the text within each node is considered to be a test module
57+ * name. This is then loaded, and its "suite" property passed to
58+ * Runner.run().
59+ *
60+ * Here's how to declare the suites to run:
61+ *
62+ * <ul id="suites">
63+ * <li>lp.registry.distroseries.initseries.test</li>
64+ * </ul>
65+ *
66+ */
67+YUI().use("event", function(Y) {
68+ Y.on("domready", function() {
69+ var suites = Y.all("ul#suites > li");
70+ Y.each(suites, function(suite_node) {
71+ var suite_name = suite_node.get("text");
72+ Y.use("lp.testing.runner", suite_name, function(y) {
73+ var module = y, parts = suite_name.split(".");
74+ while (parts.length > 0) { module = module[parts.shift()]; }
75+ y.lp.testing.Runner.run(module.suite);
76+ });
77+ });
78+ });
79+});
80
81=== modified file 'lib/lp/registry/browser/distroseries.py'
82--- lib/lp/registry/browser/distroseries.py 2011-07-08 09:06:24 +0000
83+++ lib/lp/registry/browser/distroseries.py 2011-07-18 11:54:37 +0000
84@@ -827,6 +827,8 @@
85 super(DistroSeriesDifferenceBaseView, self).initialize()
86
87 def initialize_sync_label(self, label):
88+ # XXX: GavinPanella 2011-07-13 bug=809985: Good thing the app servers
89+ # are running single threaded...
90 self.__class__.actions.byname['actions.sync'].label = label
91
92 @property
93@@ -861,6 +863,8 @@
94 SimpleTerm(diff, diff.id)
95 for diff in self.cached_differences.batch]
96 diffs_vocabulary = SimpleVocabulary(terms)
97+ # XXX: GavinPanella 2011-07-13 bug=809985: Good thing the app servers
98+ # are running single threaded...
99 choice = self.form_fields['selected_differences'].field.value_type
100 choice.vocabulary = diffs_vocabulary
101
102
103=== renamed file 'lib/lp/registry/javascript/distroseries.js' => 'lib/lp/registry/javascript/distroseries.initseries.js'
104--- lib/lp/registry/javascript/distroseries.js 2011-06-27 17:04:27 +0000
105+++ lib/lp/registry/javascript/distroseries.initseries.js 2011-07-18 11:54:37 +0000
106@@ -22,7 +22,9 @@
107 *
108 * @class FormRowWidget
109 */
110-var FormRowWidget = function() {
111+var FormRowWidget;
112+
113+FormRowWidget = function() {
114 FormRowWidget.superclass.constructor.apply(this, arguments);
115 };
116
117@@ -166,7 +168,9 @@
118 * can also be made an overlay, and a component and a pocket selected.
119 *
120 */
121-var ParentSeriesListWidget = function() {
122+var ParentSeriesListWidget;
123+
124+ParentSeriesListWidget = function() {
125 ParentSeriesListWidget
126 .superclass.constructor.apply(this, arguments);
127 };
128@@ -466,7 +470,9 @@
129 *
130 * @class ChoiceListWidget
131 */
132-var ChoiceListWidget = function() {
133+var ChoiceListWidget;
134+
135+ChoiceListWidget = function() {
136 ChoiceListWidget.superclass.constructor.apply(this, arguments);
137 };
138
139@@ -660,7 +666,9 @@
140 *
141 * @class ArchitecturesChoiceListWidget
142 */
143-var ArchitecturesChoiceListWidget = function() {
144+var ArchitecturesChoiceListWidget;
145+
146+ArchitecturesChoiceListWidget = function() {
147 ArchitecturesChoiceListWidget
148 .superclass.constructor.apply(this, arguments);
149 };
150@@ -726,14 +734,15 @@
151 */
152 remove_distroseries: function(distroseries_id) {
153 // Compute which das is only in the distroseries to be removed.
154- arch_to_remove = [];
155+ var arch_to_remove = [];
156 var das = this._distroseries[distroseries_id];
157 var i, ds, j;
158 for (i=0; i<das.entries.length; i++) {
159- remove_das = true;
160- arch = das.entries[i].get('architecture_tag');
161+ var remove_das = true;
162+ var arch = das.entries[i].get('architecture_tag');
163 for (ds in this._distroseries) {
164- if (ds !== distroseries_id) {
165+ if (this._distroseries.hasOwnProperty(ds) &&
166+ ds !== distroseries_id) {
167 var other_das = this._distroseries[ds];
168 for (j=0; j<other_das.entries.length; j++) {
169 var other_arch = other_das.entries[j].get(
170@@ -782,7 +791,9 @@
171 *
172 * @class SelectWidget
173 */
174-var SelectWidget = function() {
175+var SelectWidget;
176+
177+SelectWidget = function() {
178 SelectWidget.superclass.constructor.apply(this, arguments);
179 };
180
181@@ -949,7 +960,9 @@
182 *
183 * @class PackagesetPickerWidget
184 */
185-var PackagesetPickerWidget = function() {
186+var PackagesetPickerWidget;
187+
188+PackagesetPickerWidget = function() {
189 PackagesetPickerWidget
190 .superclass.constructor.apply(this, arguments);
191 };
192@@ -1144,7 +1157,9 @@
193 *
194 * @class FormActionsWidget
195 */
196-var FormActionsWidget = function() {
197+var FormActionsWidget;
198+
199+FormActionsWidget = function() {
200 FormActionsWidget
201 .superclass.constructor.apply(this, arguments);
202 };
203@@ -1234,7 +1249,9 @@
204 *
205 * @class DeriveDistroSeriesActionsWidget
206 */
207-var DeriveDistroSeriesActionsWidget = function() {
208+var DeriveDistroSeriesActionsWidget;
209+
210+DeriveDistroSeriesActionsWidget = function() {
211 DeriveDistroSeriesActionsWidget
212 .superclass.constructor.apply(this, arguments);
213 };
214@@ -1333,7 +1350,8 @@
215 add_parent_series(result);
216 };
217
218- parent_picker = Y.lp.app.picker.create('DistroSeriesDerivation', config);
219+ var parent_picker =
220+ Y.lp.app.picker.create('DistroSeriesDerivation', config);
221 parent_picker.show();
222 };
223
224@@ -1354,17 +1372,21 @@
225 *
226 * @function setup
227 */
228-namespace.setup = function() {
229- var form_actions = namespace.setupWidgets();
230- namespace.setupInteraction(form_actions);
231+namespace.setup = function(cache) {
232+ var form_actions = namespace.setupWidgets(cache);
233+ namespace.setupInteraction(form_actions, cache);
234 };
235
236 /**
237 * Setup the widgets objects and return the form object.
238 *
239 * @function setupWidgets
240+ * @param {Object} cache Specify the value cache to use. If not
241+ * specified, LP.cache is used. Intended chiefly for testing.
242 */
243-namespace.setupWidgets = function() {
244+namespace.setupWidgets = function(cache) {
245+ if (cache === undefined) { cache = LP.cache; }
246+
247 var form_container = Y.one("#initseries-form-container");
248 var form_table = form_container.one("table.form");
249 var form_table_body = form_table.append(Y.Node.create('<tbody />'));
250@@ -1394,7 +1416,7 @@
251 "architectures)."))
252 .render(form_table_body);
253 var packageset_choice = null;
254- if (LP.cache['is_first_derivation']) {
255+ if (cache.is_first_derivation) {
256 packageset_choice =
257 new PackagesetPickerWidget()
258 .set("name", "field.packagesets")
259@@ -1424,7 +1446,7 @@
260 .render(form_table_body);
261 var form_actions =
262 new DeriveDistroSeriesActionsWidget({
263- context: LP.cache.context,
264+ context: cache.context,
265 srcNode: form_container.one("div.actions"),
266 deriveFromChoices: parents_selection,
267 architectureChoice: architecture_choice,
268@@ -1440,10 +1462,14 @@
269 * Setup the interaction between the widgets.
270 *
271 * @function setupInteraction
272- * @param {DeriveDistroSeriesActionsWidget} The form widget containing all
273- * the other widgets.
274+ * @param {DeriveDistroSeriesActionsWidget} The form widget containing
275+ * all the other widgets.
276+ * @param {Object} cache Specify the value cache to use. If not
277+ * specified, LP.cache is used. Intended chiefly for testing.
278 */
279-namespace.setupInteraction = function(form_actions) {
280+namespace.setupInteraction = function(form_actions, cache) {
281+ if (cache === undefined) { cache = LP.cache; }
282+
283 // Wire up the add parent series link.
284 var link = Y.one('#add-parent-series');
285 if (Y.Lang.isValue(link)) {
286@@ -1458,7 +1484,7 @@
287 }
288 });
289
290- if (LP.cache['is_first_derivation']) {
291+ if (cache.is_first_derivation) {
292 // Wire the architecture and packageset pickers to the parent picker.
293 Y.on('parent_added', function(parent) {
294 form_actions.architectureChoice.add_distroseries(parent);
295@@ -1471,7 +1497,7 @@
296 });
297 }
298 else {
299- // Disable rebuilding if LP.cache['is_first_derivation'] is false.
300+ // Disable rebuilding if cache.is_first_derivation is false.
301 form_actions.packageCopyOptions.fieldNode
302 .one('input[value="Copy Source and Rebuild"]')
303 .set('disabled', 'disabled');
304@@ -1485,13 +1511,12 @@
305 "if you want to use all the available " +
306 "architectures)."));
307 form_actions.architectureChoice.add_distroseries(
308- LP.cache['previous_series']);
309+ cache.previous_series);
310 // Setup the pre-selected parents (parents from the previous series).
311- var index;
312- for (index in LP.cache['previous_parents']) {
313- form_actions.deriveFromChoices.add_parent(
314- LP.cache['previous_parents'][index]);
315- }
316+ Y.each(
317+ cache.previous_parents,
318+ form_actions.deriveFromChoices.add_parent,
319+ form_actions.deriveFromChoices);
320 }
321
322 // Wire up the form submission.
323
324=== renamed file 'lib/lp/registry/javascript/tests/test_distroseries.html' => 'lib/lp/registry/javascript/tests/test_distroseries.initseries.html'
325--- lib/lp/registry/javascript/tests/test_distroseries.html 2011-07-08 06:06:15 +0000
326+++ lib/lp/registry/javascript/tests/test_distroseries.initseries.html 2011-07-18 11:54:37 +0000
327@@ -6,27 +6,40 @@
328 <title>Launchpad DistroSeries</title>
329
330 <!-- YUI and test setup -->
331- <script type="text/javascript"
332- src="../../../../canonical/launchpad/icing/yui/yui/yui.js">
333- </script>
334 <link rel="stylesheet" href="../../../app/javascript/testing/test.css" />
335 <script type="text/javascript"
336+ src="../../../../canonical/launchpad/icing/yui/yui/yui.js"></script>
337+ <script type="text/javascript"
338 src="../../../app/javascript/testing/testrunner.js"></script>
339
340- <!-- Required modules -->
341- <script type="text/javascript" src="../../../app/javascript/client.js"></script>
342- <script type="text/javascript" src="../../../app/javascript/activator/activator.js"></script>
343- <script type="text/javascript" src="../../../app/javascript/anim/anim.js"></script>
344- <script type="text/javascript" src="../../../app/javascript/lazr/lazr.js"></script>
345- <script type="text/javascript" src="../../../app/javascript/overlay/overlay.js"></script>
346- <script type="text/javascript" src="../../../app/javascript/picker/picker.js"></script>
347- <script type="text/javascript" src="../../../app/javascript/picker/person_picker.js"></script>
348- <script type="text/javascript" src="../../../app/javascript/picker/picker_patcher.js"></script>
349- <!-- The module under test -->
350- <script type="text/javascript" src="../distroseries.js"></script>
351- <!-- The test suite -->
352- <script type="text/javascript" src="test_distroseries.js"></script>
353+ <!-- Required modules -->
354+ <script type="text/javascript"
355+ src="../../../app/javascript/client.js"></script>
356+ <script type="text/javascript"
357+ src="../../../app/javascript/activator/activator.js"></script>
358+ <script type="text/javascript"
359+ src="../../../app/javascript/anim/anim.js"></script>
360+ <script type="text/javascript"
361+ src="../../../app/javascript/lazr/lazr.js"></script>
362+ <script type="text/javascript"
363+ src="../../../app/javascript/overlay/overlay.js"></script>
364+ <script type="text/javascript"
365+ src="../../../app/javascript/picker/picker.js"></script>
366+ <script type="text/javascript"
367+ src="../../../app/javascript/picker/person_picker.js"></script>
368+ <script type="text/javascript"
369+ src="../../../app/javascript/picker/picker_patcher.js"></script>
370+
371+ <!-- The module under test -->
372+ <script type="text/javascript" src="../distroseries.initseries.js"></script>
373+
374+ <!-- The test suite -->
375+ <script type="text/javascript" src="test_distroseries.initseries.js"></script>
376+
377 </head>
378 <body class="yui3-skin-sam">
379+ <ul id="suites">
380+ <li>lp.registry.distroseries.initseries.test</li>
381+ </ul>
382 </body>
383 </html>
384
385=== renamed file 'lib/lp/registry/javascript/tests/test_distroseries.js' => 'lib/lp/registry/javascript/tests/test_distroseries.initseries.js'
386--- lib/lp/registry/javascript/tests/test_distroseries.js 2011-07-08 05:39:39 +0000
387+++ lib/lp/registry/javascript/tests/test_distroseries.initseries.js 2011-07-18 11:54:37 +0000
388@@ -1,9 +1,16 @@
389-/* Copyright (c) 2011, Canonical Ltd. All rights reserved. */
390-
391-YUI().use(
392- 'lp.testing.runner', 'test', 'console', 'node-event-simulate',
393- 'lp.registry.distroseries.initseries',
394- function(Y) {
395+/**
396+ * Copyright 2011 Canonical Ltd. This software is licensed under the
397+ * GNU Affero General Public License version 3 (see the file LICENSE).
398+ *
399+ * Tests for DistroSeries related stuff.
400+ *
401+ * @module lp.registry.distroseries
402+ * @submodule test
403+ */
404+
405+YUI.add('lp.registry.distroseries.initseries.test', function(Y) {
406+
407+ var namespace = Y.namespace('lp.registry.distroseries.initseries.test');
408
409 var Assert = Y.Assert;
410 var ArrayAssert = Y.ArrayAssert;
411@@ -440,6 +447,7 @@
412 },
413
414 testParentGetter: function() {
415+ var parent;
416 parent = {value: "4", title: "Hoary", api_uri: "ubuntu/hoary"};
417 this.widget.add_parent(parent);
418 parent = {value: "3", title: "Warty", api_uri: "ubuntu/warty"};
419@@ -495,7 +503,7 @@
420 Assert.isFunction(config.on.failure);
421 }
422 };
423- distroseries = {api_uri: "ubuntu/hoary", value: 3};
424+ var distroseries = {api_uri: "ubuntu/hoary", value: 3};
425 this.widget.add_distroseries(distroseries);
426 Assert.isTrue(io, "No IO initiated.");
427 },
428@@ -1056,6 +1064,10 @@
429 else if (name === "overlay_components") {
430 return ['restricted', null];
431 }
432+ else {
433+ Assert.fail("Unrecognized property: " + name);
434+ return null; // Keep lint quiet.
435+ }
436 }
437 },
438 architectureChoice: {
439@@ -1169,30 +1181,10 @@
440 Y.one('body').appendChild(node);
441 },
442
443- setUpFirstDerivation: function() {
444- window.LP = {cache: {is_first_derivation: true}};
445- },
446-
447- setUpNotFirstDerivation: function() {
448- window.LP = {cache:
449- {is_first_derivation: false,
450- previous_series: {
451- api_uri: '/ubuntu/natty',
452- value: '3',
453- title: 'Ubunty: Natty'},
454- previous_parents: [
455- {api_uri: '/debian/sid',
456- value: '4',
457- title: 'Debian: Sid'},
458- {api_uri: '/zz/aa',
459- value: '5',
460- title: 'ZZ: aa'}]}};
461- },
462-
463 testIsFirstDerivation: function() {
464- this.setUpFirstDerivation();
465- var form_actions = initseries.setupWidgets();
466- initseries.setupInteraction(form_actions);
467+ var cache = {is_first_derivation: true};
468+ var form_actions = initseries.setupWidgets(cache);
469+ initseries.setupInteraction(form_actions, cache);
470
471 // No pre-populated parent.
472 ArrayAssert.itemsAreEqual(
473@@ -1201,8 +1193,21 @@
474 },
475
476 testIsNotFirstDerivation: function() {
477- this.setUpNotFirstDerivation();
478- var form_actions = initseries.setupWidgets();
479+ var cache = {
480+ is_first_derivation: false,
481+ previous_series: {
482+ api_uri: '/ubuntu/natty',
483+ value: '3',
484+ title: 'Ubunty: Natty'
485+ },
486+ previous_parents: [
487+ {api_uri: '/debian/sid',
488+ value: '4', title: 'Debian: Sid'},
489+ {api_uri: '/zz/aa',
490+ value: '5', title: 'ZZ: aa'}
491+ ]
492+ };
493+ var form_actions = initseries.setupWidgets(cache);
494 // Monkeypatch LP client.
495 var client = {
496 get: function(path, config) {
497@@ -1220,7 +1225,7 @@
498 }
499 };
500 form_actions.architectureChoice.client = client;
501- initseries.setupInteraction(form_actions);
502+ initseries.setupInteraction(form_actions, cache);
503
504 // Parents are populated.
505 ArrayAssert.itemsAreEqual(
506@@ -1237,7 +1242,8 @@
507 };
508
509 suite.add(new Y.Test.Case(testDeriveDistroSeriesSetup));
510-
511- Y.lp.testing.Runner.run(suite);
512-
513-});
514+ namespace.suite = suite;
515+
516+}, "0.1", {"requires": [
517+ 'test', 'console', 'node-event-simulate',
518+ 'lp.registry.distroseries.initseries']});