Bug 1301305 - Move test data alongside the test function; r=hiro
authorBrian Birtles <birtles@gmail.com>
Fri, 02 Dec 2016 08:56:29 +0900
changeset 325325 ca7fd1a24055581dbfcd48f2cd71b2abbbad33f3
parent 325324 40c8129cffbf82cd89b4e22caf52aa042b5573e4
child 325326 aa5c5ad83b28d871837a3265d1b35fd2d75e8212
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewershiro
bugs1301305
milestone53.0a1
Bug 1301305 - Move test data alongside the test function; r=hiro Currently these tests are hard to read because the test data is separated from the test function so it's not clear what each of the fields mean or how to use it. This patch just brings the test data and test functions alongside one-another so they are easier to read. MozReview-Commit-ID: EzFLDG4YiXh
dom/animation/test/chrome/test_animation_performance_warning.html
--- a/dom/animation/test/chrome/test_animation_performance_warning.html
+++ b/dom/animation/test/chrome/test_animation_performance_warning.html
@@ -91,538 +91,171 @@ function assert_property_state_on_compos
     assert_true(sortedActual[i].runningOnCompositor,
                 'runningOnCompositor property should be true on ' +
                 sortedActual[i].property);
     assert_not_exists(sortedActual[i], 'warning',
                       'warning property should not be set');
   }
 }
 
