Merge lp:~sinzui/launchpad/webkit-yuitest-love-1 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 13229
Proposed branch: lp:~sinzui/launchpad/webkit-yuitest-love-1
Merge into: lp:launchpad
Prerequisite: lp:~jcsackett/launchpad/these-tests-never-end
Diff against target: 1416 lines (+235/-356)
42 files modified
buildout-templates/bin/test.in (+3/-0)
lib/canonical/testing/layers.py (+10/-7)
lib/lp/app/javascript/tests/test_hide_comment.html (+1/-1)
lib/lp/app/javascript/tests/test_hide_comment.js (+1/-3)
lib/lp/app/javascript/tests/test_lp_client.js (+1/-3)
lib/lp/app/javascript/tests/test_lp_collapsibles.js (+1/-3)
lib/lp/app/javascript/tests/test_multicheckboxwidget.js (+14/-12)
lib/lp/app/javascript/tests/test_personpicker.html (+1/-1)
lib/lp/app/javascript/tests/test_personpicker.js (+1/-3)
lib/lp/app/javascript/tests/test_picker.js (+1/-3)
lib/lp/app/tests/test_yuitests.py (+2/-2)
lib/lp/app/windmill/testing.py (+1/-14)
lib/lp/bugs/javascript/tests/test_bug_notification_level.js (+3/-23)
lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js (+9/-8)
lib/lp/bugs/javascript/tests/test_me_too.js (+12/-10)
lib/lp/bugs/javascript/tests/test_subscriber.js (+1/-3)
lib/lp/bugs/javascript/tests/test_subscribers_list.js (+1/-3)
lib/lp/bugs/javascript/tests/test_subscription.js (+1/-3)
lib/lp/bugs/tests/test_yuitests.py (+2/-2)
lib/lp/bugs/windmill/testing.py (+1/-15)
lib/lp/code/javascript/tests/test_branchdiff.js (+1/-3)
lib/lp/code/javascript/tests/test_productseries_setbranch.js (+1/-3)
lib/lp/code/tests/test_yuitests.py (+2/-2)
lib/lp/code/windmill/testing.py (+1/-15)
lib/lp/registry/javascript/structural-subscription.js (+1/-1)
lib/lp/registry/javascript/tests/test_distroseries.js (+10/-6)
lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js (+3/-5)
lib/lp/registry/javascript/tests/test_milestone_table.js (+1/-3)
lib/lp/registry/javascript/tests/test_structural_subscription.html (+1/-0)
lib/lp/registry/javascript/tests/test_structural_subscription.js (+3/-5)
lib/lp/registry/javascript/tests/timeline-iframe.html (+1/-26)
lib/lp/registry/javascript/tests/timeline.js (+69/-74)
lib/lp/registry/tests/test_yuitests.py (+2/-2)
lib/lp/registry/windmill/testing.py (+1/-14)
lib/lp/soyuz/javascript/tests/archivesubscribers_index.js (+1/-3)
lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js (+1/-3)
lib/lp/soyuz/tests/test_yuitests.py (+2/-2)
lib/lp/soyuz/windmill/testing.py (+1/-14)
lib/lp/testing/__init__.py (+51/-32)
lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js (+12/-8)
lib/lp/translations/tests/test_yuitests.py (+2/-2)
lib/lp/translations/windmill/testing.py (+1/-14)
To merge this branch: bzr merge lp:~sinzui/launchpad/webkit-yuitest-love-1
Reviewer Review Type Date Requested Status
Deryck Hodge (community) code Approve
Review via email: mp+63884@code.launchpad.net

Description of the change

Use and embedded webkit browser to play YUI tests on a fast layer.

    Launchpad bug: https://bugs.launchpad.net/bugs/793680
    Pre-implementation: no one

This started as a spike to produce a way to run YUI tests in the standard
test environment. The current approach that leverages windmill and
firefox is too brittle to be trusted.

This branch uses a html5-capable browser object that can be driven by
python code. This branch has a lot of mechanical changes to address the
case when the test completes, but the dom is not yet rendered.

--------------------------------------------------------------------

RULES

    * From the spike which produced http://launchpad.net/html5-browser
      * Write a browser based on webkit.WebView to load the file.
      * Return the data when the page or script signals complete
    * Enable YUI tests to always run.
    * Update BaseYUITestLayer to extend FunctionalLayer
    * Update YUIUnitTestCase to use html5browser.Browser
      * Bonus, read the actual tests and report the individual failures.
    * ADDENDUM: YUI tests that use events can signal the test is complete
      /before/ the dom is rendered, this explains why the testrunner reports
      that they fail, but we see them pass.
    * ADDENDUM: Fix the broken YUI tests so that the branch can be landed
      with YUI tests automatically run.

QA

    * None

LINT

    buildout-templates/bin/test.in
    lib/canonical/testing/layers.py
    lib/lp/app/javascript/tests/test_hide_comment.html
    lib/lp/app/javascript/tests/test_hide_comment.js
    lib/lp/app/javascript/tests/test_lp_client.js
    lib/lp/app/javascript/tests/test_lp_collapsibles.js
    lib/lp/app/javascript/tests/test_multicheckboxwidget.js
    lib/lp/app/javascript/tests/test_picker.js
    lib/lp/bugs/javascript/tests/test_bug_notification_level.js
    lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js
    lib/lp/bugs/javascript/tests/test_me_too.js
    lib/lp/bugs/javascript/tests/test_subscriber.js
    lib/lp/bugs/javascript/tests/test_subscribers_list.js
    lib/lp/bugs/javascript/tests/test_subscription.js
    lib/lp/code/javascript/tests/test_branchdiff.js
    lib/lp/code/javascript/tests/test_productseries_setbranch.js
    lib/lp/registry/javascript/structural-subscription.js
    lib/lp/registry/javascript/tests/test_distroseries.js
    lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js
    lib/lp/registry/javascript/tests/test_milestone_table.js
    lib/lp/registry/javascript/tests/test_personpicker.html
    lib/lp/registry/javascript/tests/test_personpicker.js
    lib/lp/registry/javascript/tests/test_structural_subscription.html
    lib/lp/registry/javascript/tests/test_structural_subscription.js
    lib/lp/registry/javascript/tests/timeline-iframe.html
    lib/lp/registry/javascript/tests/timeline.js
    lib/lp/soyuz/javascript/tests/archivesubscribers_index.js
    lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js
    lib/lp/testing/__init__.py
    lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js
    lib/lp/translations/windmill/testing.py
    lib/lp/translations/windmill/tests/test_yuitests.py

There is a lot of lint in these file. I can fix this before I land.

TEST

    ./bin/test -vv --layer=YUI

IMPLEMENTATION

Always run YUI tests.
    buildout-templates/bin/test.in

YUI tests are simple tests. They do not require anything more than the basic
FunctionalLayer. No database, no app server, no windmill.
    lib/canonical/testing/layers.py

Updated to start of setup to use html5browser.Browser. Most tests passed!
Many timed out out after 5 seconds. I chose to set the timeout to 30 seconds,
since html5browser uses a signal instead of polling or waiting.
I discovered that many tests failed because the complete signal is raised
/before/ the log is rendered in the dom. I decided to return the data passed
to our handler as JSON, which I think is faster and more accurate.
I discovered that several tests had more than on failure, but the only the
first was reported. I change the assertion to report all the errors.
    lib/lp/testing/__init__.py

The test was failing because the setup uses invalid markup. Each browser makes
a choice when it encounters invalid markup, often choosing to rewrite the dom
to make it valid; the expected content will not be returned. The test also
failed to place the new node in the document so that it can be rendered.
    lib/lp/registry/javascript/tests/test_distroseries.js

The title and heading were reversed. That is to say, the test was looking
for a haystack in a needle.
    lib/lp/registry/javascript/tests/test_structural_subscription.js

I reported bug 794597 that I disabled the resize testcase. webkit will
not run this test because of XSS concerns. The other test cases are fine.
    lib/lp/registry/javascript/tests/timeline.js

This test was broken for two reason. The fakes that were passed to the test
did not provide the correct api, *and* the unlink_overlay object was never
passed. This was pretty difficult to debug because the code fail using
import_overlay was really about the missing argument, unlink_overlay.
The http test probably misbehaves because the test is run by webkit, but
on reading the code, I saw that the the method does not use http, it uses
lp, which works fine.
    lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js

