← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/morphing-tests into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/morphing-tests into lp:maas.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/morphing-tests/+merge/106531

I decided to finish up Huw's branch (see https://code.launchpad.net/~huwshimi/maas/morphing-tests/+merge/102056).  Huw won't have time to finish it in the foreseeable future.  I've fixed the conflicts and implemented the changes I suggested on the MP (!).

= Pre-imp =

Talked very briefly about this with jtv.  Neither he nor me want to have a lingering branch like this so I decided to take the bull by the horns and finish it up.

= Notes =

I've refactored all of the "animation creating" methods into module level methods.  This way, they are completely self-contained and easy to test.
-- 
https://code.launchpad.net/~rvb/maas/morphing-tests/+merge/106531
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/morphing-tests into lp:maas.
=== modified file 'src/maasserver/static/js/morph.js'
--- src/maasserver/static/js/morph.js	2012-04-30 13:10:04 +0000
+++ src/maasserver/static/js/morph.js	2012-05-20 13:53:18 +0000
@@ -35,6 +35,89 @@
     }
 };
 
+/**
+ * Create the animation for morphing out the original content and
+ * morphin in the new content.
+ *
+ * @method _create_morph
+ */
+module._create_morph = function(srcNode, targetNode, publisher) {
+    var self = this;
+    var morph = module._create_morph_out(targetNode);
+    morph.on('end', function () {
+        var anim = module._create_morph_in(srcNode, targetNode);
+        anim.on('end', function () {
+            publisher.fire('morphed');
+        });
+        anim.run();
+    });
+    return morph;
+};
+
+/**
+ * Create the animation for morphing out the original content.
+ *
+ * @method _create_morph_out
+ */
+module._create_morph_out = function(targetNode) {
+    var morph_out = new Y.Anim({
+        node: targetNode,
+        to: {opacity: 0},
+        duration: 0.2,
+        easing: 'easeOut'
+    });
+    morph_out.on('end', function () {
+        targetNode.addClass('hidden');
+    });
+    return morph_out;
+};
+
+/**
+ * Create an animation for morphing in the new content.
+ *
+ * @method _create_morph_in
+ */
+module._create_morph_in = function(srcNode, targetNode) {
+    var self = this;
+    srcNode.setStyle('opacity', 0);
+    srcNode.removeClass('hidden');
+    var src_height = srcNode.getComputedStyle('height')
+        .replace('px', '');
+    var target_height = targetNode.getComputedStyle('height');
+    srcNode.setStyle('height', target_height);
+    var morph_in = new Y.Anim({
+        node: srcNode,
+        to: {opacity: 1},
+        duration: 1,
+        easing: 'easeIn'
+    });
+    // Resize the srcNode to its original size.
+    var resize_anim = module._create_resize(srcNode, src_height);
+    morph_in.on('start', function () {
+        resize_anim.run();
+    });
+    return morph_in;
+};
+
+/**
+ * Create an animation for resizing the given node.
+ *
+ * @method _create_resize
+ */
+module._create_resize = function(srcNode, height) {
+    var resize = new Y.Anim({
+        node: srcNode,
+        to: {height: height},
+        duration: 0.5,
+        easing: 'easeOut'
+        });
+    resize.on('end', function () {
+        srcNode.setStyle('height', 'auto');
+        resize.fire('resized');
+    });
+    return resize;
+};
+
 Y.extend(Morph, Y.Widget, {
     initializer: function(cfg) {
         if (Y.Lang.isValue(cfg.animate)) {
@@ -45,51 +128,28 @@
         }
     },
 
+    /**
+     * Animate between the original and new content.
+     *
+     * @method morph
+     * @param {Boolean} reverse: whether or not the widget should morph in the
+            new content or return to the original content.
+     */
     morph: function(reverse) {
+        if (!Y.Lang.isValue(reverse)) {
+            reverse = false;
+        }
         var srcNode = this.get(reverse ? 'targetNode' : 'srcNode');
         var targetNode = this.get(reverse ? 'srcNode' : 'targetNode');
         if (this._animate) {
-            var target_height = targetNode.getComputedStyle('height');
-            var fade_out = new Y.Anim({
-                node: targetNode,
-                to: {opacity: 0},
-                duration: 0.2,
-                easing: 'easeOut'
-                });
-            var self = this;
-            fade_out.on('end', function () {
-                targetNode.addClass('hidden');
-                srcNode.setStyle('opacity', 0);
-                srcNode.removeClass('hidden');
-                var src_height = srcNode.getComputedStyle('height')
-                    .replace('px', '');
-                srcNode.setStyle('height', target_height);
-                var fade_in = new Y.Anim({
-                    node: srcNode,
-                    to: {opacity: 1},
-                    duration: 1,
-                    easing: 'easeIn'
-                    });
-                var resize = new Y.Anim({
-                    node: srcNode,
-                    to: {height: src_height},
-                    duration: 0.5,
-                    easing: 'easeOut'
-                    });
-                resize.on('end', function () {
-                    srcNode.setStyle('height', 'auto');
-                    self.fire('morphed');
-                });
-                fade_in.run();
-                resize.run();
-            });
-            fade_out.run();
+            module._create_morph(srcNode, targetNode, this).run();
         }
         else {
             targetNode.addClass('hidden');
             srcNode.removeClass('hidden');
         }
     }
+
 });
 
 module.Morph = Morph;