-var gAnimationsTests = [
-  {
-    desc: 'animations on compositor',
-    frames: {
-      opacity: [0, 1]
-    },
-    expected: [
-      {
-        property: 'opacity',
-        runningOnCompositor: true
-      }
-    ]
-  },
-  {
-    desc: 'animations on main thread',
-    frames: {
-      backgroundColor: ['white', 'red']
+function testBasicOperation() {
+  [
+    {
+      desc: 'animations on compositor',
+      frames: {
+        opacity: [0, 1]
+      },
+      expected: [
+        {
+          property: 'opacity',
+          runningOnCompositor: true
+        }
+      ]
     },
-    expected: [
-      {
-        property: 'background-color',
-        runningOnCompositor: false
-      }
-    ]
-  },
-  {
-    desc: 'animations on both threads',
-    frames: {
-      backgroundColor: ['white', 'red'],
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    expected: [
-      {
-        property: 'background-color',
-        runningOnCompositor: false
+    {
+      desc: 'animations on main thread',
+      frames: {
+        backgroundColor: ['white', 'red']
       },
-      {
-        property: 'transform',
-        runningOnCompositor: true
-      }
-    ]
-  },
-  {
-    desc: 'two animation properties on compositor thread',
-    frames: {
-      opacity: [0, 1],
-      transform: ['translate(0px)', 'translate(100px)']
+      expected: [
+        {
+          property: 'background-color',
+          runningOnCompositor: false
+        }
+      ]
     },
-    expected: [
-      {
-        property: 'opacity',
-        runningOnCompositor: true
+    {
+      desc: 'animations on both threads',
+      frames: {
+        backgroundColor: ['white', 'red'],
+        transform: ['translate(0px)', 'translate(100px)']
       },
-      {
-        property: 'transform',
-        runningOnCompositor: true
-      }
-    ]
-  },
-  {
-    desc: 'opacity on compositor with animation of geometric properties',
-    frames: {
-      width: ['100px', '200px'],
-      opacity: [0, 1]
-    },
-    expected: [
-      {
-        property: 'width',
-        runningOnCompositor: false
-      },
-      {
-        property: 'opacity',
-        runningOnCompositor: true
-      }
-    ]
-  },
-];
-
-// Test cases that check results of adding/removing a 'width' property on the
-// same animation object.
-var gAnimationWithGeometricKeyframeTests = [
-  {
-    desc: 'transform',
-    frames: {
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    expected: {
-      withoutGeometric: [
+      expected: [
+        {
+          property: 'background-color',
+          runningOnCompositor: false
+        },
         {
           property: 'transform',
           runningOnCompositor: true
         }
-      ],
-      withGeometric: [
-        {
-          property: 'width',
-          runningOnCompositor: false
-        },
-        {
-          property: 'transform',
-          runningOnCompositor: false,
-          warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
-        }
       ]
-    }
-  },
-  {
-    desc: 'opacity and transform',
-    frames: {
-      opacity: [0, 1],
-      transform: ['translate(0px)', 'translate(100px)']
     },
-    expected: {
-      withoutGeometric: [
+    {
+      desc: 'two animation properties on compositor thread',
+      frames: {
+        opacity: [0, 1],
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      expected: [
         {
           property: 'opacity',
           runningOnCompositor: true
         },
         {
           property: 'transform',
           runningOnCompositor: true
         }
-      ],
-      withGeometric: [
+      ]
+    },
+    {
+      desc: 'opacity on compositor with animation of geometric properties',
+      frames: {
+        width: ['100px', '200px'],
+        opacity: [0, 1]
+      },
+      expected: [
         {
           property: 'width',
           runningOnCompositor: false
         },
         {
           property: 'opacity',
           runningOnCompositor: true
-        },
-        {
-          property: 'transform',
-          runningOnCompositor: false,
-          warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
         }
       ]
-    }
-  },
-];
-
-// Performance warning tests that set and clear a style property.
-var gPerformanceWarningTestsStyle = [
-  {
-    desc: 'preserve-3d transform',
-    frames: {
-      transform: ['translate(0px)', 'translate(100px)']
     },
-    style: 'transform-style: preserve-3d',
-    expected: [
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: 'CompositorAnimationWarningTransformPreserve3D'
-      }
-    ]
-  },
-  {
-    desc: 'transform with backface-visibility:hidden',
-    frames: {
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    style: 'backface-visibility: hidden;',
-    expected: [
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
-      }
-    ]
-  },
-  {
-    desc: 'opacity and transform with preserve-3d',
-    frames: {
-      opacity: [0, 1],
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    style: 'transform-style: preserve-3d',
-    expected: [
-      {
-        property: 'opacity',
-        runningOnCompositor: true
-      },
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: 'CompositorAnimationWarningTransformPreserve3D'
-      }
-    ]
-  },
-  {
-    desc: 'opacity and transform with backface-visibility:hidden',
-    frames: {
-      opacity: [0, 1],
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    style: 'backface-visibility: hidden;',
-    expected: [
-      {
-        property: 'opacity',
-        runningOnCompositor: true
-      },
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
-      }
-    ]
-  },
-];
-
-// Performance warning tests that set and clear the id property
-var gPerformanceWarningTestsId= [
-  {
-    desc: 'moz-element referencing a transform',
-    frames: {
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    id: 'transformed',
-    createelement: 'width:100px; height:100px; background: -moz-element(#transformed)',
-    expected: [
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: 'CompositorAnimationWarningHasRenderingObserver'
-      }
-    ]
-  },
-];
-
-var gMultipleAsyncAnimationsTests = [
-  {
-    desc: 'opacity and transform with preserve-3d',
-    style: 'transform-style: preserve-3d',
-    animations: [
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: [
-          {
-            property: 'transform',
-            runningOnCompositor: false,
-            warning: 'CompositorAnimationWarningTransformPreserve3D'
-          }
-        ]
-      },
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: [
-          {
-            property: 'opacity',
-            runningOnCompositor: true,
-          }
-        ]
-      }
-    ],
-  },
-  {
-    desc: 'opacity and transform with backface-visibility:hidden',
-    style: 'backface-visibility: hidden;',
-    animations: [
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: [
-          {
-            property: 'transform',
-            runningOnCompositor: false,
-            warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
-          }
-        ]
-      },
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: [
-          {
-            property: 'opacity',
-            runningOnCompositor: true,
-          }
-        ]
-      }
-    ],
-  },
-];
-
-// Test cases that check results of adding/removing a 'width' keyframe on the
-// same animation object, where multiple animation objects belong to the same
-// element.
-// The 'width' property is added to animations[1].
-var gMultipleAsyncAnimationsWithGeometricKeyframeTests = [
-  {
-    desc: 'transform and opacity with geometric keyframes',
-    animations: [
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: {
-          withoutGeometric: [
-            {
-              property: 'transform',
-              runningOnCompositor: true
-            }
-          ],
-          withGeometric: [
-            {
-              property: 'transform',
-              runningOnCompositor: false,
-              warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
-            }
-          ]
-        }
-      },
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: {
-          withoutGeometric: [
-            {
-              property: 'opacity',
-              runningOnCompositor: true,
-            }
-          ],
-          withGeometric: [
-            {
-              property: 'width',
-              runningOnCompositor: false,
-            },
-            {
-              property: 'opacity',
-              runningOnCompositor: true,
-            }
-          ]
-        }
-      }
-    ],
-  },
-  {
-    desc: 'opacity and transform with geometric keyframes',
-    animations: [
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: {
-          withoutGeometric: [
-            {
-              property: 'opacity',
-              runningOnCompositor: true,
-            }
-          ],
-          withGeometric: [
-            {
-              property: 'opacity',
-              runningOnCompositor: true,
-            }
-          ]
-        }
-      },
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: {
-          withoutGeometric: [
-            {
-              property: 'transform',
-              runningOnCompositor: true
-            }
-          ],
-          withGeometric: [
-            {
-              property: 'width',
-              runningOnCompositor: false,
-            },
-            {
-              property: 'transform',
-              runningOnCompositor: false,
-              warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
-            }
-          ]
-        }
-      }
-    ]
-  },
-];
-
-// Test cases that check results of adding/removing 'width' animation on the
-// same element which has async animations.
-var gMultipleAsyncAnimationsWithGeometricAnimationTests = [
-  {
-    desc: 'transform',
-    animations: [
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: [
-          {
-            property: 'transform',
-            runningOnCompositor: false,
-            warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
-          }
-        ]
-      },
-    ]
-  },
-  {
-    desc: 'opacity',
-    animations: [
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: [
-          {
-            property: 'opacity',
-            runningOnCompositor: true
-          }
-        ]
-      },
-    ]
-  },
-  {
-    desc: 'opacity and transform',
-    animations: [
-      {
-        frames: {
-          transform: ['translate(0px)', 'translate(100px)']
-        },
-        expected: [
-          {
-            property: 'transform',
-            runningOnCompositor: false,
-            warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
-          }
-        ]
-      },
-      {
-        frames: {
-          opacity: [0, 1]
-        },
-        expected: [
-          {
-            property: 'opacity',
-            runningOnCompositor: true,
-          }
-        ]
-      }
-    ],
-  },
-];
-
-var gAnimationsOnTooSmallElementTests = [
-  {
-    desc: 'opacity on too small element',
-    frames: {
-      opacity: [0, 1]
-    },
-    style: { style: 'width: 8px; height: 8px; background-color: red;' +
-                    // We need to set transform here to try creating an
-                    // individual frame for this opacity element.
-                    // Without this, this small element is created on the same
-                    // nsIFrame of mochitest iframe, i.e. the document which are
-                    // running this test, as a result the layer corresponding
-                    // to the frame is sent to compositor.
-                    'transform: translateX(100px);' },
-    expected: [
-      {
-        property: 'opacity',
-        runningOnCompositor: false,
-        warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
-      }
-    ]
-  },
-  {
-    desc: 'transform on too small element',
-    frames: {
-      transform: ['translate(0px)', 'translate(100px)']
-    },
-    style: { style: 'width: 8px; height: 8px; background-color: red;' },
-    expected: [
-      {
-        property: 'transform',
-        runningOnCompositor: false,
-        warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
-      }
-    ]
-  },
-];
-
-function start() {
-  var bundleService = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1']
-    .getService(SpecialPowers.Ci.nsIStringBundleService);
-  gStringBundle = bundleService
-    .createBundle("chrome://global/locale/layout_errors.properties");
-
-  gAnimationsTests.forEach(function(subtest) {
+  ].forEach(subtest => {
     promise_test(function(t) {
-      var animation = addDivAndAnimate(t,
-                                       { class: 'compositable' },
+      var animation = addDivAndAnimate(t, { class: 'compositable' },
                                        subtest.frames, 100 * MS_PER_SEC);
       return animation.ready.then(function() {
         assert_animation_property_state_equals(
           animation.effect.getProperties(),
           subtest.expected);
       });
     }, subtest.desc);
   });
+}
 
-  gAnimationWithGeometricKeyframeTests.forEach(function(subtest) {
+// Test adding/removing a 'width' property on the same animation object.
+function testKeyframesWithGeometricProperties() {
+  [
+    {
+      desc: 'transform',
+      frames: {
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      expected: {
+        withoutGeometric: [
+          {
+            property: 'transform',
+            runningOnCompositor: true
+          }
+        ],
+        withGeometric: [
+          {
+            property: 'width',
+            runningOnCompositor: false
+          },
+          {
+            property: 'transform',
+            runningOnCompositor: false,
+            warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+          }
+        ]
+      }
+    },
+    {
+      desc: 'opacity and transform',
+      frames: {
+        opacity: [0, 1],
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      expected: {
+        withoutGeometric: [
+          {
+            property: 'opacity',
+            runningOnCompositor: true
+          },
+          {
+            property: 'transform',
+            runningOnCompositor: true
+          }
+        ],
+        withGeometric: [
+          {
+            property: 'width',
+            runningOnCompositor: false
+          },
+          {
+            property: 'opacity',
+            runningOnCompositor: true
+          },
+          {
+            property: 'transform',
+            runningOnCompositor: false,
+            warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+          }
+        ]
+      }
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
-      var animation = addDivAndAnimate(t,
-                                       { class: 'compositable' },
+      var animation = addDivAndAnimate(t, { class: 'compositable' },
                                        subtest.frames, 100 * MS_PER_SEC);
       return animation.ready.then(function() {
         // First, a transform animation is running on compositor.
         assert_animation_property_state_equals(
           animation.effect.getProperties(),
           subtest.expected.withoutGeometric);
       }).then(function() {
         // Add a 'width' property.
@@ -651,21 +284,90 @@ function start() {
       }).then(function() {
         // Finally, the transform animation is running on compositor.
         assert_animation_property_state_equals(
           animation.effect.getProperties(),
           subtest.expected.withoutGeometric);
       });
     }, 'An animation has: ' + subtest.desc);
   });
+}
 
-  gPerformanceWarningTestsStyle.forEach(function(subtest) {
+// Performance warning tests that set and clear a style property.
+function testStyleChanges() {
+  [
+    {
+      desc: 'preserve-3d transform',
+      frames: {
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      style: 'transform-style: preserve-3d',
+      expected: [
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: 'CompositorAnimationWarningTransformPreserve3D'
+        }
+      ]
+    },
+    {
+      desc: 'transform with backface-visibility:hidden',
+      frames: {
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      style: 'backface-visibility: hidden;',
+      expected: [
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
+        }
+      ]
+    },
+    {
+      desc: 'opacity and transform with preserve-3d',
+      frames: {
+        opacity: [0, 1],
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      style: 'transform-style: preserve-3d',
+      expected: [
+        {
+          property: 'opacity',
+          runningOnCompositor: true
+        },
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: 'CompositorAnimationWarningTransformPreserve3D'
+        }
+      ]
+    },
+    {
+      desc: 'opacity and transform with backface-visibility:hidden',
+      frames: {
+        opacity: [0, 1],
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      style: 'backface-visibility: hidden;',
+      expected: [
+        {
+          property: 'opacity',
+          runningOnCompositor: true
+        },
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
+        }
+      ]
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
-      var animation = addDivAndAnimate(t,
-                                       { class: 'compositable' },
+      var animation = addDivAndAnimate(t, { class: 'compositable' },
                                        subtest.frames, 100 * MS_PER_SEC);
       return animation.ready.then(function() {
         assert_property_state_on_compositor(
           animation.effect.getProperties(),
           subtest.expected);
         animation.effect.target.style = subtest.style;
         return waitForFrame();
       }).then(function() {
@@ -676,25 +378,43 @@ function start() {
         return waitForFrame();
       }).then(function() {
         assert_property_state_on_compositor(
           animation.effect.getProperties(),
           subtest.expected);
       });
     }, subtest.desc);
   });
+}
 
-  gPerformanceWarningTestsId.forEach(function(subtest) {
+// Performance warning tests that set and clear the id property
+function testIdChanges() {
+  [
+    {
+      desc: 'moz-element referencing a transform',
+      frames: {
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      id: 'transformed',
+      createelement: 'width:100px; height:100px; background: -moz-element(#transformed)',
+      expected: [
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: 'CompositorAnimationWarningHasRenderingObserver'
+        }
+      ]
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
       if (subtest.createelement) {
         addDiv(t, { style: subtest.createelement });
       }
 
-      var animation = addDivAndAnimate(t,
-                                       { class: 'compositable' },
+      var animation = addDivAndAnimate(t, { class: 'compositable' },
                                        subtest.frames, 100 * MS_PER_SEC);
       return animation.ready.then(function() {
         assert_property_state_on_compositor(
           animation.effect.getProperties(),
           subtest.expected);
         animation.effect.target.id = subtest.id;
         return waitForFrame();
       }).then(function() {
@@ -705,164 +425,447 @@ function start() {
         return waitForFrame();
       }).then(function() {
         assert_property_state_on_compositor(
           animation.effect.getProperties(),
           subtest.expected);
       });
     }, subtest.desc);
   });
+}
 
-  gMultipleAsyncAnimationsTests.forEach(function(subtest) {
+function testMultipleAnimations() {
+  [
+    {
+      desc: 'opacity and transform with preserve-3d',
+      style: 'transform-style: preserve-3d',
+      animations: [
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: [
+            {
+              property: 'transform',
+              runningOnCompositor: false,
+              warning: 'CompositorAnimationWarningTransformPreserve3D'
+            }
+          ]
+        },
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: [
+            {
+              property: 'opacity',
+              runningOnCompositor: true,
+            }
+          ]
+        }
+      ],
+    },
+    {
+      desc: 'opacity and transform with backface-visibility:hidden',
+      style: 'backface-visibility: hidden;',
+      animations: [
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: [
+            {
+              property: 'transform',
+              runningOnCompositor: false,
+              warning: 'CompositorAnimationWarningTransformBackfaceVisibilityHidden'
+            }
+          ]
+        },
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: [
+            {
+              property: 'opacity',
+              runningOnCompositor: true,
+            }
+          ]
+        }
+      ],
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
       var div = addDiv(t, { class: 'compositable' });
       var animations = subtest.animations.map(function(anim) {
         var animation = div.animate(anim.frames, 100 * MS_PER_SEC);
 
         // Bind expected values to animation object.
         animation.expected = anim.expected;
         return animation;
       });
       return waitForAllAnimations(animations).then(function() {
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_property_state_on_compositor(
             anim.effect.getProperties(),
             anim.expected);
         });
         div.style = subtest.style;
         return waitForFrame();
       }).then(function() {
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_animation_property_state_equals(
             anim.effect.getProperties(),
             anim.expected);
         });
         div.style = '';
         return waitForFrame();
       }).then(function() {
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_property_state_on_compositor(
             anim.effect.getProperties(),
             anim.expected);
         });
       });
     }, 'Multiple animations: ' + subtest.desc);
   });
+}
 
-  gMultipleAsyncAnimationsWithGeometricKeyframeTests.forEach(function(subtest) {
+// Test adding/removing a 'width' keyframe on the same animation object, where
+// multiple animation objects belong to the same element.
+// The 'width' property is added to animations[1].
+function testMultipleAnimationsWithGeometricKeyframes() {
+  [
+    {
+      desc: 'transform and opacity with geometric keyframes',
+      animations: [
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: {
+            withoutGeometric: [
+              {
+                property: 'transform',
+                runningOnCompositor: true
+              }
+            ],
+            withGeometric: [
+              {
+                property: 'transform',
+                runningOnCompositor: false,
+                warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+              }
+            ]
+          }
+        },
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: {
+            withoutGeometric: [
+              {
+                property: 'opacity',
+                runningOnCompositor: true,
+              }
+            ],
+            withGeometric: [
+              {
+                property: 'width',
+                runningOnCompositor: false,
+              },
+              {
+                property: 'opacity',
+                runningOnCompositor: true,
+              }
+            ]
+          }
+        }
+      ],
+    },
+    {
+      desc: 'opacity and transform with geometric keyframes',
+      animations: [
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: {
+            withoutGeometric: [
+              {
+                property: 'opacity',
+                runningOnCompositor: true,
+              }
+            ],
+            withGeometric: [
+              {
+                property: 'opacity',
+                runningOnCompositor: true,
+              }
+            ]
+          }
+        },
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: {
+            withoutGeometric: [
+              {
+                property: 'transform',
+                runningOnCompositor: true
+              }
+            ],
+            withGeometric: [
+              {
+                property: 'width',
+                runningOnCompositor: false,
+              },
+              {
+                property: 'transform',
+                runningOnCompositor: false,
+                warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+              }
+            ]
+          }
+        }
+      ]
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
       var div = addDiv(t, { class: 'compositable' });
       var animations = subtest.animations.map(function(anim) {
         var animation = div.animate(anim.frames, 100 * MS_PER_SEC);
 
         // Bind expected values to animation object.
         animation.expected = anim.expected;
         return animation;
       });
       return waitForAllAnimations(animations).then(function() {
         // First, all animations are running on compositor.
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_animation_property_state_equals(
             anim.effect.getProperties(),
             anim.expected.withoutGeometric);
         });
       }).then(function() {
         // Add a 'width' property to animations[1].
         var keyframes = animations[1].effect.getKeyframes();
 
         keyframes[0].width = '100px';
         keyframes[1].width = '200px';
 
         animations[1].effect.setKeyframes(keyframes);
         return waitForFrame();
       }).then(function() {
         // Now the transform animation is not running on compositor because of
         // the 'width' property.
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_animation_property_state_equals(
             anim.effect.getProperties(),
             anim.expected.withGeometric);
         });
       }).then(function() {
         // Remove the 'width' property from animations[1].
         var keyframes = animations[1].effect.getKeyframes();
 
         delete keyframes[0].width;
         delete keyframes[1].width;
 
         animations[1].effect.setKeyframes(keyframes);
         return waitForFrame();
       }).then(function() {
         // Finally, all animations are running on compositor.
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_animation_property_state_equals(
             anim.effect.getProperties(),
             anim.expected.withoutGeometric);
         });
       });
     }, 'Multiple animations with geometric property: ' + subtest.desc);
   });
