Merge lp:~rharding/launchpad/yuixhr_combo into lp:launchpad

Proposed by Richard Harding on 2012-03-23
Status: Merged
Approved by: Richard Harding on 2012-03-23
Approved revision: no longer in the source branch.
Merged at revision: 15004
Proposed branch: lp:~rharding/launchpad/yuixhr_combo
Merge into: lp:launchpad
Diff against target: 286 lines (+135/-69)
5 files modified
lib/lp/registry/javascript/tests/test_milestone_creation.js (+1/-4)
lib/lp/testing/tests/test_standard_yuixhr_test_template.js (+1/-5)
lib/lp/testing/tests/test_yuixhr_fixture.js (+1/-4)
lib/lp/testing/tests/test_yuixhr_fixture_facet.js (+1/-4)
lib/lp/testing/yuixhr.py (+131/-52)
To merge this branch: bzr merge lp:~rharding/launchpad/yuixhr_combo
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code 2012-03-23 Approve on 2012-03-23
Review via email: mp+99023@code.launchpad.net

Commit Message

Update YUI XHR tests to be able to folllow the combo loader feature flag and run tests both with and without going through the combo loader JS.

Description of the Change

= Summary =
The YUI XHR tests are the last that need to be updated for the upcoming combo loader era. They run their own web app instance and need to check the feature flag settings and vary the YUI config just as the base-layout-macros code does.

== Proposed Fix ==
Add checks for the feature flag, swap out the YUI config based on that, and allow this app to serve out the JS and CSS files needed from the combo loader build directory. It serves them one at a time though since it cannot access a running combo loader server during tests.

== Implementation Details ==
Added a new render path COMBOFILE and updated the html rendering. Tests then needed to be updated to use the standard LPJS and not setup their own loader rules.

== Tests ==
lib/lp/registry/javascript/tests/test_milestone_creation.js
lib/lp/testing/tests/test_yuixhr_fixture.js
lib/lp/testing/tests/test_yuixhr_fixture.js
lib/lp/testing/tests/test_yuixhr_fixture_facet.js

== Demo and Q/A ==
The tests should all pass, you can also make run-testapp and set the combo loader feature flag and run the tests manually to see them pass with the different loading enabled.

To post a comment you must log in.
Brad Crittenden (bac) wrote :

This looks great Rick and I find it to be much cleaner. Thanks!