Mechanical changes to signal that the test runner is complete. The log CSS was
broken in several tests because the test css was not loaded, or the page uses
old yui classes.
    lib/lp/app/javascript/tests/test_hide_comment.html
    lib/lp/app/javascript/tests/test_hide_comment.js
    lib/lp/app/javascript/tests/test_lp_client.js
    lib/lp/app/javascript/tests/test_lp_collapsibles.js
    lib/lp/app/javascript/tests/test_multicheckboxwidget.js
    lib/lp/app/javascript/tests/test_picker.js
    lib/lp/bugs/javascript/tests/test_bug_notification_level.js
    lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js
    lib/lp/bugs/javascript/tests/test_me_too.js
    lib/lp/bugs/javascript/tests/test_subscriber.js
    lib/lp/bugs/javascript/tests/test_subscribers_list.js
    lib/lp/bugs/javascript/tests/test_subscription.js
    lib/lp/code/javascript/tests/test_branchdiff.js
    lib/lp/code/javascript/tests/test_productseries_setbranch.js
    lib/lp/registry/javascript/structural-subscription.js
    lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js
    lib/lp/registry/javascript/tests/test_milestone_table.js
    lib/lp/registry/javascript/tests/test_personpicker.html
    lib/lp/registry/javascript/tests/test_personpicker.js
    lib/lp/registry/javascript/tests/test_structural_subscription.html
    lib/lp/registry/javascript/tests/timeline-iframe.html
    lib/lp/soyuz/javascript/tests/archivesubscribers_index.js
    lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

I see The last two files in the diff are from jc's branch. His is landing now.

Revision history for this message
Deryck Hodge (deryck) wrote :