+}
 
-  gMultipleAsyncAnimationsWithGeometricAnimationTests.forEach(function(subtest) {
+// Tests adding/removing 'width' animation on the same element which has async
+// animations.
+function testMultipleAnimationsWithGeometricAnimations() {
+  [
+    {
+      desc: 'transform',
+      animations: [
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: [
+            {
+              property: 'transform',
+              runningOnCompositor: false,
+              warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+            }
+          ]
+        },
+      ]
+    },
+    {
+      desc: 'opacity',
+      animations: [
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: [
+            {
+              property: 'opacity',
+              runningOnCompositor: true
+            }
+          ]
+        },
+      ]
+    },
+    {
+      desc: 'opacity and transform',
+      animations: [
+        {
+          frames: {
+            transform: ['translate(0px)', 'translate(100px)']
+          },
+          expected: [
+            {
+              property: 'transform',
+              runningOnCompositor: false,
+              warning: 'CompositorAnimationWarningTransformWithGeometricProperties'
+            }
+          ]
+        },
+        {
+          frames: {
+            opacity: [0, 1]
+          },
+          expected: [
+            {
+              property: 'opacity',
+              runningOnCompositor: true,
+            }
+          ]
+        }
+      ],
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
       var div = addDiv(t, { class: 'compositable' });
       var animations = subtest.animations.map(function(anim) {
         var animation = div.animate(anim.frames, 100 * MS_PER_SEC);
 
         // Bind expected values to animation object.
         animation.expected = anim.expected;
         return animation;
       });
 
       var widthAnimation;
 
       return waitForAllAnimations(animations).then(function() {
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_property_state_on_compositor(
             anim.effect.getProperties(),
             anim.expected);
         });
       }).then(function() {
         // Append 'width' animation on the same element.
         widthAnimation = div.animate({ width: ['100px', '200px'] },
                                      100 * MS_PER_SEC);
         return waitForFrame();
       }).then(function() {
         // Now transform animations are not running on compositor because of
         // the 'width' animation.
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_animation_property_state_equals(
             anim.effect.getProperties(),
             anim.expected);
         });
         // Remove the 'width' animation.
         widthAnimation.cancel();
         return waitForFrame();
       }).then(function() {
         // Now all animations are running on compositor.
-        animations.forEach(function(anim) {
+        animations.forEach(anim => {
           assert_property_state_on_compositor(
             anim.effect.getProperties(),
             anim.expected);
         });
       });
     }, 'Multiple async animations and geometric animation: ' + subtest.desc);
   });
