Bug 1245849 - Remove mochitest browser_animation_name.js and add a xpcshell test instead; r=ochameau draft
authorPatrick Brosset <pbrosset@mozilla.com>
Mon, 08 Feb 2016 13:42:28 +0100
changeset 329528 af66171068bd45c0d031cc1f8e090182396384b4
parent 329527 411bf60720dc8dd21a2b5df3b1c175b3fc9e0edf
child 513972 45ed7882ac010ab2259e5b948910f99613631e1c
push id10540
push userpbrosset@mozilla.com
push dateMon, 08 Feb 2016 12:44:01 +0000
reviewersochameau
bugs1245849
milestone47.0a1
Bug 1245849 - Remove mochitest browser_animation_name.js and add a xpcshell test instead; r=ochameau
devtools/server/actors/animation.js
devtools/server/tests/browser/animation.html
devtools/server/tests/browser/browser.ini
devtools/server/tests/browser/browser_animation_name.js
devtools/server/tests/unit/test_animation_name.js
devtools/server/tests/unit/test_animation_type.js
devtools/server/tests/unit/xpcshell.ini
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -36,16 +36,17 @@ const {NodeActor} = require("devtools/se
 const events = require("sdk/event/core");
 
 // Types of animations.
 const ANIMATION_TYPES = {
   CSS_ANIMATION: "cssanimation",
   CSS_TRANSITION: "csstransition",
   UNKNOWN: "unknown"
 };
+exports.ANIMATION_TYPES = ANIMATION_TYPES;
 
 /**
  * The AnimationPlayerActor provides information about a given animation: its
  * startTime, currentTime, current state, etc.
  *
  * Since the state of a player changes as the animation progresses it is often
  * useful to call getCurrentState at regular intervals to get the current state.
  *
@@ -66,41 +67,40 @@ var AnimationPlayerActor = ActorClass({
    * @param {AnimationPlayer} The player object returned by getAnimationPlayers
    */
   initialize: function(animationsActor, player) {
     Actor.prototype.initialize.call(this, animationsActor.conn);
 
     this.onAnimationMutation = this.onAnimationMutation.bind(this);
 
     this.walker = animationsActor.walker;
-    this.tabActor = animationsActor.tabActor;
     this.player = player;
     this.node = player.effect.target;
 
-    let win = this.node.ownerDocument.defaultView;
-    this.styles = win.getComputedStyle(this.node);
-
     // Listen to animation mutations on the node to alert the front when the
     // current animation changes.
-    this.observer = new win.MutationObserver(this.onAnimationMutation);
+    this.observer = new this.window.MutationObserver(this.onAnimationMutation);
     this.observer.observe(this.node, {animations: true});
   },
 
   destroy: function() {
     // Only try to disconnect the observer if it's not already dead (i.e. if the
     // container view hasn't navigated since).
     if (this.observer && !Cu.isDeadWrapper(this.observer)) {
       this.observer.disconnect();
     }
-    this.tabActor = this.player = this.node = this.styles = null;
-    this.observer = this.walker = null;
+    this.player = this.node = this.observer = this.walker = null;
 
     Actor.prototype.destroy.call(this);
   },
 
+  get window() {
+    return this.node.ownerDocument.defaultView;
+  },
+
   /**
    * Release the actor, when it isn't needed anymore.
    * Protocol.js uses this release method to call the destroy method.
    */
   release: method(function() {}, {release: true}),
 
   form: function(detail) {
     if (detail === "actorid") {
@@ -114,22 +114,22 @@ var AnimationPlayerActor = ActorClass({
     // return its corresponding NodeActor ID too.
     if (this.walker && this.walker.hasNode(this.node)) {
       data.animationTargetNodeActorID = this.walker.getNode(this.node).actorID;
     }
 
     return data;
   },
 
-  isAnimation: function(player=this.player) {
-    return player instanceof this.tabActor.window.CSSAnimation;
+  isAnimation: function(player = this.player) {
+    return player instanceof this.window.CSSAnimation;
   },
 
-  isTransition: function(player=this.player) {
-    return player instanceof this.tabActor.window.CSSTransition;
+  isTransition: function(player = this.player) {
+    return player instanceof this.window.CSSTransition;
   },
 
   getType: function() {
     if (this.isAnimation()) {
       return ANIMATION_TYPES.CSS_ANIMATION;
     } else if (this.isTransition()) {
       return ANIMATION_TYPES.CSS_TRANSITION;
     }
@@ -367,16 +367,18 @@ var AnimationPlayerActor = ActorClass({
   }, {
     request: {},
     response: {
       frames: RetVal("json")
     }
   })
 });
 
+exports.AnimationPlayerActor = AnimationPlayerActor;
+
 var AnimationPlayerFront = FrontClass(AnimationPlayerActor, {
   initialize: function(conn, form, detail, ctx) {
     Front.prototype.initialize.call(this, conn, form, detail, ctx);
 
     this.state = {};
   },
 
   form: function(form, detail) {
--- a/devtools/server/tests/browser/animation.html
+++ b/devtools/server/tests/browser/animation.html
@@ -140,56 +140,28 @@
     }
   }
 
   @keyframes grow {
     100% {
       width: 100px;
     }
   }
-
-  .script-generated {
-    display: inline-block;
-
-    width: 50px;
-    height: 50px;
-    border-radius: 50%;
-    background-color: black;
-    background-image:
-      repeating-linear-gradient(45deg, transparent 0, transparent 5px, #f06 5px, #f06 10px);
-    border: 5px solid #f06;
-    box-sizing: border-box;
-  }
 </style>
 <div class="not-animated"></div>
 <div class="simple-animation"></div>
 <div class="multiple-animations"></div>
 <div class="transition"></div>
 <div class="long-animation"></div>
 <div class="short-animation"></div>
 <div class="delayed-animation"></div>
 <div class="delayed-transition"></div>
 <div class="delayed-multiple-animations"></div>
 <div class="multiple-animations-2"></div>
 <div class="all-transitions"></div>
-<div class="script-generated"></div>
 <script type="text/javascript">
   // Get the transitions started when the page loads
   var players;
   addEventListener("load", function() {
     document.querySelector(".transition").classList.add("get-round");
     document.querySelector(".delayed-transition").classList.add("get-round");
-
-    // Create a script-generated animation.
-    var animation = document.querySelector(".script-generated").animate({
-      backgroundColor: ["black", "gold"]
-    }, {
-      duration: 500,
-      iterations: Infinity,
-      direction: "alternate"
-    });
-    animation.id = "custom-animation-name";
-
-    // Add a custom animation id to an existing css animation.
-    document.querySelector(".delayed-animation")
-            .getAnimations()[0].id = "cssanimation-custom-name";
   });
 </script>
--- a/devtools/server/tests/browser/browser.ini
+++ b/devtools/server/tests/browser/browser.ini
@@ -23,17 +23,16 @@ support-files =
 
 [browser_animation_emitMutations.js]
 [browser_animation_getFrames.js]
 [browser_animation_getMultipleStates.js]
 [browser_animation_getPlayers.js]
 [browser_animation_getStateAfterFinished.js]
 [browser_animation_getSubTreeAnimations.js]
 [browser_animation_keepFinished.js]
-[browser_animation_name.js]
 [browser_animation_playerState.js]
 [browser_animation_playPauseIframe.js]
 [browser_animation_playPauseSeveral.js]
 [browser_animation_reconstructState.js]
 [browser_animation_refreshTransitions.js]
 [browser_animation_setCurrentTime.js]
 [browser_animation_setPlaybackRate.js]
 [browser_animation_simple.js]
deleted file mode 100644
--- a/devtools/server/tests/browser/browser_animation_name.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test that the AnimationPlayerActor provides the correct name for an
-// animation. Whether this animation is a CSSAnimation, CSSTransition or a
-// script-based animation that has been given an id, or even a CSSAnimation that
-// has been given an id.
-
-const TEST_DATA = [{
-  selector: ".simple-animation",
-  animationIndex: 0,
-  expectedName: "move"
-}, {
-  selector: ".transition",
-  animationIndex: 0,
-  expectedName: "width"
-}, {
-  selector: ".script-generated",
-  animationIndex: 0,
-  expectedName: "custom-animation-name"
-}, {
-  selector: ".delayed-animation",
-  animationIndex: 0,
-  expectedName: "cssanimation-custom-name"
-}];
-
-add_task(function*() {
-  let {client, walker, animations} =
-    yield initAnimationsFrontForUrl(MAIN_DOMAIN + "animation.html");
-
-  for (let {selector, animationIndex, expectedName} of TEST_DATA) {
-    let {name} = yield getAnimationStateForNode(walker, animations, selector,
-                                                animationIndex);
-    is(name, expectedName, "The animation has the expected name");
-  }
-
-  yield closeDebuggerClient(client);
-  gBrowser.removeCurrentTab();
-});
-
-function* getAnimationStateForNode(walker, animations, nodeSelector, index) {
-  let node = yield walker.querySelector(walker.rootNode, nodeSelector);
-  let players = yield animations.getAnimationPlayersForNode(node);
-  let player = players[index];
-  yield player.ready();
-  let state = yield player.getCurrentState();
-  return state;
-}
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_animation_name.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that AnimationPlayerActor.getName returns the right name depending on
+// the type of an animation and the various properties available on it.
+
+const { AnimationPlayerActor } = require("devtools/server/actors/animation");
+
+function run_test() {
+  // Mock a window with just the properties the AnimationPlayerActor uses.
+  let window = {
+    MutationObserver: function() {
+      this.observe = () => {};
+    },
+    Animation: function() {
+      this.effect = {target: getMockNode()};
+    },
+    CSSAnimation: function() {
+      this.effect = {target: getMockNode()};
+    },
+    CSSTransition: function() {
+      this.effect = {target: getMockNode()};
+    }
+  };
+  window.CSSAnimation.prototype = Object.create(window.Animation.prototype);
+  window.CSSTransition.prototype = Object.create(window.Animation.prototype);
+
+  // Helper to get a mock DOM node.
+  function getMockNode() {
+    return {
+      ownerDocument: {
+        defaultView: window
+      }
+    };
+  }
+
+  // Objects in this array should contain the following properties:
+  // - desc {String} For logging
+  // - animation {Object} An animation object instantiated from one of the mock
+  //   window animation constructors.
+  // - props {Objet} Properties of this object will be added to the animation
+  //   object.
+  // - expectedName {String} The expected name out of getName.
+  const TEST_DATA = [{
+    desc: "Animation with an id",
+    animation: new window.Animation(),
+    props: { id: "animation-id" },
+    expectedName: "animation-id"
+  }, {
+    desc: "CSSTransition with an id",
+    animation: new window.CSSTransition(),
+    props: { id: "transition-with-id", transitionProperty: "width" },
+    expectedName: "transition-with-id"
+  }, {
+    desc: "CSSAnimation with an id",
+    animation: new window.CSSAnimation(),
+    props: { id: "animation-with-id", animationName: "move" },
+    expectedName: "animation-with-id"
+  }, {
+    desc: "CSSTransition without an id",
+    animation: new window.CSSTransition(),
+    props: { transitionProperty: "width" },
+    expectedName: "width"
+  }, {
+    desc: "CSSAnimation without an id",
+    animation: new window.CSSAnimation(),
+    props: { animationName: "move" },
+    expectedName: "move"
+  }];
+
+  for (let { desc, animation, props, expectedName } of TEST_DATA) {
+    do_print(desc);
+    for (let key in props) {
+      animation[key] = props[key];
+    }
+    let actor = AnimationPlayerActor({}, animation);
+    do_check_eq(actor.getName(), expectedName);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_animation_type.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test the output of AnimationPlayerActor.getType().
+
+const { ANIMATION_TYPES, AnimationPlayerActor } =
+  require("devtools/server/actors/animation");
+
+function run_test() {
+  // Mock a window with just the properties the AnimationPlayerActor uses.
+  let window = {
+    MutationObserver: function() {
+      this.observe = () => {};
+    },
+    Animation: function() {
+      this.effect = {target: getMockNode()};
+    },
+    CSSAnimation: function() {
+      this.effect = {target: getMockNode()};
+    },
+    CSSTransition: function() {
+      this.effect = {target: getMockNode()};
+    }
+  };
+  window.CSSAnimation.prototype = Object.create(window.Animation.prototype);
+  window.CSSTransition.prototype = Object.create(window.Animation.prototype);
+
+  // Helper to get a mock DOM node.
+  function getMockNode() {
+    return {
+      ownerDocument: {
+        defaultView: window
+      }
+    };
+  }
+
+  // Objects in this array should contain the following properties:
+  // - desc {String} For logging
+  // - animation {Object} An animation object instantiated from one of the mock
+  //   window animation constructors.
+  // - expectedType {String} The expected type out of getType.
+  const TEST_DATA = [{
+    desc: "Test CSSAnimation type",
+    animation: new window.CSSAnimation(),
+    expectedType: ANIMATION_TYPES.CSS_ANIMATION
+  }, {
+    desc: "Test CSSTransition type",
+    animation: new window.CSSTransition(),
+    expectedType: ANIMATION_TYPES.CSS_TRANSITION
+  }, {
+    desc: "Test unknown type",
+    animation: {effect: {target: getMockNode()}},
+    expectedType: ANIMATION_TYPES.UNKNOWN
+  }];
+
+  for (let { desc, animation, expectedType } of TEST_DATA) {
+    do_print(desc);
+    let actor = AnimationPlayerActor({}, animation);
+    do_check_eq(actor.getType(), expectedType);
+  }
+}
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -28,16 +28,18 @@ support-files =
   setBreakpoint-on-line.js
   setBreakpoint-on-line-in-gcd-script.js
   setBreakpoint-on-line-with-multiple-offsets.js
   setBreakpoint-on-line-with-multiple-statements.js
   setBreakpoint-on-line-with-no-offsets.js
   setBreakpoint-on-line-with-no-offsets-at-end-of-script.js
   setBreakpoint-on-line-with-no-offsets-in-gcd-script.js
 
+[test_animation_name.js]
+[test_animation_type.js]
 [test_ScriptStore.js]
 [test_actor-registry-actor.js]
 [test_nesting-01.js]
 [test_nesting-02.js]
 [test_nesting-03.js]
 [test_forwardingprefix.js]
 [test_getyoungestframe.js]
 [test_nsjsinspector.js]