layout/style/test/test_value_storage.html

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 <!DOCTYPE HTML>
     2 <html>
     3 <!--
     4 -->
     5 <head>
     6   <title>Test for parsing, storage, and serialization of CSS values</title>
     7   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     8   <script type="text/javascript" src="property_database.js"></script>
     9   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
    10   <style type="text/css" id="prereqsheet">
    11   #testnode {}
    12   </style>
    13 </head>
    14 <body>
    15 <p id="display"></p>
    16 <div id="content" style="display: none">
    18 <div id="testnode"></div>
    20 </div>
    21 <pre id="test">
    22 <script class="testbody" type="text/javascript">
    24 /** Test for parsing, storage, and serialization of CSS values **/
    26 /*
    27  * The idempotence tests here deserve a little bit of explanation.  What
    28  * we're testing here are the following operations:
    29  *   parse: string -> CSS rule
    30  *   serialize: CSS rule -> string (normalization 1)
    31  *     (this actually has two variants that go through partly different
    32  *     codepaths, which we exercise with getPropertyValue and cssText)
    33  *   compute: CSS rule -> computed style
    34  *   cserialize: computed style -> string (normalization 2)
    35  *
    36  * Both serialize and cserialize do some normalization, so we can't test
    37  * for pure round-tripping, and we also can't compare their output since
    38  * they could normalize differently.  (We might at some point in the
    39  * future want to guarantee that any output of cserialize is
    40  * untouched by going through parse+serialize, though.)
    41  *
    42  * So we test idempotence of parse + serialize by running the whole
    43  * operation twice.  Likewise for parse + compute + cserialize.
    44  *
    45  * Slightly more interestingly, we test that serialize + parse is the
    46  * identity transform by comparing the output of parse + compute +
    47  * cserialize to the output of parse + serialize + parse + compute +
    48  * cserialize.
    49  */
    51 var gSystemFont = {
    52   "caption": true,
    53   "icon": true,
    54   "menu": true,
    55   "message-box": true,
    56   "small-caption": true,
    57   "status-bar": true,
    58   "-moz-window": true,
    59   "-moz-document": true,
    60   "-moz-desktop": true,
    61   "-moz-info": true,
    62   "-moz-dialog": true,
    63   "-moz-button": true,
    64   "-moz-pull-down-menu": true,
    65   "-moz-list": true,
    66   "-moz-field": true,
    67   "-moz-workspace": true,
    68 };
    70 var gBadCompute = {
    71   // output wrapped around to positive, in exponential notation
    72   "-moz-box-ordinal-group": [ "-1", "-1000" ],
    73 };
    75 function xfail_compute(property, value)
    76 {
    77   if (property in gBadCompute &&
    78       gBadCompute[property].indexOf(value) != -1)
    79     return true;
    81   return false;
    82 }
    84 var gBadSerialize = {
    85   // Font-families which include quotes don't get those escaped when
    86   //serializing: see bug 660397
    87   "font-family": ["\\\"Times New Roman", "Times, \\\"Times New Roman"],
    88 };
    90 function xfail_serialize(property, value)
    91 {
    92   if (property in gBadSerialize &&
    93       gBadSerialize[property].indexOf(value) != -1)
    94     return true;
    96   return false;
    97 }
    99 var gElement = document.getElementById("testnode");
   100 var gDeclaration = gElement.style;
   101 var gComputedStyle = window.getComputedStyle(gElement, "");
   103 var gPrereqDeclaration =
   104   document.getElementById("prereqsheet").sheet.cssRules[0].style;
   106 function test_property(property)
   107 {
   108   ok(SpecialPowers.getBoolPref("layout.css.variables.enabled"), "pref not set #2");
   109   var info = gCSSProperties[property];
   111   var test_computed = !("backend_only" in info);
   113   // can all properties be removed from the style?
   114   function test_remove_all_properties(property, value) {
   115     var i, p = [];
   116     for (i = 0; i < gDeclaration.length; i++) p.push(gDeclaration[i]);
   117     for (i = 0; i < p.length; i++) gDeclaration.removeProperty(p[i]);
   118     var errstr = "when setting property " + property + " to " + value;
   119     is(gDeclaration.length, 0, "unremovable properties " + errstr);
   120     is(gDeclaration.cssText, "", "non-empty serialization after removing all properties " + errstr);
   121   }
   123   function test_value(value, resolved_value) {
   124     var value_has_variable_reference = resolved_value != null;
   126     gDeclaration.setProperty(property, value, "");
   128     var idx;
   130     var step1val = gDeclaration.getPropertyValue(property);
   131     var step1vals = [];
   132     var step1ser = gDeclaration.cssText;
   133     if ("subproperties" in info)
   134       for (idx in info.subproperties)
   135         step1vals.push(gDeclaration.getPropertyValue(info.subproperties[idx]));
   136     var step1comp;
   137     var step1comps = [];
   138     if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND)
   139       step1comp = gComputedStyle.getPropertyValue(property);
   140     if (test_computed && "subproperties" in info)
   141       for (idx in info.subproperties)
   142         step1comps.push(gComputedStyle.getPropertyValue(info.subproperties[idx]));
   144     isnot(step1val, "", "setting '" + value + "' on '" + property + "'");
   145     if ("subproperties" in info)
   146       for (idx in info.subproperties) {
   147         var subprop = info.subproperties[idx];
   148         if (value_has_variable_reference &&
   149             (!info.alias_for || info.type == CSS_TYPE_TRUE_SHORTHAND)) {
   150           is(gDeclaration.getPropertyValue(subprop), "",
   151              "setting '" + value + "' on '" + property + "' (for '" + subprop + "')");
   152         } else {
   153           isnot(gDeclaration.getPropertyValue(subprop), "",
   154                 "setting '" + value + "' on '" + property + "' (for '" + subprop + "')");
   155         }
   156       }
   158     // We don't care particularly about the whitespace or the placement of
   159     // semicolons, but for simplicity we'll test the current behavior.
   160     var expected_serialization = "";
   161     if (step1val != "") {
   162       if ("alias_for" in info) {
   163         expected_serialization = info.alias_for + ": " + step1val + ";";
   164       } else {
   165         expected_serialization = property + ": " + step1val + ";";
   166       }
   167     }
   168     is(step1ser, expected_serialization,
   169        "serialization should match property value");
   171     gDeclaration.removeProperty(property);
   172     gDeclaration.setProperty(property, step1val, "");
   174     var serialize_func = xfail_serialize(property, value) &&
   175                          !value_has_variable_reference ? todo_is : is;
   177     serialize_func(gDeclaration.getPropertyValue(property), step1val,
   178        "parse+serialize should be idempotent for '" +
   179          property + ": " + value + "'");
   180     if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND) {
   181       serialize_func(gComputedStyle.getPropertyValue(property), step1comp,
   182          "serialize+parse should be identity transform for '" +
   183          property + ": " + value + "'");
   184     }
   186     if ("subproperties" in info &&
   187         // Using setProperty over subproperties is not sufficient for
   188         // system fonts, since the shorthand does more than its parts.
   189         (property != "font" || !(value in gSystemFont)) &&
   190         // Likewise for special compatibility values of transform
   191         (property != "-moz-transform" || !value.match(/^matrix.*(px|em|%)/)) &&
   192         !value_has_variable_reference) {
   193       gDeclaration.removeProperty(property);
   194       for (idx in info.subproperties) {
   195         var subprop = info.subproperties[idx];
   196         gDeclaration.setProperty(subprop, step1vals[idx], "");
   197       }
   199       // Now that all the subprops are set, check their values.  Note that we
   200       // need this in a separate loop, in case parts of the shorthand affect
   201       // the computed values of other parts.
   202       for (idx in info.subproperties) {
   203         var subprop = info.subproperties[idx];
   204         if (test_computed && !("backend_only" in gCSSProperties[subprop])) {
   205           is(gComputedStyle.getPropertyValue(subprop), step1comps[idx],
   206              "serialize(" + subprop + ")+parse should be the identity " +
   207              "transform for '" + property + ": " + value + "'");
   208         }
   209       }
   210       is(gDeclaration.getPropertyValue(property), step1val,
   211          "parse+split+serialize should be idempotent for '" +
   212          property + ": " + value + "'");
   213     }
   215     if (test_computed && info.type != CSS_TYPE_TRUE_SHORTHAND) {
   216       gDeclaration.removeProperty(property);
   217       gDeclaration.setProperty(property, step1comp, "");
   218       var func = (xfail_compute(property, value) ||
   219         xfail_serialize(property, resolved_value || value)) ? todo_is : is;
   220       func(gComputedStyle.getPropertyValue(property), step1comp,
   221            "parse+compute+serialize should be idempotent for '" +
   222            property + ": " + value + "'");
   223     }
   224     if (test_computed && "subproperties" in info) {
   225       gDeclaration.removeProperty(property);
   226       for (idx in info.subproperties) {
   227         var subprop = info.subproperties[idx];
   228         if ("backend_only" in gCSSProperties[subprop])
   229           continue;
   230         gDeclaration.setProperty(subprop, step1comps[idx], "");
   231       }
   233       // Now that all the subprops are set, check their values.  Note that we
   234       // need this in a separate loop, in case parts of the shorthand affect
   235       // the computed values of other parts.
   236       for (idx in info.subproperties) {
   237         var subprop = info.subproperties[idx];
   238         if ("backend_only" in gCSSProperties[subprop])
   239           continue;
   240         is(gComputedStyle.getPropertyValue(subprop), step1comps[idx],
   241            "parse+compute+serialize(" + subprop + ") should be idempotent for '" +
   242            property + ": " + value + "'");
   243       }
   244     }
   246     // sanity check shorthands to make sure disabled props aren't exposed
   247     if (info.type != CSS_TYPE_LONGHAND) {
   248       gDeclaration.setProperty(property, value, "");
   249       test_remove_all_properties(property, value);
   250     }
   252     gDeclaration.removeProperty(property);
   253   }
   255   function test_value_without_variable(value) {
   256     test_value(value, null);
   257   }
   259   function test_value_with_variable(value) {
   260     gPrereqDeclaration.setProperty("--a", value, "");
   261     test_value("var(--a)", value);
   262     gPrereqDeclaration.removeProperty("--a");
   263   }
   265   if ("prerequisites" in info) {
   266     var prereqs = info.prerequisites;
   267     for (var prereq in prereqs) {
   268       gPrereqDeclaration.setProperty(prereq, prereqs[prereq], "");
   269     }
   270   }
   272   var idx;
   273   for (idx in info.initial_values) {
   274     test_value_without_variable(info.initial_values[idx]);
   275     test_value_with_variable(info.initial_values[idx]);
   276   }
   277   for (idx in info.other_values) {
   278     test_value_without_variable(info.other_values[idx]);
   279     test_value_with_variable(info.other_values[idx]);
   280   }
   282   if ("prerequisites" in info) {
   283     for (var prereq in info.prerequisites) {
   284       gPrereqDeclaration.removeProperty(prereq);
   285     }
   286   }
   288 }
   290 function runTest() {
   291   // To avoid triggering the slow script dialog, we have to test one
   292   // property at a time.
   293   ok(SpecialPowers.getBoolPref("layout.css.variables.enabled"), "pref not set #1");
   294   var props = [];
   295   for (var prop in gCSSProperties)
   296     props.push(prop);
   297   props = props.reverse();
   298   function do_one() {
   299     if (props.length == 0) {
   300       SimpleTest.finish();
   301       return;
   302     }
   303     test_property(props.pop());
   304     SimpleTest.executeSoon(do_one);
   305   }
   306   SimpleTest.executeSoon(do_one);
   307 }
   309 SimpleTest.waitForExplicitFinish();
   310 SimpleTest.requestLongerTimeout(2);
   312 SpecialPowers.pushPrefEnv({ set: [["layout.css.variables.enabled", true]] },
   313                           runTest);
   314 </script>
   315 </pre>
   316 </body>
   317 </html>

mercurial