← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Richard Harding has proposed merging lp:~rharding/launchpad/yuixhr_combo into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rharding/launchpad/yuixhr_combo/+merge/99023

= 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.
-- 
https://code.launchpad.net/~rharding/launchpad/yuixhr_combo/+merge/99023
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rharding/launchpad/yuixhr_combo into lp:launchpad.
=== modified file 'lib/lp/registry/javascript/tests/test_milestone_creation.js'
--- lib/lp/registry/javascript/tests/test_milestone_creation.js	2012-03-19 17:52:42 +0000
+++ lib/lp/registry/javascript/tests/test_milestone_creation.js	2012-03-23 15:03:23 +0000
@@ -1,7 +1,4 @@
-YUI({
-    base: '/+icing/yui/',
-    filter: 'raw', combine: false, fetchCSS: false
-}).use('test',
+LPJS.use('test',
        'lp.client',
        'lp.testing.serverfixture',
        'lp.registry.milestonetable',

=== modified file 'lib/lp/testing/tests/test_standard_yuixhr_test_template.js'
--- lib/lp/testing/tests/test_standard_yuixhr_test_template.js	2011-10-14 13:34:25 +0000
+++ lib/lp/testing/tests/test_standard_yuixhr_test_template.js	2012-03-23 15:03:23 +0000
@@ -1,8 +1,4 @@
-YUI({
-    base: '/+icing/yui/',
-    filter: 'raw', combine: false, fetchCSS: false
-// TODO: Add other modules you want to test into the "use" list.
-}).use('test', 'lp.testing.serverfixture',
+LPJS.use('test', 'lp.testing.serverfixture',
        function(Y) {
 
 // This is one-half of an example yuixhr test.  The other half of a

=== modified file 'lib/lp/testing/tests/test_yuixhr_fixture.js'
--- lib/lp/testing/tests/test_yuixhr_fixture.js	2012-03-07 07:14:48 +0000
+++ lib/lp/testing/tests/test_yuixhr_fixture.js	2012-03-23 15:03:23 +0000
@@ -1,7 +1,4 @@
-YUI({
-    base: '/+icing/yui/',
-    filter: 'raw', combine: false, fetchCSS: false
-}).use('test', 'json', 'cookie', 'lp.testing.serverfixture',
+LPJS.use('test', 'json', 'cookie', 'lp.testing.serverfixture',
        function(Y) {
 
 var suite = new Y.Test.Suite("lp.testing.yuixhr Tests");

=== modified file 'lib/lp/testing/tests/test_yuixhr_fixture_facet.js'
--- lib/lp/testing/tests/test_yuixhr_fixture_facet.js	2011-11-03 23:29:01 +0000
+++ lib/lp/testing/tests/test_yuixhr_fixture_facet.js	2012-03-23 15:03:23 +0000
@@ -1,7 +1,4 @@
-YUI({
-  base: '/+icing/yui/',
-  filter: 'raw', combine: false, fetchCSS: false
-}).use('test', 'lp.testing.serverfixture',
+LPJS.use('test', 'lp.testing.serverfixture',
        function(Y) {
 
 var suite = new Y.Test.Suite("lp.testing.yuixhr facet Tests");

=== modified file 'lib/lp/testing/yuixhr.py'
--- lib/lp/testing/yuixhr.py	2012-03-21 01:06:04 +0000
+++ lib/lp/testing/yuixhr.py	2012-03-23 15:03:23 +0000
@@ -157,53 +157,101 @@
     """Dynamically loads YUI test along their fixtures run over an app server.
     """
 
+    COMBOFILE = 'COMBOFILE'
     JAVASCRIPT = 'JAVASCRIPT'
     HTML = 'HTML'
     SETUP = 'SETUP'
     TEARDOWN = 'TEARDOWN'
     INDEX = 'INDEX'
 
+    yui_block_no_combo = dedent("""\
+        <script type="text/javascript"
+            src="/+icing/rev%(revno)s/build/launchpad.js"></script>
+
+        <script type="text/javascript">
+            YUI.GlobalConfig = {
+                fetchCSS: false,
+                timeout: 50,
+                ignore: [
+                    'yui2-yahoo', 'yui2-event', 'yui2-dom',
+                    'yui2-calendar','yui2-dom-event'
+                ]
+            }
+       </script>
+    """)
+
+    yui_block_combo = dedent("""\
+       <script type="text/javascript"
+           src="/+yuitest/build/js/yui/yui/yui-min.js"></script>
+       <script type="text/javascript"
+           src="/+yuitest/build/js/yui/loader/loader-min.js"></script>
+       <script type="text/javascript"
+           src="/+yuitest/build/js/lp/meta.js"></script>
+       <script type="text/javascript">
+            YUI.GlobalConfig = {
+                combine: false,
+                base: '/+yuitest/build/js/yui/',
+                debug: true,
+                fetchCSS: false,
+                groups: {
+                    lp: {
+                        combine: false,
+                        base: '/+yuitest/build/js/lp/',
+                        root: 'lp/',
+                        debug: true,
+                        filter: 'raw',
+                        // comes from including lp/meta.js
+                        modules: LP_MODULES,
+                        fetchCSS: false
+                    },
+                    yui2: {
+                        combine: true,
+                        base: '/+yuitest/build/js/yui2/',
+                        fetchCSS: false,
+                        modules: {
+                            'yui2-yahoo': {
+                                path: 'yahoo/yahoo.js'
+                            },
+                            'yui2-event': {
+                                path: 'event/event.js'
+                            },
+                            'yui2-dom': {
+                                path: 'dom/dom.js'
+                            },
+                            'yui2-calendar': {
+                                path: 'calendar/calendar.js'
+                            },
+                            'yui2-dom-event': {
+                                path: 'yahoo-dom-event/yahoo-dom-event.js'
+                            }
+                        }
+                    }
+                }
+            }
+        </script>
+    """)
+
     page_template = dedent("""\
         <!DOCTYPE html>
         <html>
           <head>
-          <title>Test</title>
-          <script type="text/javascript"
-            src="/+icing/rev%(revno)s/build/launchpad.js"></script>
-          <script type="text/javascript">
-              YUI.GlobalConfig = {
-                  fetchCSS: false,
-                  timeout: 50,
-                  ignore: [
-                      'yui2-yahoo', 'yui2-event', 'yui2-dom',
-                      'yui2-calendar','yui2-dom-event'
-                  ]
-              }
-          </script>
-          <link rel="stylesheet"
-            href="/+icing/yui/assets/skins/sam/skin.css"/>
-          <link rel="stylesheet" href="/+icing/rev%(revno)s/combo.css"/>
-          <style>
-          /* Taken and customized from testlogger.css */
-          .yui-console-entry-src { display:none; }
-          .yui-console-entry.yui-console-entry-pass .yui-console-entry-cat {
-            background-color: green;
-            font-weight: bold;
-            color: white;
-          }
-          .yui-console-entry.yui-console-entry-fail .yui-console-entry-cat {
-            background-color: red;
-            font-weight: bold;
-            color: white;
-          }
-          .yui-console-entry.yui-console-entry-ignore .yui-console-entry-cat {
-            background-color: #666;
-            font-weight: bold;
-            color: white;
-          }
-          </style>
-          <script type="text/javascript" src="%(test_module)s"></script>
-        </head>
+            <title>Test</title>
+            %(javascript_block)s
+            <script type="text/javascript">
+              // we need this to create a single YUI instance all events and
+              // code talks across. All instances of YUI().use should be
+              // based off of LPJS instead.
+              LPJS = new YUI();
+            </script>
+            <link rel="stylesheet"
+              href="/+yuitest/build/js/yui/console/assets/console-core.css"/>
+            <link rel="stylesheet"
+              href="/+yuitest/build/js/yui/console/assets/skins/sam/console.css"/>
+            <link rel="stylesheet"
+              href="/+yuitest/build/js/yui/test/assets/skins/sam/test.css"/>
+            <link rel="stylesheet" href="/+icing/rev%(revno)s/combo.css"/>
+            <script type="text/javascript" src="%(test_module)s"></script>
+          </head>
         <body class="yui3-skin-sam">
           <div id="log"></div>
           <p>Want to re-run your test?</p>
@@ -263,23 +311,29 @@
             self.action = self.INDEX
             return
         path, ext = os.path.splitext(self.traversed_path)
-        full_path = os.path.join(config.root, 'lib', path)
-        if not os.path.exists(full_path + '.py'):
-            raise NotFound(self, full_path + '.py', self.request)
-        if not os.path.exists(full_path + '.js'):
-            raise NotFound(self, full_path + '.js', self.request)
-
-        if ext == '.js':
-            self.action = self.JAVASCRIPT
+        # we need to route requests with build/js in them to the combo loader
+        # js files so we can load those to bootstap
+        if path.startswith('build/js'):
+            self.action = self.COMBOFILE
         else:
-            if self.request.method == 'GET':
-                self.action = self.HTML
+            full_path = os.path.join(config.root, 'lib', path)
+
+            if not os.path.exists(full_path + '.py'):
+                raise NotFound(self, full_path + '.py', self.request)
+            if not os.path.exists(full_path + '.js'):
+                raise NotFound(self, full_path + '.js', self.request)
+
+            if ext == '.js':
+                self.action = self.JAVASCRIPT
             else:
-                self.fixtures = self.request.form['fixtures'].split(',')
-                if self.request.form['action'] == 'setup':
-                    self.action = self.SETUP
+                if self.request.method == 'GET':
+                    self.action = self.HTML
                 else:
-                    self.action = self.TEARDOWN
+                    self.fixtures = self.request.form['fixtures'].split(',')
+                    if self.request.form['action'] == 'setup':
+                        self.action = self.SETUP
+                    else:
+                        self.action = self.TEARDOWN
 
     # The following two zope methods publishTraverse and browserDefault
     # allow this view class to take control of traversal from this point
@@ -351,6 +405,16 @@
             'revno': revno,
             'tests': '\n'.join(test_lines)}
 
+    def renderCOMBOFILE(self):
+        """We need to serve the combo files out of the build directory."""
+        self.request.response.setHeader('Cache-Control', 'no-cache')
+        if self.traversed_path.endswith('js'):
+            self.request.response.setHeader('Content-Type', 'text/javascript')
+        elif self.traversed_path.endswith('css'):
+            self.request.response.setHeader('Content-Type', 'text/css')
+        return open(
+            os.path.join(config.root, self.traversed_path))
+
     def renderJAVASCRIPT(self):
         self.request.response.setHeader('Content-Type', 'text/javascript')
         self.request.response.setHeader('Cache-Control', 'no-cache')
@@ -369,7 +433,8 @@
                 reload(module)
         return self.page_template % dict(
             test_module='/+yuitest/%s.js' % self.traversed_path,
-            revno=revno)
+            revno=revno,
+            javascript_block=self.renderYUI())
 
     def renderSETUP(self):
         data = {}
@@ -415,6 +480,20 @@
             result = CloseDbResult()
         return result
 
+    def renderYUI(self):
+        """Render out which YUI block we need based on the combo loader
+
+        If the combo loader is enabled, we need that setup and config and not
+        to load launchpad.js, else we need launchpad.js for things to run.
+
+        """
+        if self.request.features.getFlag('js.combo_loader.enabled'):
+            return self.yui_block_combo % dict(
+                revno=revno,
+                combo_url=self.combo_url)
+        else:
+            return self.yui_block_no_combo % dict(revno=revno)
+
     def render(self):
         return getattr(self, 'render' + self.action)()