=== modified file 'src/maasserver/static/js/tests/test_morph.html'
--- src/maasserver/static/js/tests/test_morph.html	2012-03-16 08:55:33 +0000
+++ src/maasserver/static/js/tests/test_morph.html	2012-05-20 13:53:18 +0000
@@ -14,12 +14,18 @@
     <script type="text/javascript" src="test_morph.js"></script>
   </head>
   <body>
-  <div id="panel-one">
-    Panel One
-  </div>
-  <div id="panel-two" class="hidden">
-    Panel Two
-  </div>
+  <script type="text/x-template" id="panel-one-template">
+    <div id="panel-one">
+      Panel One
+    </div>
+  </script>
+  <script type="text/x-template" id="panel-two-template">
+    <div id="panel-two" class="hidden">
+      Panel Two
+    </div>
+  </script>
+
+  <div id="placeholder"></div>
 
   <span id="suite">maas.morph.tests</span>
   </body>

=== modified file 'src/maasserver/static/js/tests/test_morph.js'
--- src/maasserver/static/js/tests/test_morph.js	2012-04-17 15:43:08 +0000
+++ src/maasserver/static/js/tests/test_morph.js	2012-05-20 13:53:18 +0000
@@ -10,52 +10,122 @@
 var module = Y.maas.morph;
 var suite = new Y.Test.Suite("maas.morph Tests");
 
