Bug 1356779 - Add tests for interaction between prefixed and non-prefixed @keyframes rules with the same name. r?dholbert draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 21 Apr 2017 12:15:27 +0900
changeset 566196 89a6645dbd003a9ce8528ab7a508ebe06f2ebf93
parent 566195 48a49d7e1c1ac138d080bf7e66d2da015f17b40a
child 625236 9921db7369fc1fe2aee87740c641c2e27e9d2166
push id55132
push userhikezoe@mozilla.com
push dateFri, 21 Apr 2017 04:05:32 +0000
reviewersdholbert
bugs1356779
milestone55.0a1
Bug 1356779 - Add tests for interaction between prefixed and non-prefixed @keyframes rules with the same name. r?dholbert MozReview-Commit-ID: KxP53Ha5eEX
layout/style/test/mochitest.ini
layout/style/test/test_keyframes_vendor_prefix.html
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -219,16 +219,17 @@ skip-if = stylo # bug 1339656
 [test_ident_escaping.html]
 [test_inherit_computation.html]
 skip-if = toolkit == 'android'
 [test_inherit_storage.html]
 [test_initial_computation.html]
 skip-if = toolkit == 'android'
 [test_initial_storage.html]
 [test_keyframes_rules.html]
+[test_keyframes_vendor_prefix.html]
 [test_load_events_on_stylesheets.html]
 [test_logical_properties.html]
 [test_media_queries.html]
 skip-if = android_version == '18' #debug-only failure; timed out #Android 4.3 aws only; bug 1030419
 [test_media_queries_dynamic.html]
 [test_media_queries_dynamic_xbl.html]
 [test_media_query_list.html]
 [test_moz_device_pixel_ratio.html]
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_keyframes_vendor_prefix.html
@@ -0,0 +1,193 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>
+Test for interaction between prefixed and non-prefixed @keyframes rules with
+the same name
+</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<div id='log'></div>
+<script>
+/**
+ * Appends a style element to the document head.
+ *
+ * @param t  The testharness.js Test object. If provided, this will be used
+ *           to register a cleanup callback to remove the style element
+ *           when the test finishes.
+ *
+ * @param rules  A dictionary object with selector names and rules to set on
+ *               the style sheet.
+ */
+function addStyle(t, rules) {
+  var extraStyle = document.createElement('style');
+  document.head.appendChild(extraStyle);
+  if (rules) {
+    var sheet = extraStyle.sheet;
+    for (var selector in rules) {
+      sheet.insertRule(selector + '{' + rules[selector] + '}',
+                       sheet.cssRules.length);
+    }
+  }
+
+  if (t && typeof t.add_cleanup === 'function') {
+    t.add_cleanup(function() {
+      extraStyle.remove();
+    });
+  }
+}
+
+/**
+ * Appends a div to the document body.
+ *
+ * @param t  The testharness.js Test object. If provided, this will be used
+ *           to register a cleanup callback to remove the div when the test
+ *           finishes.
+ *
+ * @param attrs  A dictionary object with attribute names and values to set on
+ *               the div.
+ */
+function addDiv(t, attrs) {
+  var div = document.createElement('div');
+  if (attrs) {
+    for (var attrName in attrs) {
+      div.setAttribute(attrName, attrs[attrName]);
+    }
+  }
+  document.body.appendChild(div);
+  if (t && typeof t.add_cleanup === 'function') {
+    t.add_cleanup(function() {
+      div.remove();
+    });
+  }
+  return div;
+}
+
+var isStylo = false;
+// 'layout.css.servo.enabled' is not yet defined on gecko, so we need a try
+// block.
+try {
+  isStylo = SpecialPowers.getBoolPref('layout.css.servo.enabled');
+} catch(e) {
+}
+
+test(function(t) {
+  addStyle(t,
+    { 'dummy': '', // XXX bug 1336863 hackaround: a single insertRule is broken
+                   // on stylo.
+      '@-webkit-keyframes anim': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-webkit- prefix keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { 'dummy': '', // XXX bug 1336863 hackaround, as above.
+      '@-moz-keyframes anim': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-moz- prefix keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { 'dummy': '', // XXX bug 1336863 hackaround, as above.
+      '@-WEBKIT-keyframes anim': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-WEBKIT- prefix keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { 'dummy': '', // XXX bug 1336863 hackaround, as above.
+      '@-MOZ-keyframes anim': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-MOZ- prefix keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { 'dummy': '', // XXX bug 1336863 hackaround, as above.
+      '@-webkit-KEYFRAMES anim': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-webkit- prefix KEYFRAMES');
+
+test(function(t) {
+  if (!isStylo) {
+    // FIXME: Bug 1312918: later prefixed rule incorrectly overrides earlier
+    // non-prefixed on gecko.
+    return;
+  }
+
+  addStyle(t,
+    { '@keyframes anim':         'from,to { color: rgb(0, 255, 0); }',
+      '@-webkit-keyframes anim': 'from,to { color: rgb(255, 0, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-webkit-keyframes should not override earlier non-prefix keyframes');
+
+test(function(t) {
+  if (!isStylo) {
+    // FIXME: Bug 1312918: later prefixed rule incorrectly overrides earlier
+    // non-prefixed on gecko.
+    return;
+  }
+
+  addStyle(t,
+    { '@keyframes anim':      'from,to { color: rgb(0, 255, 0); }',
+      '@-moz-keyframes anim': 'from,to { color: rgb(255, 0, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, '-moz-keyframes should not override earlier non-prefix keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { '@-moz-keyframes anim': 'from,to { color: rgb(255, 0, 0); }',
+      '@keyframes anim':      'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, 'non-prefix keyframes should override earlier -moz-keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { '@-webkit-keyframes anim': 'from,to { color: rgb(255, 0, 0); }',
+      '@keyframes anim':         'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, 'non-prefix keyframes should override earlier -webkit-keyframes');
+
+test(function(t) {
+  addStyle(t,
+    { '@-webkit-keyframes anim': 'from,to { color: rgb(255, 0, 0); }',
+      '@-moz-keyframes anim':    'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+
+  addStyle(t,
+    { '@-moz-keyframes anim2':    'from,to { color: rgb(255, 0, 0); }',
+      '@-webkit-keyframes anim2': 'from,to { color: rgb(0, 255, 0); }' });
+
+  var div = addDiv(t, { style: 'animation: anim2 100s' });
+
+  assert_equals(getComputedStyle(div).color, 'rgb(0, 255, 0)');
+}, 'last prefixed keyframes should override earlier prefixed keyframes');
+</script>