<nit>At 208 (and perhaps elsewhere) would you follow PEP-8 wrt comments being properly capitalized and punctuated?</nit>

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/javascript/tests/test_milestone_creation.js'
2--- lib/lp/registry/javascript/tests/test_milestone_creation.js 2012-03-19 17:52:42 +0000
3+++ lib/lp/registry/javascript/tests/test_milestone_creation.js 2012-03-23 18:10:27 +0000
4@@ -1,7 +1,4 @@
5-YUI({
6- base: '/+icing/yui/',
7- filter: 'raw', combine: false, fetchCSS: false
8-}).use('test',
9+LPJS.use('test',
10 'lp.client',
11 'lp.testing.serverfixture',
12 'lp.registry.milestonetable',
13
14=== modified file 'lib/lp/testing/tests/test_standard_yuixhr_test_template.js'
15--- lib/lp/testing/tests/test_standard_yuixhr_test_template.js 2011-10-14 13:34:25 +0000
16+++ lib/lp/testing/tests/test_standard_yuixhr_test_template.js 2012-03-23 18:10:27 +0000
17@@ -1,8 +1,4 @@
18-YUI({
19- base: '/+icing/yui/',
20- filter: 'raw', combine: false, fetchCSS: false
21-// TODO: Add other modules you want to test into the "use" list.
22-}).use('test', 'lp.testing.serverfixture',
23+LPJS.use('test', 'lp.testing.serverfixture',
24 function(Y) {
25
26 // This is one-half of an example yuixhr test. The other half of a
27
28=== modified file 'lib/lp/testing/tests/test_yuixhr_fixture.js'
29--- lib/lp/testing/tests/test_yuixhr_fixture.js 2012-03-07 07:14:48 +0000
30+++ lib/lp/testing/tests/test_yuixhr_fixture.js 2012-03-23 18:10:27 +0000
31@@ -1,7 +1,4 @@
32-YUI({
33- base: '/+icing/yui/',
34- filter: 'raw', combine: false, fetchCSS: false
35-}).use('test', 'json', 'cookie', 'lp.testing.serverfixture',
36+LPJS.use('test', 'json', 'cookie', 'lp.testing.serverfixture',
37 function(Y) {
38
39 var suite = new Y.Test.Suite("lp.testing.yuixhr Tests");
40
41=== modified file 'lib/lp/testing/tests/test_yuixhr_fixture_facet.js'
42--- lib/lp/testing/tests/test_yuixhr_fixture_facet.js 2011-11-03 23:29:01 +0000
43+++ lib/lp/testing/tests/test_yuixhr_fixture_facet.js 2012-03-23 18:10:27 +0000
44@@ -1,7 +1,4 @@
45-YUI({
46- base: '/+icing/yui/',
47- filter: 'raw', combine: false, fetchCSS: false
48-}).use('test', 'lp.testing.serverfixture',
49+LPJS.use('test', 'lp.testing.serverfixture',
50 function(Y) {
51
52 var suite = new Y.Test.Suite("lp.testing.yuixhr facet Tests");
53
54=== modified file 'lib/lp/testing/yuixhr.py'
55--- lib/lp/testing/yuixhr.py 2012-03-21 01:06:04 +0000
56+++ lib/lp/testing/yuixhr.py 2012-03-23 18:10:27 +0000
57@@ -157,53 +157,101 @@
58 """Dynamically loads YUI test along their fixtures run over an app server.
59 """
60
61+ COMBOFILE = 'COMBOFILE'
62 JAVASCRIPT = 'JAVASCRIPT'
63 HTML = 'HTML'
64 SETUP = 'SETUP'
65 TEARDOWN = 'TEARDOWN'
66 INDEX = 'INDEX'
67
68+ yui_block_no_combo = dedent("""\
69+ <script type="text/javascript"
70+ src="/+icing/rev%(revno)s/build/launchpad.js"></script>
71+
72+ <script type="text/javascript">
73+ YUI.GlobalConfig = {
74+ fetchCSS: false,
75+ timeout: 50,
76+ ignore: [
77+ 'yui2-yahoo', 'yui2-event', 'yui2-dom',
78+ 'yui2-calendar','yui2-dom-event'
79+ ]
80+ }
81+ </script>
82+ """)
83+
84+ yui_block_combo = dedent("""\
85+ <script type="text/javascript"
86+ src="/+yuitest/build/js/yui/yui/yui-min.js"></script>
87+ <script type="text/javascript"
88+ src="/+yuitest/build/js/yui/loader/loader-min.js"></script>
89+ <script type="text/javascript"
90+ src="/+yuitest/build/js/lp/meta.js"></script>
91+ <script type="text/javascript">
92+ YUI.GlobalConfig = {
93+ combine: false,
94+ base: '/+yuitest/build/js/yui/',
95+ debug: true,
96+ fetchCSS: false,
97+ groups: {
98+ lp: {
99+ combine: false,
100+ base: '/+yuitest/build/js/lp/',
101+ root: 'lp/',
102+ debug: true,
103+ filter: 'raw',
104+ // comes from including lp/meta.js
105+ modules: LP_MODULES,
106+ fetchCSS: false
107+ },
108+ yui2: {
109+ combine: true,
110+ base: '/+yuitest/build/js/yui2/',
111+ fetchCSS: false,
112+ modules: {
113+ 'yui2-yahoo': {
114+ path: 'yahoo/yahoo.js'
115+ },
116+ 'yui2-event': {
117+ path: 'event/event.js'
118+ },
119+ 'yui2-dom': {
120+ path: 'dom/dom.js'
121+ },
122+ 'yui2-calendar': {
123+ path: 'calendar/calendar.js'
124+ },
125+ 'yui2-dom-event': {
126+ path: 'yahoo-dom-event/yahoo-dom-event.js'
127+ }
128+ }
129+ }
130+ }
131+ }
132+ </script>
133+ """)
134+
135 page_template = dedent("""\
136 <!DOCTYPE html>
137 <html>
138 <head>
139- <title>Test</title>
140- <script type="text/javascript"
141- src="/+icing/rev%(revno)s/build/launchpad.js"></script>
142- <script type="text/javascript">
143- YUI.GlobalConfig = {
144- fetchCSS: false,
145- timeout: 50,
146- ignore: [
147- 'yui2-yahoo', 'yui2-event', 'yui2-dom',
148- 'yui2-calendar','yui2-dom-event'
149- ]
150- }
151- </script>
152- <link rel="stylesheet"
153- href="/+icing/yui/assets/skins/sam/skin.css"/>
154- <link rel="stylesheet" href="/+icing/rev%(revno)s/combo.css"/>
155- <style>
156- /* Taken and customized from testlogger.css */
157- .yui-console-entry-src { display:none; }
158- .yui-console-entry.yui-console-entry-pass .yui-console-entry-cat {
159- background-color: green;
160- font-weight: bold;
161- color: white;
162- }
163- .yui-console-entry.yui-console-entry-fail .yui-console-entry-cat {
164- background-color: red;
165- font-weight: bold;
166- color: white;
167- }
168- .yui-console-entry.yui-console-entry-ignore .yui-console-entry-cat {
169- background-color: #666;
170- font-weight: bold;
171- color: white;
172- }
173- </style>
174- <script type="text/javascript" src="%(test_module)s"></script>
175- </head>
176+ <title>Test</title>
177+ %(javascript_block)s
178+ <script type="text/javascript">
179+ // we need this to create a single YUI instance all events and
180+ // code talks across. All instances of YUI().use should be
181+ // based off of LPJS instead.
182+ LPJS = new YUI();
183+ </script>
184+ <link rel="stylesheet"
185+ href="/+yuitest/build/js/yui/console/assets/console-core.css"/>
186+ <link rel="stylesheet"
187+ href="/+yuitest/build/js/yui/console/assets/skins/sam/console.css"/>
188+ <link rel="stylesheet"
189+ href="/+yuitest/build/js/yui/test/assets/skins/sam/test.css"/>
190+ <link rel="stylesheet" href="/+icing/rev%(revno)s/combo.css"/>
191+ <script type="text/javascript" src="%(test_module)s"></script>
192+ </head>
193 <body class="yui3-skin-sam">
194 <div id="log"></div>
195 <p>Want to re-run your test?</p>
196@@ -263,23 +311,29 @@
197 self.action = self.INDEX
198 return
199 path, ext = os.path.splitext(self.traversed_path)
200- full_path = os.path.join(config.root, 'lib', path)
201- if not os.path.exists(full_path + '.py'):
202- raise NotFound(self, full_path + '.py', self.request)
203- if not os.path.exists(full_path + '.js'):
204- raise NotFound(self, full_path + '.js', self.request)
205-
206- if ext == '.js':
207- self.action = self.JAVASCRIPT
208+ # We need to route requests with build/js in them to the combo loader
209+ # js files so we can load those to bootstap.
210+ if path.startswith('build/js'):
211+ self.action = self.COMBOFILE
212 else:
213- if self.request.method == 'GET':
214- self.action = self.HTML
215+ full_path = os.path.join(config.root, 'lib', path)
216+
217+ if not os.path.exists(full_path + '.py'):
218+ raise NotFound(self, full_path + '.py', self.request)
219+ if not os.path.exists(full_path + '.js'):
220+ raise NotFound(self, full_path + '.js', self.request)
221+
222+ if ext == '.js':
223+ self.action = self.JAVASCRIPT
224 else:
225- self.fixtures = self.request.form['fixtures'].split(',')
226- if self.request.form['action'] == 'setup':
227- self.action = self.SETUP
228+ if self.request.method == 'GET':
229+ self.action = self.HTML
230 else:
231- self.action = self.TEARDOWN
232+ self.fixtures = self.request.form['fixtures'].split(',')
233+ if self.request.form['action'] == 'setup':
234+ self.action = self.SETUP
235+ else:
236+ self.action = self.TEARDOWN
237
238 # The following two zope methods publishTraverse and browserDefault
239 # allow this view class to take control of traversal from this point
240@@ -351,6 +405,16 @@
241 'revno': revno,
242 'tests': '\n'.join(test_lines)}
243
244+ def renderCOMBOFILE(self):
245+ """We need to serve the combo files out of the build directory."""
246+ self.request.response.setHeader('Cache-Control', 'no-cache')
247+ if self.traversed_path.endswith('js'):
248+ self.request.response.setHeader('Content-Type', 'text/javascript')
249+ elif self.traversed_path.endswith('css'):
250+ self.request.response.setHeader('Content-Type', 'text/css')
251+ return open(
252+ os.path.join(config.root, self.traversed_path))
253+
254 def renderJAVASCRIPT(self):
255 self.request.response.setHeader('Content-Type', 'text/javascript')
256 self.request.response.setHeader('Cache-Control', 'no-cache')
257@@ -369,7 +433,8 @@
258 reload(module)
259 return self.page_template % dict(
260 test_module='/+yuitest/%s.js' % self.traversed_path,
261- revno=revno)
262+ revno=revno,
263+ javascript_block=self.renderYUI())
264
265 def renderSETUP(self):
266 data = {}
267@@ -415,6 +480,20 @@
268 result = CloseDbResult()
269 return result
270
271+ def renderYUI(self):
272+ """Render out which YUI block we need based on the combo loader
273+
274+ If the combo loader is enabled, we need that setup and config and not
275+ to load launchpad.js, else we need launchpad.js for things to run.
276+
277+ """
278+ if self.request.features.getFlag('js.combo_loader.enabled'):
279+ return self.yui_block_combo % dict(
280+ revno=revno,
281+ combo_url=self.combo_url)
282+ else:
283+ return self.yui_block_no_combo % dict(revno=revno)
284+
285 def render(self):
286 return getattr(self, 'render' + self.action)()
287