Looks fantastic. Best pleasant surprise of the day, errr the month. Thanks for doing this, Curtis!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout-templates/bin/test.in'
2--- buildout-templates/bin/test.in 2011-04-17 23:53:37 +0000
3+++ buildout-templates/bin/test.in 2011-06-14 16:45:56 +0000
4@@ -98,6 +98,9 @@
5 except KeyError:
6 pass
7
8+# Suppress accessability warning because the test runner does not have UI.
9+os.environ['GTK_MODULES'] = ''
10+
11 # Silence spurious warnings. Note that this does not propagate to subprocesses
12 # so this is not always as easy as it seems. Warnings caused by our code that
13 # need to be silenced should have an accompanied Bug reference.
14
15=== modified file 'lib/canonical/testing/layers.py'
16--- lib/canonical/testing/layers.py 2011-04-14 02:06:27 +0000
17+++ lib/canonical/testing/layers.py 2011-06-14 16:45:56 +0000
18@@ -44,6 +44,7 @@
19 'TwistedAppServerLayer',
20 'TwistedLaunchpadZopelessLayer',
21 'TwistedLayer',
22+ 'YUITestLayer',
23 'ZopelessAppServerLayer',
24 'ZopelessDatabaseLayer',
25 'ZopelessLayer',
26@@ -362,7 +363,7 @@
27 frame = frame.f_back
28 BaseLayer.test_name = str(frame.f_locals['test'])
29 finally:
30- del frame # As per no-leak stack inspection in Python reference.
31+ del frame # As per no-leak stack inspection in Python reference.
32
33 @classmethod
34 @profiled
35@@ -438,7 +439,7 @@
36 # due to a leak because someone ignored the warnings.
37 if gc.garbage:
38 del gc.garbage[:]
39- gc.collect() # Expensive, so only do if there might be garbage.
40+ gc.collect() # Expensive, so only do if there might be garbage.
41 if gc.garbage:
42 BaseLayer.flagTestIsolationFailure(
43 "Test left uncollectable garbage\n"
44@@ -512,7 +513,7 @@
45 return frame.f_locals['self']
46 frame = frame.f_back
47 finally:
48- del frame # As per no-leak stack inspection in Python reference.
49+ del frame # As per no-leak stack inspection in Python reference.
50
51 @classmethod
52 def getCurrentTestCase(cls):
53@@ -530,7 +531,7 @@
54 frame = frame.f_back
55 return frame.f_locals['test']
56 finally:
57- del frame # As per no-leak stack inspection in Python reference.
58+ del frame # As per no-leak stack inspection in Python reference.
59
60 @classmethod
61 def appserver_config(cls):
62@@ -636,7 +637,7 @@
63 @classmethod
64 def purge(cls):
65 "Purge everything from our memcached."
66- MemcachedLayer.client.flush_all() # Only do this in tests!
67+ MemcachedLayer.client.flush_all() # Only do this in tests!
68
69
70 # We store a reference to the DB-API connect method here when we
71@@ -770,16 +771,18 @@
72
73 global _org_connect
74 _org_connect = psycopg2.connect
75+
76 # Proxy real connections with our mockdb.
77 def fake_connect(*args, **kw):
78 return cls.script.connect(_org_connect, *args, **kw)
79+
80 psycopg2.connect = fake_connect
81
82 @classmethod
83 @profiled
84 def uninstallMockDb(cls):
85 if cls.mockdb_mode is None:
86- return # Already uninstalled
87+ return # Already uninstalled
88
89 # Store results if we are recording
90 if cls.mockdb_mode == 'record':
91@@ -2105,5 +2108,5 @@
92 os.environ['WINDMILL_CONFIG_FILE'] = cls.config_file.name
93
94
95-class BaseYUITestLayer(BaseWindmillLayer):
96+class YUITestLayer(FunctionalLayer):
97 """The base class for all YUITests cases."""
98
99=== modified file 'lib/lp/app/javascript/tests/test_hide_comment.html'
100--- lib/lp/app/javascript/tests/test_hide_comment.html 2011-05-16 18:07:09 +0000
101+++ lib/lp/app/javascript/tests/test_hide_comment.html 2011-06-14 16:45:56 +0000
102@@ -22,7 +22,7 @@
103 <!-- The test suite -->
104 <script type="text/javascript" src="test_hide_comment.js"></script>
105 </head>
106- <body class="yui-skin-sam">
107+ <body class="yui3-skin-sam">
108
109 <!-- The example markup required by the script to run -->
110 <div class="boardComment">
111
112=== modified file 'lib/lp/app/javascript/tests/test_hide_comment.js'
113--- lib/lp/app/javascript/tests/test_hide_comment.js 2011-06-06 17:43:55 +0000
114+++ lib/lp/app/javascript/tests/test_hide_comment.js 2011-06-14 16:45:56 +0000
115@@ -81,9 +81,7 @@
116
117 // Lock, stock, and two smoking barrels.
118 var handle_complete = function(data) {
119- status_node = Y.Node.create(
120- '<p id="complete">Test status: complete</p>');
121- Y.one('body').appendChild(status_node);
122+ window.status = '::::' + JSON.stringify(data);
123 };
124 Y.Test.Runner.on('complete', handle_complete);
125 Y.Test.Runner.add(suite);
126
127=== modified file 'lib/lp/app/javascript/tests/test_lp_client.js'
128--- lib/lp/app/javascript/tests/test_lp_client.js 2011-04-26 20:18:38 +0000
129+++ lib/lp/app/javascript/tests/test_lp_client.js 2011-06-14 16:45:56 +0000
130@@ -284,9 +284,7 @@
131
132 // Lock, stock, and two smoking barrels.
133 var handle_complete = function(data) {
134- status_node = Y.Node.create(
135- '<p id="complete">Test status: complete</p>');
136- Y.one('body').appendChild(status_node);
137+ window.status = '::::' + JSON.stringify(data);
138 };
139 Y.Test.Runner.on('complete', handle_complete);
140 Y.Test.Runner.add(suite);
141
142=== modified file 'lib/lp/app/javascript/tests/test_lp_collapsibles.js'
143--- lib/lp/app/javascript/tests/test_lp_collapsibles.js 2011-04-06 16:21:30 +0000
144+++ lib/lp/app/javascript/tests/test_lp_collapsibles.js 2011-06-14 16:45:56 +0000
145@@ -325,9 +325,7 @@
146
147 // Lock, stock, and two smoking barrels.
148 var handle_complete = function(data) {
149- status_node = Y.Node.create(
150- '<p id="complete">Test status: complete</p>');
151- Y.one('body').appendChild(status_node);
152+ window.status = '::::' + JSON.stringify(data);
153 };
154 Y.Test.Runner.on('complete', handle_complete);
155 Y.Test.Runner.add(suite);
156
157=== modified file 'lib/lp/app/javascript/tests/test_multicheckboxwidget.js'
158--- lib/lp/app/javascript/tests/test_multicheckboxwidget.js 2011-04-05 03:15:54 +0000
159+++ lib/lp/app/javascript/tests/test_multicheckboxwidget.js 2011-06-14 16:45:56 +0000
160@@ -40,7 +40,7 @@
161 'patch': function(uri, representation, config, headers) {
162 var patch_content = new Y.lp.client.Entry();
163 var html = Y.Node.create("<span/>");
164- html.set('innerHTML', representation['multicheckboxtest']);
165+ html.set('innerHTML', representation.multicheckboxtest);
166 patch_content.set('lp_html', {'multicheckboxtest': html});
167 config.on.success(patch_content);
168 }
169@@ -52,10 +52,11 @@
170 createWidget: function(header) {
171 // Create a widget with some default data
172 var config = {"empty_display_value": "None"};
173- if( header != 'None' ) {
174- if( header == null )
175- header = 'Test multicheckbox widget:';
176- config['header'] = header;
177+ if (header !== 'None') {
178+ if (header === undefined) {
179+ header = 'Test multicheckbox widget:';
180+ }
181+ config.header = header;
182 }
183
184 var mock_client = new MockClient();
185@@ -93,8 +94,9 @@
186
187 test_default_header_value: function() {
188 // Check the default header text value.
189+ var header;
190 this.createWidget(header='None');
191- var header = Y.one('.yui3-widget-hd');
192+ header = Y.one('.yui3-widget-hd');
193 Y.Assert.areEqual(
194 header.get('innerHTML'), '<h2>Choose an item.</h2>');
195 },
196@@ -110,18 +112,20 @@
197 test_widget_has_correct_choice_data: function() {
198 // Make sure the checkboxes are rendered with expected data values..
199 this.createWidget();
200- for( var x=0; x<2; x++ ) {
201+ var x;
202+ for (x = 0; x < 2; x++) {
203 var item = Y.one(
204 'input[id="field.multicheckboxtest.'+x+'][type=checkbox]');
205 Y.Assert.areEqual(item.getAttribute('value'), x);
206- Y.Assert.areEqual(item.get('checked'), x==0);
207+ Y.Assert.areEqual(item.get('checked'), x === 0);
208 }
209 },
210
211 test_widget_has_correct_choice_text: function() {
212 // Make sure the checkboxes are rendered with expected label text.
213 this.createWidget();
214- for( var x=0; x<2; x++ ) {
215+ var x;
216+ for (x = 0; x < 2; x++) {
217 var item = Y.one('label[for="field.multicheckboxtest.'+x+']');
218 var txt = item.get('textContent');
219 //remove any &nbsp in the text
220@@ -167,9 +171,7 @@
221
222 // Lock, stock, and two smoking barrels.
223 var handle_complete = function(data) {
224- status_node = Y.Node.create(
225- '<p id="complete">Test status: complete</p>');
226- Y.one('body').appendChild(status_node);
227+ window.status = '::::' + JSON.stringify(data);
228 };
229 Y.Test.Runner.on('complete', handle_complete);
230 Y.Test.Runner.add(suite);
231
232=== modified file 'lib/lp/app/javascript/tests/test_personpicker.html'
233--- lib/lp/app/javascript/tests/test_personpicker.html 2011-06-07 15:54:47 +0000
234+++ lib/lp/app/javascript/tests/test_personpicker.html 2011-06-14 16:45:56 +0000
235@@ -22,7 +22,7 @@
236 <!-- The test suite -->
237 <script type="text/javascript" src="test_personpicker.js"></script>
238 </head>
239- <body class="yui-skin-sam">
240+ <body class="yui3-skin-sam">
241
242 <!-- The example markup required by the script to run -->
243 <input type="text" value="" id="choose"
244
245=== modified file 'lib/lp/app/javascript/tests/test_personpicker.js'
246--- lib/lp/app/javascript/tests/test_personpicker.js 2011-06-09 23:04:06 +0000
247+++ lib/lp/app/javascript/tests/test_personpicker.js 2011-06-14 16:45:56 +0000
248@@ -71,9 +71,7 @@
249
250 // Lock, stock, and two smoking barrels.
251 var handle_complete = function(data) {
252- status_node = Y.Node.create(
253- '<p id="complete">Test status: complete</p>');
254- Y.one('body').appendChild(status_node);
255+ window.status = '::::' + JSON.stringify(data);
256 };
257 Y.Test.Runner.on('complete', handle_complete);
258 Y.Test.Runner.add(suite);
259
260=== modified file 'lib/lp/app/javascript/tests/test_picker.js'
261--- lib/lp/app/javascript/tests/test_picker.js 2011-06-09 08:39:57 +0000
262+++ lib/lp/app/javascript/tests/test_picker.js 2011-06-14 16:45:56 +0000
263@@ -308,9 +308,7 @@
264
265 // Lock, stock, and two smoking barrels.
266 var handle_complete = function(data) {
267- status_node = Y.Node.create(
268- '<p id="complete">Test status: complete</p>');
269- Y.one('body').appendChild(status_node);
270+ window.status = '::::' + JSON.stringify(data);
271 };
272 Y.Test.Runner.on('complete', handle_complete);
273 Y.Test.Runner.add(suite);
274
275=== renamed file 'lib/lp/app/windmill/tests/test_yuitests.py' => 'lib/lp/app/tests/test_yuitests.py'
276--- lib/lp/app/windmill/tests/test_yuitests.py 2011-04-14 21:58:31 +0000
277+++ lib/lp/app/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
278@@ -6,7 +6,7 @@
279 __metaclass__ = type
280 __all__ = []
281
282-from lp.app.windmill.testing import AppYUITestLayer
283+from canonical.testing.layers import YUITestLayer
284 from lp.testing import (
285 build_yui_unittest_suite,
286 YUIUnitTestCase,
287@@ -15,7 +15,7 @@
288
289 class AppYUIUnitTestCase(YUIUnitTestCase):
290
291- layer = AppYUITestLayer
292+ layer = YUITestLayer
293 suite_name = 'AppYUIUnitTests'
294
295
296
297=== modified file 'lib/lp/app/windmill/testing.py'
298--- lib/lp/app/windmill/testing.py 2011-04-14 21:58:31 +0000
299+++ lib/lp/app/windmill/testing.py 2011-06-14 16:45:56 +0000
300@@ -6,14 +6,10 @@
301 __metaclass__ = type
302 __all__ = [
303 'AppWindmillLayer',
304- 'AppYUITestLayer',
305 ]
306
307
308-from canonical.testing.layers import (
309- BaseWindmillLayer,
310- BaseYUITestLayer,
311- )
312+from canonical.testing.layers import BaseWindmillLayer
313
314
315 class AppWindmillLayer(BaseWindmillLayer):
316@@ -23,12 +19,3 @@
317 def setUp(cls):
318 cls.base_url = cls.appserver_root_url()
319 super(AppWindmillLayer, cls).setUp()
320-
321-
322-class AppYUITestLayer(BaseYUITestLayer):
323- """Layer for Code YUI tests."""
324-
325- @classmethod
326- def setUp(cls):
327- cls.base_url = cls.appserver_root_url()
328- super(AppYUITestLayer, cls).setUp()
329
330=== modified file 'lib/lp/bugs/javascript/tests/test_bug_notification_level.js'
331--- lib/lp/bugs/javascript/tests/test_bug_notification_level.js 2011-04-28 07:35:01 +0000
332+++ lib/lp/bugs/javascript/tests/test_bug_notification_level.js 2011-06-14 16:45:56 +0000
333@@ -219,7 +219,8 @@
334 },
335
336 test_value_undefined: function() {
337- // When there is no selected radio button, returned value is undefined.
338+ // When there is no selected radio button, the returned value
339+ // is undefined.
340 var level_node = Y.Node.create('<div></div>');
341 var node = Y.Node.create('<div></div>');
342 node.appendChild(createRadioButton(this.MY_NAME));
343@@ -349,25 +350,6 @@
344 }, 50);
345 },
346
347- test_no_level_options: function() {
348- // When there are no level options, no animation is set-up.
349- var options_node = Y.Node.create('<div></div>');
350- options_node.appendChild(createRadioButton(this.MY_NAME, true));
351-
352- var event_fired = false;
353- Y.on('bugnotificationlevel:contentready', function () {
354- event_fired = true;
355- });
356-
357- this.root.appendChild(options_node);
358- Y.Assert.isFalse(module.setup());
359-
360- // Event is fired regardless.
361- this.wait(function() {
362- Y.Assert.isTrue(event_fired);
363- }, 50);
364- },
365-
366 test_single_option_no_animation: function() {
367 // When there is only a single option, no animation is set-up.
368 var level_node = Y.Node.create('<div></div>')
369@@ -444,9 +426,7 @@
370 }));
371
372 var handle_complete = function(data) {
373- status_node = Y.Node.create(
374- '<p id="complete">Test status: complete</p>');
375- Y.one('body').appendChild(status_node);
376+ window.status = '::::' + JSON.stringify(data);
377 };
378 Y.Test.Runner.on('complete', handle_complete);
379 Y.Test.Runner.add(suite);
380
381=== modified file 'lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js'
382--- lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js 2011-04-29 01:55:28 +0000
383+++ lib/lp/bugs/javascript/tests/test_filebug_dupfinder.js 2011-06-14 16:45:56 +0000
384@@ -52,11 +52,11 @@
385 Y.one("#possible-duplicates").set('innerHTML', '');
386 Y.one(Y.DOM.byId('field.comment')).set('value', '');
387 var node = Y.one(Y.DOM.byId('field.search'));
388- if (node != null) {
389+ if (node !== null) {
390 node.set('value', '');
391 }
392 node = Y.one(Y.DOM.byId('field.title'));
393- if (node != null) {
394+ if (node !== null) {
395 node.set('value', '');
396 }
397 Y.one('#filebug-form-container').addClass('transparent')
398@@ -118,7 +118,8 @@
399 this.config.yio.io.doAfter = function() {
400 // Check the expected io calls have been made.
401 Y.ArrayAssert.itemsAreEqual(
402- ['https://bugs.launchpad.dev/foo/+filebug-show-similar?title=foo'],
403+ ['https://bugs.launchpad.dev/' +
404+ 'foo/+filebug-show-similar?title=foo'],
405 this.config.yio.calls);
406 // filebug container should be visible after the dup search
407 this.assertIsVisible(null, '#filebug-form-container');
408@@ -303,8 +304,10 @@
409 Y.Assert.areEqual(
410 'an error occurred', comment_text.get('value'));
411 Y.ArrayAssert.itemsAreEqual(
412- ['https://bugs.launchpad.dev/foo/+filebug-show-similar?title=foo',
413- 'https://bugs.launchpad.dev/bar/+filebug-show-similar?title=foo'],
414+ ['https://bugs.launchpad.dev/' +
415+ 'foo/+filebug-show-similar?title=foo',
416+ 'https://bugs.launchpad.dev/' +
417+ 'bar/+filebug-show-similar?title=foo'],
418 this.config.yio.calls);
419 };
420 simulate(search_button, undefined, 'click');
421@@ -317,9 +320,7 @@
422 }));
423
424 var handle_complete = function(data) {
425- status_node = Y.Node.create(
426- '<p id="complete">Test status: complete</p>');
427- Y.one('body').appendChild(status_node);
428+ window.status = '::::' + JSON.stringify(data);
429 };
430 Y.Test.Runner.on('complete', handle_complete);
431 Y.Test.Runner.add(suite);
432
433=== modified file 'lib/lp/bugs/javascript/tests/test_me_too.js'
434--- lib/lp/bugs/javascript/tests/test_me_too.js 2011-02-28 00:54:30 +0000
435+++ lib/lp/bugs/javascript/tests/test_me_too.js 2011-06-14 16:45:56 +0000
436@@ -43,7 +43,7 @@
437 var inpage = Y.Node.create([
438 '<span id="affectsmetoo">',
439 ' <span class="static">',
440- ' <img src="https://bugs.launchpad.net/@@/flame-icon" alt="" />',
441+ ' <img src="https://bugs.launchpad.net/@@/flame-icon" alt=""/>',
442 ' This bug affects me too',
443 ' <a href="+affectsmetoo">',
444 ' <img class="editicon" alt="Edit"',
445@@ -54,8 +54,8 @@
446 ' <img class="editicon" alt="Edit"',
447 ' src="https://bugs.launchpad.net/@@/edit" />',
448 ' <a href="+affectsmetoo" class="js-action"',
449- ' ><span class="value">Does this bug affect you?</span></a>',
450- ' <img src="https://bugs.launchpad.net/@@/flame-icon" alt=""/>',
451+ ' ><span class="value">Does this bug affect you?</span></a>',
452+ ' <img src="https://bugs.launchpad.net/@@/flame-icon" alt=""/>',
453 ' </span>',
454 '</span>'].join(''));
455 Y.one("body").appendChild(inpage);
456@@ -64,7 +64,8 @@
457 contentBox: me_too_content, value: null,
458 elementToFlash: me_too_content, others_affected_count: 5
459 };
460- this.choice_edit = new Y.lp.bugs.bugtask_index._MeTooChoiceSource(this.config);
461+ this.choice_edit = new Y.lp.bugs.bugtask_index._MeTooChoiceSource(
462+ this.config);
463 this.choice_edit.render();
464 },
465
466@@ -81,7 +82,8 @@
467 test_is_inline: function() {
468 var display = this.choice_edit.get('boundingBox').getStyle('display');
469 Assert.areEqual(
470- display, 'inline', "Not displayed inline, display is: " + display);
471+ display, 'inline',
472+ "Not displayed inline, display is: " + display);
473 },
474
475 /**
476@@ -135,7 +137,8 @@
477 simulate(this.choice_edit.get('boundingBox'), '.value', 'click');
478 Assert.isNull(
479 edit_icon.get('src').match(/\/spinner$/),
480- "The edit icon is displaying a spinner after opening the choice list.");
481+ "The edit icon is displaying a spinner after opening the " +
482+ "choice list.");
483 // The spinner should be visible during the interval between a
484 // choice being made and a response coming back from Launchpad
485 // that the choice has been saved.
486@@ -159,7 +162,8 @@
487 // saved.
488 Assert.isNull(
489 edit_icon.get('src').match(/\/spinner$/),
490- "The edit icon is displaying a spinner once the choice has been made.");
491+ "The edit icon is displaying a spinner once the choice has " +
492+ "been made.");
493 },
494
495 test__getSourceNames: function() {
496@@ -198,9 +202,7 @@
497 }));
498
499 var handle_complete = function(data) {
500- status_node = Y.Node.create(
501- '<p id="complete">Test status: complete</p>');
502- Y.one('body').appendChild(status_node);
503+ window.status = '::::' + JSON.stringify(data);
504 };
505 Y.Test.Runner.on('complete', handle_complete);
506 Y.Test.Runner.add(suite);
507
508=== modified file 'lib/lp/bugs/javascript/tests/test_subscriber.js'
509--- lib/lp/bugs/javascript/tests/test_subscriber.js 2011-04-22 16:59:16 +0000
510+++ lib/lp/bugs/javascript/tests/test_subscriber.js 2011-06-14 16:45:56 +0000
511@@ -273,9 +273,7 @@
512
513
514 var handle_complete = function(data) {
515- status_node = Y.Node.create(
516- '<p id="complete">Test status: complete</p>');
517- Y.one('body').appendChild(status_node);
518+ window.status = '::::' + JSON.stringify(data);
519 };
520 Y.Test.Runner.on('complete', handle_complete);
521 Y.Test.Runner.add(suite);
522
523=== modified file 'lib/lp/bugs/javascript/tests/test_subscribers_list.js'
524--- lib/lp/bugs/javascript/tests/test_subscribers_list.js 2011-05-18 18:34:19 +0000
525+++ lib/lp/bugs/javascript/tests/test_subscribers_list.js 2011-06-14 16:45:56 +0000
526@@ -329,9 +329,7 @@
527
528
529 var handle_complete = function(data) {
530- status_node = Y.Node.create(
531- '<p id="complete">Test status: complete</p>');
532- Y.one('body').appendChild(status_node);
533+ window.status = '::::' + JSON.stringify(data);
534 };
535 Y.Test.Runner.on('complete', handle_complete);
536 Y.Test.Runner.add(suite);
537
538=== modified file 'lib/lp/bugs/javascript/tests/test_subscription.js'
539--- lib/lp/bugs/javascript/tests/test_subscription.js 2011-06-02 04:22:25 +0000
540+++ lib/lp/bugs/javascript/tests/test_subscription.js 2011-06-14 16:45:56 +0000
541@@ -2772,9 +2772,7 @@
542
543
544 var handle_complete = function(data) {
545- status_node = Y.Node.create(
546- '<p id="complete">Test status: complete</p>');
547- Y.one('body').appendChild(status_node);
548+ window.status = '::::' + JSON.stringify(data);
549 };
550 Y.Test.Runner.on('complete', handle_complete);
551 Y.Test.Runner.add(suite);
552
553=== renamed file 'lib/lp/bugs/windmill/tests/test_yuitests.py' => 'lib/lp/bugs/tests/test_yuitests.py'
554--- lib/lp/bugs/windmill/tests/test_yuitests.py 2011-04-14 21:58:31 +0000
555+++ lib/lp/bugs/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
556@@ -6,7 +6,7 @@
557 __metaclass__ = type
558 __all__ = []
559
560-from lp.bugs.windmill.testing import BugsYUITestLayer
561+from canonical.testing.layers import YUITestLayer
562 from lp.testing import (
563 build_yui_unittest_suite,
564 YUIUnitTestCase,
565@@ -15,7 +15,7 @@
566
567 class BugsYUIUnitTestCase(YUIUnitTestCase):
568
569- layer = BugsYUITestLayer
570+ layer = YUITestLayer
571 suite_name = 'BugsYUIUnitTests'
572
573
574
575=== modified file 'lib/lp/bugs/windmill/testing.py'
576--- lib/lp/bugs/windmill/testing.py 2011-04-14 21:58:31 +0000
577+++ lib/lp/bugs/windmill/testing.py 2011-06-14 16:45:56 +0000
578@@ -6,14 +6,10 @@
579 __metaclass__ = type
580 __all__ = [
581 'BugsWindmillLayer',
582- 'BugsYUITestLayer',
583 ]
584
585
586-from canonical.testing.layers import (
587- BaseWindmillLayer,
588- BaseYUITestLayer,
589- )
590+from canonical.testing.layers import BaseWindmillLayer
591
592
593 class BugsWindmillLayer(BaseWindmillLayer):
594@@ -24,13 +20,3 @@
595 cls.facet = 'bugs'
596 cls.base_url = cls.appserver_root_url(cls.facet)
597 super(BugsWindmillLayer, cls).setUp()
598-
599-
600-class BugsYUITestLayer(BaseYUITestLayer):
601- """Layer for Code YUI tests."""
602-
603- @classmethod
604- def setUp(cls):
605- cls.facet = 'bugs'
606- cls.base_url = cls.appserver_root_url(cls.facet)
607- super(BugsYUITestLayer, cls).setUp()
608
609=== modified file 'lib/lp/code/javascript/tests/test_branchdiff.js'
610--- lib/lp/code/javascript/tests/test_branchdiff.js 2011-05-05 20:10:16 +0000
611+++ lib/lp/code/javascript/tests/test_branchdiff.js 2011-06-14 16:45:56 +0000
612@@ -52,9 +52,7 @@
613 }));
614
615 var handle_complete = function(data) {
616- status_node = Y.Node.create(
617- '<p id="complete">Test status: complete</p>');
618- Y.one('body').appendChild(status_node);
619+ window.status = '::::' + JSON.stringify(data);
620 };
621 Y.Test.Runner.on('complete', handle_complete);
622 Y.Test.Runner.add(suite);
623
624=== modified file 'lib/lp/code/javascript/tests/test_productseries_setbranch.js'
625--- lib/lp/code/javascript/tests/test_productseries_setbranch.js 2011-02-03 21:14:05 +0000
626+++ lib/lp/code/javascript/tests/test_productseries_setbranch.js 2011-06-14 16:45:56 +0000
627@@ -231,9 +231,7 @@
628
629 // Lock, stock, and two smoking barrels.
630 var handle_complete = function(data) {
631- status_node = Y.Node.create(
632- '<p id="complete">Test status: complete</p>');
633- Y.one('body').appendChild(status_node);
634+ window.status = '::::' + JSON.stringify(data);
635 };
636 Y.Test.Runner.on('complete', handle_complete);
637 Y.Test.Runner.add(suite);
638
639=== renamed file 'lib/lp/code/windmill/tests/test_yuitests.py' => 'lib/lp/code/tests/test_yuitests.py'
640--- lib/lp/code/windmill/tests/test_yuitests.py 2011-04-14 21:58:31 +0000
641+++ lib/lp/code/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
642@@ -6,7 +6,7 @@
643 __metaclass__ = type
644 __all__ = []
645
646-from lp.code.windmill.testing import CodeYUITestLayer
647+from canonical.testing.layers import YUITestLayer
648 from lp.testing import (
649 build_yui_unittest_suite,
650 YUIUnitTestCase,
651@@ -15,7 +15,7 @@
652
653 class CodeYUIUnitTestCase(YUIUnitTestCase):
654
655- layer = CodeYUITestLayer
656+ layer = YUITestLayer
657 suite_name = 'CodeYUIUnitTests'
658
659
660
661=== modified file 'lib/lp/code/windmill/testing.py'
662--- lib/lp/code/windmill/testing.py 2011-04-14 21:58:31 +0000
663+++ lib/lp/code/windmill/testing.py 2011-06-14 16:45:56 +0000
664@@ -6,14 +6,10 @@
665 __metaclass__ = type
666 __all__ = [
667 'CodeWindmillLayer',
668- 'CodeYUITestLayer',
669 ]
670
671
672-from canonical.testing.layers import (
673- BaseWindmillLayer,
674- BaseYUITestLayer,
675- )
676+from canonical.testing.layers import BaseWindmillLayer
677
678
679 class CodeWindmillLayer(BaseWindmillLayer):
680@@ -24,13 +20,3 @@
681 cls.facet = 'code'
682 cls.base_url = cls.appserver_root_url(cls.facet)
683 super(CodeWindmillLayer, cls).setUp()
684-
685-
686-class CodeYUITestLayer(BaseYUITestLayer):
687- """Layer for Code YUI tests."""
688-
689- @classmethod
690- def setUp(cls):
691- cls.facet = 'code'
692- cls.base_url = cls.appserver_root_url(cls.facet)
693- super(CodeYUITestLayer, cls).setUp()
694
695=== modified file 'lib/lp/registry/javascript/structural-subscription.js'
696--- lib/lp/registry/javascript/structural-subscription.js 2011-06-03 20:52:27 +0000
697+++ lib/lp/registry/javascript/structural-subscription.js 2011-06-14 16:45:56 +0000
698@@ -1648,7 +1648,7 @@
699 */
700 function get_team_info(form_data) {
701 var is_team = (form_data.recipient[0] === "team");
702- var link, team, title, url;
703+ var link, team, title, url, has_preferredemail;
704 if (is_team) {
705 link = form_data.team[0];
706 team = get_team(link);
707
708=== modified file 'lib/lp/registry/javascript/tests/test_distroseries.js'
709--- lib/lp/registry/javascript/tests/test_distroseries.js 2011-06-09 09:11:19 +0000
710+++ lib/lp/registry/javascript/tests/test_distroseries.js 2011-06-14 16:45:56 +0000
711@@ -333,11 +333,16 @@
712 },
713
714 testBuildSelector: function() {
715- node = Y.Node.create(
716- '<tr><input type="checkbox"/><td class="test" /></tr>');
717+ var node = Y.Node.create(
718+ '<tr id="snarf">' +
719+ '<td><input type="checkbox"/></td>' +
720+ '<td class="test"></td>' +
721+ '</tr>');
722+ Y.one('body').append(node);
723+ node = Y.one('#snarf');
724 this.widget.build_selector(node, ['a', 'b', 'c'], 'test');
725 Assert.areEqual(
726- '<input type="checkbox">' +
727+ '<td><input type="checkbox"></td>' +
728 '<td class="test">' +
729 '<select disabled="disabled">' +
730 '<option value="a">a</option>' +
731@@ -345,6 +350,7 @@
732 '<option value="c">c</option>' +
733 '</select>' +
734 '</td>', node.get('innerHTML'));
735+ Y.one('body').removeChild(node);
736 },
737
738 testAddParentAddsLine: function() {
739@@ -1136,9 +1142,7 @@
740
741 // Lock, stock, and two smoking barrels.
742 var handle_complete = function(data) {
743- status_node = Y.Node.create(
744- '<p id="complete">Test status: complete</p>');
745- Y.one('body').appendChild(status_node);
746+ window.status = '::::' + JSON.stringify(data);
747 };
748 Y.Test.Runner.on('complete', handle_complete);
749 Y.Test.Runner.add(suite);
750
751=== modified file 'lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js'
752--- lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js 2011-05-12 12:09:17 +0000
753+++ lib/lp/registry/javascript/tests/test_distroseriesdifferences_details.js 2011-06-14 16:45:56 +0000
754@@ -101,7 +101,7 @@
755 .addClass('FAILED');
756 dsd_details.setup_packages_diff_states(
757 placeholder.one('.diff-extra-container'), dsd_uri);
758- var func_req = undefined;
759+ var func_req;
760 var lp_prot = Y.lp.client.Launchpad.prototype;
761 lp_prot.named_post = function(url, func, config) {
762 func_req = func;
763@@ -128,7 +128,7 @@
764 .addClass('FAILED');
765 dsd_details.setup_packages_diff_states(
766 placeholder.one('.diff-extra-container'), dsd_uri);
767- var func_req = undefined;
768+ var func_req;
769 var lp_prot = Y.lp.client.Launchpad.prototype;
770 lp_prot.named_post = function(url, func, config) {
771 func_req = func;
772@@ -178,9 +178,7 @@
773
774 // Lock, stock, and two smoking barrels.
775 var handle_complete = function(data) {
776- status_node = Y.Node.create(
777- '<p id="complete">Test status: complete</p>');
778- Y.one('body').appendChild(status_node);
779+ window.status = '::::' + JSON.stringify(data);
780 };
781 Y.Test.Runner.on('complete', handle_complete);
782 Y.Test.Runner.add(suite);
783
784=== modified file 'lib/lp/registry/javascript/tests/test_milestone_table.js'
785--- lib/lp/registry/javascript/tests/test_milestone_table.js 2011-03-21 15:49:21 +0000
786+++ lib/lp/registry/javascript/tests/test_milestone_table.js 2011-06-14 16:45:56 +0000
787@@ -247,9 +247,7 @@
788
789 // Lock, stock, and two smoking barrels.
790 var handle_complete = function(data) {
791- status_node = Y.Node.create(
792- '<p id="complete">Test status: complete</p>');
793- Y.one('body').appendChild(status_node);
794+ window.status = '::::' + JSON.stringify(data);
795 };
796 Y.Test.Runner.on('complete', handle_complete);
797 Y.Test.Runner.add(suite);
798
799=== modified file 'lib/lp/registry/javascript/tests/test_structural_subscription.html'
800--- lib/lp/registry/javascript/tests/test_structural_subscription.html 2011-04-29 20:59:39 +0000
801+++ lib/lp/registry/javascript/tests/test_structural_subscription.html 2011-06-14 16:45:56 +0000
802@@ -10,6 +10,7 @@
803 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
804 <link rel="stylesheet"
805 href="../../../../canonical/launchpad/icing/lazr/build/testing/assets/testlogger.css"/>
806+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
807
808 <!-- Dependency -->
809 <script type="text/javascript"
810
811=== modified file 'lib/lp/registry/javascript/tests/test_structural_subscription.js'
812--- lib/lp/registry/javascript/tests/test_structural_subscription.js 2011-06-03 10:38:25 +0000
813+++ lib/lp/registry/javascript/tests/test_structural_subscription.js 2011-06-14 16:45:56 +0000
814@@ -438,9 +438,9 @@
815 module._show_add_overlay(this.configuration);
816 overlay = Y.one('#accordion-overlay');
817 // This is the title we would expect if there were no shortening.
818- var full_title = Y.one(content_box_id).one('h2').get('text');
819+ var header = Y.one(content_box_id).one('h2').get('text');
820 // The actual title is a prefix of the unabridged title.
821- var header = (
822+ var full_title = (
823 'Add a mail subscription for ' + this.project_title);
824 Assert.areEqual(0, full_title.search(header));
825 }
826@@ -1848,9 +1848,7 @@
827
828 // Lock, stock, and two smoking barrels.
829 var handle_complete = function(data) {
830- var status_node = Y.Node.create(
831- '<p id="complete">Test status: complete</p>');
832- Y.one('body').appendChild(status_node);
833+ window.status = '::::' + JSON.stringify(data);
834 };
835 Y.Test.Runner.on('complete', handle_complete);
836 Y.Test.Runner.add(suite);
837
838=== modified file 'lib/lp/registry/javascript/tests/timeline-iframe.html'
839--- lib/lp/registry/javascript/tests/timeline-iframe.html 2010-11-04 20:05:41 +0000
840+++ lib/lp/registry/javascript/tests/timeline-iframe.html 2011-06-14 16:45:56 +0000
841@@ -8,38 +8,13 @@
842 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssreset/reset.css"/>
843 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssfonts/fonts.css"/>
844 <link rel="stylesheet" href="../../../../canonical/launchpad/icing/yui/cssbase/base.css"/>
845+ <link rel="stylesheet" href="../../../../canonical/launchpad/javascript/test.css" />
846
847 <!-- The module under test -->
848 <script type="text/javascript" src="../timeline.js"></script>
849
850 <!-- The test suite -->
851 <script type="text/javascript" src="timeline.js"></script>
852- <style>
853- /* Taken and customized from testlogger.css */
854- #log .yui-console-content { width:44em }
855- #log .yui-console .yui-console-bd { height:100%}
856- #log .yui-console .yui-console-controls { display:none; }
857- #log .yui-console .yui-console-hd { display:none; }
858- #log .yui-console .yui-console-ft { position:absolute;top:0em; }
859-
860- #log .yui-console-entry-src { display:none; }
861-
862- #log .yui-console-entry-pass .yui-console-entry-cat {
863- background-color: green;
864- font-weight: bold;
865- color: white;
866- }
867- #log .yui-console-entry-fail .yui-console-entry-cat {
868- background-color: red;
869- font-weight: bold;
870- color: white;
871- }
872- #log .yui-console-entry-ignore .yui-console-entry-cat {
873- background-color: #666;
874- font-weight: bold;
875- color: white;
876- }
877- </style>
878 </head>
879 <body class="yui3-skin-sam">
880 <div id="timeline_example">
881
882=== modified file 'lib/lp/registry/javascript/tests/timeline.js'
883--- lib/lp/registry/javascript/tests/timeline.js 2011-02-03 21:14:05 +0000
884+++ lib/lp/registry/javascript/tests/timeline.js 2011-06-14 16:45:56 +0000
885@@ -146,72 +146,74 @@
886 }
887 }));
888
889-suite.add(new Y.Test.Case({
890-
891- name: 'resizing-config',
892-
893- setUp: function() {
894- this.timeline_graph = new Y.lp.registry.timeline.TimelineGraph(
895- RESIZING_CONFIG);
896- this.timeline_graph.render();
897- this.content_box = this.timeline_graph.get('contentBox');
898- },
899-
900- tearDown: function() {
901- var bounding_box = this.timeline_graph.get('boundingBox');
902- bounding_box.get('parentNode').removeChild(bounding_box);
903- this.timeline_graph.destroy();
904- },
905-
906- test_milestone_label_second_line: function() {
907- var label = this.content_box.one('div#ski');
908- var second_line = label.one('div');
909- Assert.areEqual(
910- '2200-05-26',
911- second_line.get('innerHTML'),
912- "Unexpected milestone date.");
913- },
914-
915- test_resize_frame: function() {
916- var frame = parent.document.getElementById(
917- this.timeline_graph.resize_frame);
918-
919- Assert.isNotNull(
920- frame,
921- 'This test must be run in an iframe with id=' +
922- this.timeline_graph.resize_frame + '.');
923-
924- var canvas = this.content_box.one('canvas');
925- var first_canvas_height = canvas.get('offsetHeight');
926- Assert.areEqual(1, this.timeline_graph.graph_scale);
927- Assert.areEqual(
928- canvas.get('offsetHeight'), frame.height,
929- '(1st) The frame was not resized to match the canvas.');
930-
931- simulate(
932- this.timeline_graph, '.yui3-timelinegraph-zoom-in', 'click');
933-
934- // The canvas is recreated in order to
935- // resize correctly in all browsers.
936- canvas = this.content_box.one('canvas');
937- Assert.areEqual(1.1, this.timeline_graph.graph_scale);
938- Assert.areEqual(
939- canvas.get('offsetHeight'), frame.height,
940- '(2nd) The frame was not resized to match the canvas.');
941- Assert.isTrue(
942- canvas.get('offsetHeight') > first_canvas_height,
943- 'The canvas did not get scaled.');
944-
945- simulate(
946- this.timeline_graph, '.yui3-timelinegraph-zoom-out', 'click');
947-
948- canvas = this.content_box.one('canvas');
949- Assert.areEqual(1, this.timeline_graph.graph_scale);
950- Assert.areEqual(
951- canvas.get('offsetHeight'), frame.height,
952- '(3rd) The frame was not resized to match the canvas.');
953- }
954-}));
955+// XXX sinzui 2011-06-07 bug=794597: This test requires a running server
956+// to pass the browser's js frame access rules.
957+//suite.add(new Y.Test.Case({
958+
959+// name: 'resizing-config',
960+
961+// setUp: function() {
962+// this.timeline_graph = new Y.lp.registry.timeline.TimelineGraph(
963+// RESIZING_CONFIG);
964+// this.timeline_graph.render();
965+// this.content_box = this.timeline_graph.get('contentBox');
966+// },
967+
968+// tearDown: function() {
969+// var bounding_box = this.timeline_graph.get('boundingBox');
970+// bounding_box.get('parentNode').removeChild(bounding_box);
971+// this.timeline_graph.destroy();
972+// },
973+
974+// test_milestone_label_second_line: function() {
975+// var label = this.content_box.one('div#ski');
976+// var second_line = label.one('div');
977+// Assert.areEqual(
978+// '2200-05-26',
979+// second_line.get('innerHTML'),
980+// "Unexpected milestone date.");
981+// },
982+
983+// test_resize_frame: function() {
984+// var frame = parent.document.getElementById(
985+// this.timeline_graph.resize_frame);
986+
987+// Assert.isNotNull(
988+// frame,
989+// 'This test must be run in an iframe with id=' +
990+// this.timeline_graph.resize_frame + '.');
991+
992+// var canvas = this.content_box.one('canvas');
993+// var first_canvas_height = canvas.get('offsetHeight');
994+// Assert.areEqual(1, this.timeline_graph.graph_scale);
995+// Assert.areEqual(
996+// canvas.get('offsetHeight'), frame.height,
997+// '(1st) The frame was not resized to match the canvas.');
998+
999+// simulate(
1000+// this.timeline_graph, '.yui3-timelinegraph-zoom-in', 'click');
1001+
1002+// // The canvas is recreated in order to
1003+// // resize correctly in all browsers.
1004+// canvas = this.content_box.one('canvas');
1005+// Assert.areEqual(1.1, this.timeline_graph.graph_scale);
1006+// Assert.areEqual(
1007+// canvas.get('offsetHeight'), frame.height,
1008+// '(2nd) The frame was not resized to match the canvas.');
1009+// Assert.isTrue(
1010+// canvas.get('offsetHeight') > first_canvas_height,
1011+// 'The canvas did not get scaled.');
1012+
1013+// simulate(
1014+// this.timeline_graph, '.yui3-timelinegraph-zoom-out', 'click');
1015+
1016+// canvas = this.content_box.one('canvas');
1017+// Assert.areEqual(1, this.timeline_graph.graph_scale);
1018+// Assert.areEqual(
1019+// canvas.get('offsetHeight'), frame.height,
1020+// '(3rd) The frame was not resized to match the canvas.');
1021+// }
1022+//}));
1023
1024 suite.add(new Y.Test.Case({
1025
1026@@ -265,14 +267,7 @@
1027
1028 Y.Test.Runner.add(suite);
1029 var handle_complete = function(data) {
1030- var parent_log = Y.Node.create(
1031- '<div id="log" style="display: none">' +
1032- Y.one('#log').get('innerHTML') + '</div>');
1033- var parent_body = Y.one(parent.document).get('body');
1034- parent_body.appendChild(parent_log);
1035- var status_node = Y.Node.create(
1036- '<p id="complete">Test status: complete</p>');
1037- parent_body.appendChild(status_node);
1038+ window.status = '::::' + JSON.stringify(data);
1039 };
1040 Y.Test.Runner.on('complete', handle_complete);
1041
1042
1043=== renamed file 'lib/lp/registry/windmill/tests/test_yuitests.py' => 'lib/lp/registry/tests/test_yuitests.py'
1044--- lib/lp/registry/windmill/tests/test_yuitests.py 2011-04-14 21:58:31 +0000
1045+++ lib/lp/registry/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
1046@@ -6,7 +6,7 @@
1047 __metaclass__ = type
1048 __all__ = []
1049
1050-from lp.registry.windmill.testing import RegistryYUITestLayer
1051+from canonical.testing.layers import YUITestLayer
1052 from lp.testing import (
1053 build_yui_unittest_suite,
1054 YUIUnitTestCase,
1055@@ -15,7 +15,7 @@
1056
1057 class RegistryYUIUnitTestCase(YUIUnitTestCase):
1058
1059- layer = RegistryYUITestLayer
1060+ layer = YUITestLayer
1061 suite_name = 'RegistryYUIUnitTests'
1062
1063
1064
1065=== modified file 'lib/lp/registry/windmill/testing.py'
1066--- lib/lp/registry/windmill/testing.py 2011-04-14 21:58:31 +0000
1067+++ lib/lp/registry/windmill/testing.py 2011-06-14 16:45:56 +0000
1068@@ -6,14 +6,10 @@
1069 __metaclass__ = type
1070 __all__ = [
1071 'RegistryWindmillLayer',
1072- 'RegistryYUITestLayer',
1073 ]
1074
1075
1076-from canonical.testing.layers import (
1077- BaseWindmillLayer,
1078- BaseYUITestLayer,
1079- )
1080+from canonical.testing.layers import BaseWindmillLayer
1081
1082
1083 class RegistryWindmillLayer(BaseWindmillLayer):
1084@@ -23,12 +19,3 @@
1085 def setUp(cls):
1086 cls.base_url = cls.appserver_root_url()
1087 super(RegistryWindmillLayer, cls).setUp()
1088-
1089-
1090-class RegistryYUITestLayer(BaseYUITestLayer):
1091- """Layer for Code YUI tests."""
1092-
1093- @classmethod
1094- def setUp(cls):
1095- cls.base_url = cls.appserver_root_url()
1096- super(RegistryYUITestLayer, cls).setUp()
1097
1098=== modified file 'lib/lp/soyuz/javascript/tests/archivesubscribers_index.js'
1099--- lib/lp/soyuz/javascript/tests/archivesubscribers_index.js 2011-02-03 21:14:05 +0000
1100+++ lib/lp/soyuz/javascript/tests/archivesubscribers_index.js 2011-06-14 16:45:56 +0000
1101@@ -135,9 +135,7 @@
1102 }));
1103
1104 Y.Test.Runner.on('complete', function(data) {
1105- status_node = Y.Node.create(
1106- '<p id="complete">Test status: complete</p>');
1107- Y.one('body').appendChild(status_node);
1108+ window.status = '::::' + JSON.stringify(data);
1109 });
1110 Y.Test.Runner.add(suite);
1111
1112
1113=== modified file 'lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js'
1114--- lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js 2011-02-03 21:14:05 +0000
1115+++ lib/lp/soyuz/javascript/tests/lp_dynamic_dom_updater.js 2011-06-14 16:45:56 +0000
1116@@ -271,9 +271,7 @@
1117 }));
1118
1119 Y.Test.Runner.on('complete', function(data) {
1120- status_node = Y.Node.create(
1121- '<p id="complete">Test status: complete</p>');
1122- Y.one('body').appendChild(status_node);
1123+ window.status = '::::' + JSON.stringify(data);
1124 });
1125 Y.Test.Runner.add(suite);
1126
1127
1128=== renamed file 'lib/lp/soyuz/windmill/tests/test_yuitests.py' => 'lib/lp/soyuz/tests/test_yuitests.py'
1129--- lib/lp/soyuz/windmill/tests/test_yuitests.py 2011-04-14 21:58:31 +0000
1130+++ lib/lp/soyuz/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
1131@@ -6,7 +6,7 @@
1132 __metaclass__ = type
1133 __all__ = []
1134
1135-from lp.soyuz.windmill.testing import SoyuzYUITestLayer
1136+from canonical.testing.layers import YUITestLayer
1137 from lp.testing import (
1138 build_yui_unittest_suite,
1139 YUIUnitTestCase,
1140@@ -15,7 +15,7 @@
1141
1142 class SoyuzYUIUnitTestCase(YUIUnitTestCase):
1143
1144- layer = SoyuzYUITestLayer
1145+ layer = YUITestLayer
1146 suite_name = 'SoyuzYUIUnitTests'
1147
1148
1149
1150=== modified file 'lib/lp/soyuz/windmill/testing.py'
1151--- lib/lp/soyuz/windmill/testing.py 2011-04-14 21:58:31 +0000
1152+++ lib/lp/soyuz/windmill/testing.py 2011-06-14 16:45:56 +0000
1153@@ -6,14 +6,10 @@
1154 __metaclass__ = type
1155 __all__ = [
1156 'SoyuzWindmillLayer',
1157- 'SoyuzYUITestLayer',
1158 ]
1159
1160
1161-from canonical.testing.layers import (
1162- BaseWindmillLayer,
1163- BaseYUITestLayer,
1164- )
1165+from canonical.testing.layers import BaseWindmillLayer
1166
1167
1168 class SoyuzWindmillLayer(BaseWindmillLayer):
1169@@ -23,12 +19,3 @@
1170 def setUp(cls):
1171 cls.base_url = cls.appserver_root_url()
1172 super(SoyuzWindmillLayer, cls).setUp()
1173-
1174-
1175-class SoyuzYUITestLayer(BaseYUITestLayer):
1176- """Layer for Code YUI tests."""
1177-
1178- @classmethod
1179- def setUp(cls):
1180- cls.base_url = cls.appserver_root_url()
1181- super(SoyuzYUITestLayer, cls).setUp()
1182
1183=== modified file 'lib/lp/testing/__init__.py'
1184--- lib/lp/testing/__init__.py 2011-06-08 13:34:15 +0000
1185+++ lib/lp/testing/__init__.py 2011-06-14 16:45:56 +0000
1186@@ -74,6 +74,15 @@
1187 import time
1188 import unittest
1189
1190+import simplejson
1191+
1192+try:
1193+ import html5browser
1194+ # Hush lint.
1195+ html5browser
1196+except ImportError:
1197+ html5browser = None
1198+
1199 from bzrlib import trace
1200 from bzrlib.bzrdir import (
1201 BzrDir,
1202@@ -908,10 +917,14 @@
1203 "([#!$%&()+,./:;?@~|^{}\\[\\]`*\\\'\\\"])", r"\\\\\1", expression)
1204
1205
1206-class YUIUnitTestCase(WindmillTestCase):
1207+class YUIUnitTestCase(TestCase):
1208
1209 layer = None
1210 suite_name = ''
1211+ js_timeout = 30000
1212+
1213+ TIMEOUT = object()
1214+ MISSING_REPORT = object()
1215
1216 _yui_results = None
1217
1218@@ -932,34 +945,33 @@
1219
1220 def setUp(self):
1221 super(YUIUnitTestCase, self).setUp()
1222- #This goes here to prevent circular import issues
1223- from canonical.testing.layers import BaseLayer
1224- _view_name = u'%s/+yui-unittest/' % BaseLayer.appserver_root_url()
1225- yui_runner_url = _view_name + self.test_path
1226-
1227- client = self.client
1228- client.open(url=yui_runner_url)
1229- client.waits.forPageLoad(timeout=constants.PAGE_LOAD)
1230- # This is very fragile for some reason, so we need a long delay here.
1231- client.waits.forElement(id='complete', timeout=constants.PAGE_LOAD)
1232- response = client.commands.getPageText()
1233+ client = html5browser.Browser()
1234+ html_uri = 'file://%s' % os.path.join(
1235+ config.root, 'lib', self.test_path)
1236+ page = client.load_page(html_uri, timeout=self.js_timeout)
1237+ if page.return_code == page.CODE_FAIL:
1238+ self._yui_results = self.TIMEOUT
1239+ return
1240+ # Data['type'] is complete (an event).
1241+ # Data['results'] is a dict (type=report)
1242+ # with 1 or more dicts (type=testcase)
1243+ # with 1 for more dicts (type=test).
1244+ report = simplejson.loads(page.content)
1245+ if report.get('type', None) != 'complete':
1246+ # Did not get a report back.
1247+ self._yui_results = self.MISSING_REPORT
1248+ return
1249 self._yui_results = {}
1250- # Maybe testing.pages should move to lp to avoid circular imports.
1251- from canonical.launchpad.testing.pages import find_tags_by_class
1252- entries = find_tags_by_class(
1253- response['result'], 'yui3-console-entry-TestRunner')
1254- for entry in entries:
1255- category = entry.find(
1256- attrs={'class': 'yui3-console-entry-cat'})
1257- if category is None:
1258- continue
1259- result = category.string
1260- if result not in ('pass', 'fail'):
1261- continue
1262- message = entry.pre.string
1263- test_name, ignore = message.split(':', 1)
1264- self._yui_results[test_name] = dict(
1265- result=result, message=message)
1266+ for key, value in report['results'].items():
1267+ if isinstance(value, dict) and value['type'] == 'testcase':
1268+ testcase_name = key
1269+ test_case = value
1270+ for key, value in test_case.items():
1271+ if isinstance(value, dict) and value['type'] == 'test':
1272+ test_name = '%s.%s' % (testcase_name, key)
1273+ test = value
1274+ self._yui_results[test_name] = dict(
1275+ result=test['result'], message=test['message'])
1276
1277 def checkResults(self):
1278 """Check the results.
1279@@ -967,13 +979,20 @@
1280 The tests are run during `setUp()`, but failures need to be reported
1281 from here.
1282 """
1283- if self._yui_results is None or len(self._yui_results) == 0:
1284- self.fail("Test harness or js failed.")
1285+ if self._yui_results == self.TIMEOUT:
1286+ self.fail("js timed out.")
1287+ elif self._yui_results == self.MISSING_REPORT:
1288+ self.fail("The data returned by js is not a test report.")
1289+ elif self._yui_results is None or len(self._yui_results) == 0:
1290+ self.fail("Test harness or js report format changed.")
1291+ failures = []
1292 for test_name in self._yui_results:
1293 result = self._yui_results[test_name]
1294- self.assertTrue('pass' == result['result'],
1295+ if result['result'] != 'pass':
1296+ failures.append(
1297 'Failure in %s.%s: %s' % (
1298- self.test_path, test_name, result['message']))
1299+ self.test_path, test_name, result['message']))
1300+ self.assertEqual([], failures, '\n'.join(failures))
1301
1302
1303 def build_yui_unittest_suite(app_testing_path, yui_test_class):
1304
1305=== modified file 'lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js'
1306--- lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js 2011-06-05 00:59:15 +0000
1307+++ lib/lp/translations/javascript/tests/test_sourcepackage_sharing_details.js 2011-06-14 16:45:56 +0000
1308@@ -139,10 +139,16 @@
1309 cache = test_ns.convert_cache(lp_client, cache);
1310 var import_overlay = {
1311 loadFormContentAndRender: function() {},
1312- render: function() {}
1313+ render: function() {},
1314+ get: function(ignore) {
1315+ return Y.Node.create(
1316+ '<p><a href="http://fake">fake</a></p>');
1317+ }
1318 };
1319+ unlink_overlay = import_overlay;
1320 usage_overlay = import_overlay;
1321- ctrl.configure(cache, {}, import_overlay, usage_overlay);
1322+ ctrl.configure(
1323+ cache, {}, unlink_overlay, import_overlay, usage_overlay);
1324 var tsconfig = ctrl.get('tsconfig');
1325 Y.Assert.areEqual(
1326 tsconfig.get('product_series').get('text'), 'title1');
1327@@ -230,20 +236,20 @@
1328 var incomplete = Y.one('#branch-incomplete');
1329 var link = Y.one('#branch-complete a');
1330 Y.Assert.areEqual('', link.get('text'));
1331- Y.Assert.areNotEqual('http:///', link.get('href'));
1332+ Y.Assert.areNotEqual('lp:///', link.get('href'));
1333 Y.Assert.isFalse(complete.hasClass('unseen'));
1334 Y.Assert.isFalse(incomplete.hasClass('unseen'));
1335 var ctrl = new TranslationSharingController();
1336 ctrl.update();
1337 Y.Assert.isTrue(complete.hasClass('unseen'));
1338 Y.Assert.isFalse(incomplete.hasClass('unseen'));
1339- ctrl.get('tsconfig').get('branch').set_link('a', 'http:///');
1340+ ctrl.get('tsconfig').get('branch').set_link('a', 'lp:///');
1341 ctrl.update();
1342 Y.Assert.isFalse(complete.hasClass('unseen'));
1343 Y.Assert.isTrue(incomplete.hasClass('unseen'));
1344 link = Y.one('#branch-complete a');
1345 Y.Assert.areEqual('a', link.get('text'));
1346- Y.Assert.areEqual('http:///', link.get('href'));
1347+ Y.Assert.areEqual('lp:///', link.get('href'));
1348 },
1349 test_update_all: function() {
1350 var ctrl = new TranslationSharingController();
1351@@ -339,9 +345,7 @@
1352
1353 // Lock, stock, and two smoking barrels.
1354 var handle_complete = function(data) {
1355- status_node = Y.Node.create(
1356- '<p id="complete">Test status: complete</p>');
1357- Y.one('body').appendChild(status_node);
1358+ window.status = '::::' + JSON.stringify(data);
1359 };
1360 Y.Test.Runner.on('complete', handle_complete);
1361 Y.Test.Runner.add(suite);
1362
1363=== renamed file 'lib/lp/translations/windmill/tests/test_yuitests.py' => 'lib/lp/translations/tests/test_yuitests.py'
1364--- lib/lp/translations/windmill/tests/test_yuitests.py 2011-06-06 17:43:55 +0000
1365+++ lib/lp/translations/tests/test_yuitests.py 2011-06-14 16:45:56 +0000
1366@@ -6,7 +6,7 @@
1367 __metaclass__ = type
1368 __all__ = []
1369
1370-from lp.translations.windmill.testing import TranslationsYUITestLayer
1371+from canonical.testing.layers import YUITestLayer
1372 from lp.testing import (
1373 build_yui_unittest_suite,
1374 YUIUnitTestCase,
1375@@ -15,7 +15,7 @@
1376
1377 class TranslationsYUIUnitTestCase(YUIUnitTestCase):
1378
1379- layer = TranslationsYUITestLayer
1380+ layer = YUITestLayer
1381 suite_name = 'TranslationsYUIUnitTests'
1382
1383
1384
1385=== modified file 'lib/lp/translations/windmill/testing.py'
1386--- lib/lp/translations/windmill/testing.py 2011-06-06 17:43:55 +0000
1387+++ lib/lp/translations/windmill/testing.py 2011-06-14 16:45:56 +0000
1388@@ -6,14 +6,10 @@
1389 __metaclass__ = type
1390 __all__ = [
1391 'TranslationsWindmillLayer',
1392- 'TranslationsYUITestLayer',
1393 ]
1394
1395
1396-from canonical.testing.layers import (
1397- BaseWindmillLayer,
1398- BaseYUITestLayer,
1399- )
1400+from canonical.testing.layers import BaseWindmillLayer
1401
1402
1403 class TranslationsWindmillLayer(BaseWindmillLayer):
1404@@ -24,12 +20,3 @@
1405 cls.facet = 'translations'
1406 cls.base_url = cls.appserver_root_url(cls.facet)
1407 super(TranslationsWindmillLayer, cls).setUp()
1408-
1409-
1410-class TranslationsYUITestLayer(BaseYUITestLayer):
1411- """Layer for Code YUI tests."""
1412-
1413- @classmethod
1414- def setUp(cls):
1415- cls.base_url = cls.appserver_root_url()
1416- super(TranslationsYUITestLayer, cls).setUp()