+}
 
-  gAnimationsOnTooSmallElementTests.forEach(function(subtest) {
+function testSmallElements() {
+  [
+    {
+      desc: 'opacity on too small element',
+      frames: {
+        opacity: [0, 1]
+      },
+      style: { style: 'width: 8px; height: 8px; background-color: red;' +
+                      // We need to set transform here to try creating an
+                      // individual frame for this opacity element.
+                      // Without this, this small element is created on the same
+                      // nsIFrame of mochitest iframe, i.e. the document which are
+                      // running this test, as a result the layer corresponding
+                      // to the frame is sent to compositor.
+                      'transform: translateX(100px);' },
+      expected: [
+        {
+          property: 'opacity',
+          runningOnCompositor: false,
+          warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
+        }
+      ]
+    },
+    {
+      desc: 'transform on too small element',
+      frames: {
+        transform: ['translate(0px)', 'translate(100px)']
+      },
+      style: { style: 'width: 8px; height: 8px; background-color: red;' },
+      expected: [
+        {
+          property: 'transform',
+          runningOnCompositor: false,
+          warning: /Animation cannot be run on the compositor because frame size \(8, 8\) is smaller than \(16, 16\)/
+        }
+      ]
+    },
+  ].forEach(subtest => {
     promise_test(function(t) {
     var div = addDiv(t, subtest.style);
     var animation = div.animate(subtest.frames, 100 * MS_PER_SEC);
       return animation.ready.then(function() {
         assert_animation_property_state_equals(
           animation.effect.getProperties(),
           subtest.expected);
       });
     }, subtest.desc);
   });
+}
+
+function start() {
+  var bundleService = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1']
+    .getService(SpecialPowers.Ci.nsIStringBundleService);
+  gStringBundle = bundleService
+    .createBundle("chrome://global/locale/layout_errors.properties");
+
+  testBasicOperation();
+  testKeyframesWithGeometricProperties();
+  testStyleChanges();
+  testIdChanges();
+  testMultipleAnimations();
+  testMultipleAnimationsWithGeometricKeyframes();
+  testMultipleAnimationsWithGeometricAnimations();
+  testSmallElements();
 
   promise_test(function(t) {
     var animation = addDivAndAnimate(t,
                                      { class: 'compositable' },
                                      { transform: [ 'translate(0px)',
                                                     'translate(100px)'] },
                                      100 * MS_PER_SEC);
     return animation.ready.then(function() {