+var panel_one = Y.one('#panel-one-template').getContent();
+var panel_two = Y.one('#panel-two-template').getContent();
+
 suite.add(new Y.maas.testing.TestCase({
     name: 'test-morphing',
 
-    testMorphing: function() {
+    setUp: function() {
+        Y.one('#placeholder').empty().append(
+            Y.Node.create(panel_one)).append(
+                Y.Node.create(panel_two));
+    },
+
+    get_morph: function(animate) {
         var cfg = {
             srcNode: '#panel-two',
-            targetNode: '#panel-one'
+            targetNode: '#panel-one',
+            animate: animate
         };
-        var morpher = new module.Morph(cfg);
-        Y.Assert.isFalse(
-            Y.one('#panel-one').hasClass('hidden'),
-            'The target panel should initially be visible');
-        Y.Assert.isTrue(
-            Y.one('#panel-two').hasClass('hidden'),
-            'The source panel should initially be hidden');
-        var morphed_fired = false;
-        morpher.on('morphed', function() {
-            morphed_fired = true;
+        return new module.Morph(cfg);
+    },
+
+    test_morphing_no_animation_sets_visibility_classes: function() {
+        var morpher = this.get_morph(false);
+        morpher.morph(false);
+
+        Y.Assert.isTrue(Y.one('#panel-one').hasClass('hidden'));
+        Y.Assert.isFalse(Y.one('#panel-two').hasClass('hidden'));
+    },
+
+    test_morphing_animation_sets_visibility_classes: function() {
+        Y.Assert.isFalse(Y.one('#panel-one').hasClass('hidden'));
+        Y.Assert.isTrue(Y.one('#panel-two').hasClass('hidden'));
+        var morpher = this.get_morph(true);
+        var self = this;
+        morpher.on('morphed', function () {
+            self.resume(function() {
+                Y.Assert.isTrue(Y.one('#panel-one').hasClass('hidden'));
+                Y.Assert.isFalse(Y.one('#panel-two').hasClass('hidden'));
+            });
         });
         morpher.morph();
-        this.wait(function() {
-            Y.Assert.isTrue(
-                Y.one(cfg.targetNode).hasClass('hidden'),
-                'The target panel should now be hidden');
-            Y.Assert.isFalse(
-                Y.one(cfg.srcNode).hasClass('hidden'),
-                'The source panel should now be visible');
-            Y.Assert.isTrue(
-                morphed_fired,
-                'The morphed event should have fired');
-            Y.Assert.areEqual(
-                'auto',
-                Y.one(cfg.srcNode).getStyle('height'),
-                'The morpher should set the height back to auto');
-            /* Fire this morph again, this time for the reverse. */
-            morpher.morph(true);
-            this.wait(function() {
-                Y.Assert.isFalse(
-                    Y.one(cfg.targetNode).hasClass('hidden'),
-                    'The target panel should now be visible again');
-                Y.Assert.isTrue(
-                    Y.one(cfg.srcNode).hasClass('hidden'),
-                    'The source panel should now be hidden again');
-            }, 2000);
-        }, 2000);
+        this.wait();
+    },
+
+    test__create_morph_out_anim_sets_opacity_and_adds_class: function() {
+        var targetNode = Y.one('#panel-one');
+        targetNode.setStyle('opacity', 0.5);
+        var morph = module._create_morph_out(targetNode);
+        var self = this;
+        morph.on('end', function () {
+            self.resume(function() {
+                var opacity = targetNode.getComputedStyle('opacity');
+                Y.Assert.areEqual(0, opacity);
+                Y.Assert.isTrue(targetNode.hasClass('hidden'));
+            });
+        });
+        morph.run();
+        this.wait();
+    },
+
+    test__create_morph_in_anim_sets_initial_opacity_and_class: function() {
+        var srcNode = Y.one('#panel-one');
+        srcNode.setStyle('opacity', 0.5);
+        var targetNode = Y.one('#panel-two');
+        var morph = module._create_morph_in(srcNode, targetNode);
+
+        Y.Assert.areEqual(0, srcNode.getComputedStyle('opacity'));
+        Y.Assert.isFalse(srcNode.hasClass('hidden'));
+    },
+
+    test__create_morph_in_anim_sets_opacity: function() {
+        var srcNode = Y.one('#panel-one');
+        srcNode.setStyle('opacity', 0.5);
+        var targetNode = Y.one('#panel-two');
+        var morph = module._create_morph_in(srcNode, targetNode);
+        var self = this;
+        morph.on('end', function () {
+            self.resume(function() {
+                Y.Assert.areEqual(1, srcNode.getComputedStyle('opacity'));
+            });
+        });
+        morph.run();
+        this.wait();
+    },
+
+    test__create_morph_anim_set_visibility_classes: function() {
+        var srcNode = Y.one('#panel-two');
+        var targetNode = Y.one('#panel-one');
+        var publisher = new Y.Base();
+        var morph = module._create_morph(srcNode, targetNode, publisher);
+        var self = this;
+        publisher.on('morphed', function () {
+            self.resume(function() {
+                Y.Assert.areEqual(1, srcNode.getComputedStyle('opacity'));
+                Y.Assert.isTrue(Y.one('#panel-one').hasClass('hidden'));
+                Y.Assert.isFalse(Y.one('#panel-two').hasClass('hidden'));
+            });
+        });
+        morph.run();
+        this.wait();
+    },
+
+    test__create_resize_animation_resizes: function() {
+        var srcNode = Y.one('#panel-one');
+        var resize = module._create_resize(srcNode, '29');
+        var self = this;
+        resize.on('resized', function () {
+            self.resume(function() {
+                var height_style = srcNode.getStyle('height');
+                Y.Assert.areEqual('auto', height_style);
+            });
+        });
+        resize.run();
+        this.wait();
     }
+
 }));
 
 namespace.suite = suite;


Follow ups