tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_SVGTransformList.xhtml (14223B)


      1 <html xmlns="http://www.w3.org/1999/xhtml">
      2 <!--
      3 https://bugzilla.mozilla.org/show_bug.cgi?id=602759
      4 -->
      5 <head>
      6  <title>Tests specific to SVGTransformList</title>
      7  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      8  <script type="text/javascript" src="matrixUtils.js"></script>
      9  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     10 </head>
     11 <body>
     12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602759">
     13  Mozilla Bug 602759</a>
     14 <p id="display"></p>
     15 <div id="content" style="display:none;">
     16 <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100" height="100"
     17     onload="this.pauseAnimations();">
     18  <g id="g"/>
     19 </svg>
     20 </div>
     21 <pre id="test">
     22 <script class="testbody" type="text/javascript">
     23 <![CDATA[
     24 
     25 SimpleTest.waitForExplicitFinish();
     26 
     27 /*
     28 This file runs a series of SVGTransformList specific tests. Generic SVGXxxList
     29 tests can be found in test_SVGxxxList.xhtml. Anything that can be generalized
     30 to other list types belongs there.
     31 */
     32 
     33 function main() {
     34  var g = $("g");
     35  var tests =
     36    [ testConsolidateMatrix,
     37      testConsolidateMatrixOneElem,
     38      testConsolidateMatrixZeroElem,
     39      testCreateSVGTransformFromMatrix,
     40      testReadOnly,
     41      testOrphan,
     42      testFailedSet,
     43      testMutationEvents,
     44    ];
     45  for (var i = 0; i < tests.length; i++) {
     46    tests[i](g);
     47  }
     48  SimpleTest.finish();
     49 }
     50 
     51 function testConsolidateMatrix(g) {
     52  // This is the example from SVG 1.1 section 7.5
     53  g.setAttribute("transform",
     54                 "translate(50 90) rotate(-45) translate(130 160)");
     55  var list = g.transform.baseVal;
     56  is(list.numberOfItems, 3, "Unexpected length of unconsolidated list");
     57 
     58  // Sanity check -- take ref to first item in list and validate it
     59  var first_item = list.getItem(0);
     60  is(first_item.type, SVGTransform.SVG_TRANSFORM_TRANSLATE,
     61     "Unexpected type of first item in list");
     62  cmpMatrix(first_item.matrix, [1, 0, 0, 1, 50, 90],
     63     "Unexpected value for first item in list");
     64 
     65  // Consolidate
     66  var consolidated = list.consolidate();
     67  is(list.numberOfItems, 1, "Unexpected length of consolidated list");
     68  ok(consolidated === list.getItem(0),
     69     "Consolidate return value should be first item in list, not a copy");
     70  is(consolidated.type, SVGTransform.SVG_TRANSFORM_MATRIX,
     71     "Consolidated transform not of type matrix");
     72  const angle = -Math.PI / 4;
     73  roughCmpMatrix(consolidated.matrix,
     74    [Math.cos(angle), Math.sin(angle),
     75     -Math.sin(angle), Math.cos(angle),
     76     130 * Math.cos(angle) - 160 * Math.sin(angle) + 50,
     77     160 * Math.cos(angle) + 130 * Math.sin(angle) + 90],
     78    "Unexpected result after consolidating matrices");
     79 
     80  // Check ref to first item in list
     81  // a) should not have changed
     82  is(first_item.type, SVGTransform.SVG_TRANSFORM_TRANSLATE,
     83     "Unexpected type of cached first item in list after consolidating");
     84  cmpMatrix(first_item.matrix, [1, 0, 0, 1, 50, 90],
     85     "Unexpected value for cached first item in list after consolidating");
     86  // b) should still be usable
     87  first_item.setScale(2, 3);
     88  is(first_item.type, SVGTransform.SVG_TRANSFORM_SCALE,
     89     "Cached first item in list not usable after consolidating");
     90 
     91  // Check consolidated is live
     92  // a) Changes to 'consolidated' affect list
     93  consolidated.setSkewX(45);
     94  is(list.getItem(0).type, SVGTransform.SVG_TRANSFORM_SKEWX,
     95     "Changing return value from consolidate doesn't affect list");
     96  // b) Changes to list affect 'consolidated'
     97  list.getItem(0).setRotate(90, 0, 0);
     98  is(consolidated.type, SVGTransform.SVG_TRANSFORM_ROTATE,
     99     "Changing list doesn't affect return value from consolidate");
    100 }
    101 
    102 function testConsolidateMatrixOneElem(g) {
    103  // Check that even if we only have one item in the list it becomes a matrix
    104  // transform (as per the spec)
    105  g.setAttribute("transform", "translate(50 90)");
    106  var list = g.transform.baseVal;
    107  is(list.numberOfItems, 1, "Unexpected length of unconsolidated list");
    108  var first_item = list.getItem(0);
    109  is(first_item.type, SVGTransform.SVG_TRANSFORM_TRANSLATE,
    110     "Unexpected type of first item in list");
    111  cmpMatrix(first_item.matrix, [1, 0, 0, 1, 50, 90],
    112     "Unexpected value for first item in list");
    113 
    114  // Consolidate
    115  var consolidated = list.consolidate();
    116  is(list.numberOfItems, 1, "Unexpected length of consolidated list");
    117  ok(consolidated === list.getItem(0),
    118     "Consolidate return value should be first item in list, not a copy");
    119  is(consolidated.type, SVGTransform.SVG_TRANSFORM_MATRIX,
    120     "Consolidated transform not of type matrix");
    121  cmpMatrix(consolidated.matrix, [1, 0, 0, 1, 50, 90],
    122     "Unexpected consolidated matrix value");
    123 }
    124 
    125 function testConsolidateMatrixZeroElem(g) {
    126  // Check that zero items returns null
    127  g.setAttribute("transform", "");
    128  var list = g.transform.baseVal;
    129  is(list.numberOfItems, 0, "Unexpected length of unconsolidated list");
    130  var consolidated = list.consolidate();
    131  ok(consolidated === null,
    132     "consolidate() should return null for a zero-length transform list");
    133 }
    134 
    135 function testCreateSVGTransformFromMatrix(g) {
    136  var m = createMatrix(1, 2, 3, 4, 5, 6);
    137 
    138  // "Creates an SVGTransform object which is initialized to transform of type
    139  // SVG_TRANSFORM_MATRIX and whose values are the given matrix. The values from
    140  // the parameter matrix are copied, the matrix parameter is not adopted as
    141  // SVGTransform::matrix."
    142  var list = g.transform.baseVal;
    143  list.clear();
    144  var t = list.createSVGTransformFromMatrix(m);
    145 
    146  // Check that list hasn't changed
    147  is(list.numberOfItems, 0,
    148     "Transform list changed after calling createSVGTransformFromMatrix");
    149 
    150  // Check return value
    151  is(t.type, SVGTransform.SVG_TRANSFORM_MATRIX,
    152     "Returned transform not of type matrix");
    153  cmpMatrix(t.matrix, [1, 2, 3, 4, 5, 6],
    154     "Unexpected returned matrix value");
    155 
    156  // Check values are copied
    157  ok(t.matrix != m, "Matrix should be copied not adopted");
    158  m.a = 2;
    159  is(t.matrix.a, 1,
    160     "Changing source matrix should not affect newly created transform");
    161 
    162  // null should give us an identity matrix
    163  t = list.createSVGTransformFromMatrix(null);
    164  cmpMatrix(t.matrix, [1, 0, 0, 1, 0, 0],
    165     "Unexpected returned matrix value");
    166 
    167  // Try passing in bad values ("undefined" etc.)
    168  let exception = null;
    169  try {
    170    t = list.createSVGTransformFromMatrix("undefined");
    171  } catch (e) { exception = e; }
    172  ok(exception,
    173    "Failed to throw for string input to createSVGTransformFromMatrix");
    174  exception = null;
    175  try {
    176    t = list.createSVGTransformFromMatrix(SVGMatrix(t));
    177  } catch (e) { exception = e; }
    178  ok(exception,
    179    "Failed to throw for bad input to createSVGTransformFromMatrix");
    180  exception = null;
    181 }
    182 
    183 function testReadOnly(g) {
    184  var SVG_NS = "http://www.w3.org/2000/svg";
    185 
    186  // Just some data to work with
    187  g.setAttribute("transform", "translate(50 90)");
    188 
    189  // baseVal / animVal are readonly attributes
    190  //   Create another (empty) transform list
    191  var otherg = document.createElementNS(SVG_NS, "g");
    192  g.parentNode.appendChild(otherg);
    193  is(g.transform.baseVal.numberOfItems, 1,
    194    "Unexpected number of items in transform list before attempting to set");
    195  is(otherg.transform.baseVal.numberOfItems, 0,
    196    "Unexpected number of items in source transform list before attempting to"
    197    + " set");
    198  //   Attempt to set the base value and check nothing changes
    199  g.transform.baseVal = otherg.transform.baseVal;
    200  is(g.transform.baseVal.numberOfItems, 1,
    201    "baseVal should be read-only but its value has changed");
    202  is(otherg.transform.baseVal.numberOfItems, 0,
    203    "baseVal changed after attempting to use it set another value");
    204 
    205  // Read-only SVGTransformList:
    206  // Standard list methods are covered in test_SVGxxxList.xhtml so here we
    207  // just add tests for SVGTransformList-specific methods
    208  var roList = g.transform.animVal;
    209  // consolidate()
    210  var threw = false;
    211  try {
    212    roList.consolidate();
    213  } catch (e) {
    214    is(e.name, "NoModificationAllowedError",
    215      "Got unexpected exception " + e +
    216      ", expected NoModificationAllowedError");
    217    is(e.code, DOMException.NO_MODIFICATION_ALLOWED_ERR,
    218      "Got unexpected exception " + e +
    219      ", expected NO_MODIFICATION_ALLOWED_ERR");
    220    threw = true;
    221  }
    222  ok(threw,
    223     "Failed to throw exception when calling consolidate on read-only list");
    224 
    225  // Read-only SVGTransform:
    226  // read-only attributes are tested in test_transform.xhtml. Here we are
    227  // concerned with methods that throw because this *object* is read-only
    228  // (since it belongs to a read-only transform list)
    229  var roTransform = roList.getItem(0);
    230  // setMatrix
    231  threw = false;
    232  try {
    233    var m = createMatrix(1, 2, 3, 4, 5, 6);
    234    roTransform.setMatrix(m);
    235  } catch (e) {
    236    is(e.name, "NoModificationAllowedError",
    237      "Got unexpected exception " + e +
    238      ", expected NoModificationAllowedError");
    239    is(e.code, DOMException.NO_MODIFICATION_ALLOWED_ERR,
    240      "Got unexpected exception " + e +
    241      ", expected NO_MODIFICATION_ALLOWED_ERR");
    242    threw = true;
    243  }
    244  ok(threw, "Failed to throw exception when calling setMatrix on read-only"
    245            + " transform");
    246  // setTranslate
    247  threw = false;
    248  try {
    249    roTransform.setTranslate(2, 3);
    250  } catch (e) {
    251    threw = true;
    252  }
    253  ok(threw, "Failed to throw when calling setTranslate on read-only"
    254             + " transform");
    255  // setScale
    256  threw = false;
    257  try {
    258    roTransform.setScale(2, 3);
    259  } catch (e) {
    260    threw = true;
    261  }
    262  ok(threw, "Failed to throw when calling setScale on read-only transform");
    263  // setRotate
    264  threw = false;
    265  try {
    266    roTransform.setRotate(1, 2, 3);
    267  } catch (e) {
    268    threw = true;
    269  }
    270  ok(threw, "Failed to throw when calling setRotate on read-only transform");
    271  // setSkewX
    272  threw = false;
    273  try {
    274    roTransform.setSkewX(2);
    275  } catch (e) {
    276    threw = true;
    277  }
    278  ok(threw, "Failed to throw when calling setSkewX on read-only transform");
    279  // setSkewY
    280  threw = false;
    281  try {
    282    roTransform.setSkewY(2);
    283  } catch (e) {
    284    threw = true;
    285  }
    286  ok(threw, "Failed to throw when calling setSkewY on read-only transform");
    287 
    288  // Read-only SVGMatrix
    289  var roMatrix = roTransform.matrix;
    290  threw = false;
    291  try {
    292    roMatrix.a = 1;
    293  } catch (e) {
    294    is(e.name, "NoModificationAllowedError",
    295      "Got unexpected exception " + e +
    296      ", expected NoModificationAllowedError");
    297    is(e.code, DOMException.NO_MODIFICATION_ALLOWED_ERR,
    298      "Got unexpected exception " + e +
    299      ", expected NO_MODIFICATION_ALLOWED_ERR");
    300    threw = true;
    301  }
    302  ok(threw, "Failed to throw exception when modifying read-only matrix");
    303 }
    304 
    305 function testOrphan(g) {
    306  // Although this isn't defined, if a read-only object becomes orphaned
    307  // (detached from it's parent), then presumably it should become editable
    308  // again.
    309 
    310  // As with the read-only test set a value to test with
    311  g.setAttribute("transform", "translate(50 90)");
    312 
    313  var roList = g.transform.animVal;
    314  var roTransform = roList.getItem(0);
    315  var roMatrix = roTransform.matrix;
    316 
    317  // Orphan transform list contents by re-setting transform attribute
    318  g.setAttribute("transform", "");
    319 
    320  // Transform should now be editable
    321  var exception = null;
    322  try {
    323    roTransform.setTranslate(5, 3);
    324  } catch (e) {
    325    exception = e;
    326  }
    327  ok(exception === null,
    328     "Unexpected exception " + exception + " modifying orphaned transform");
    329 
    330  // So should matrix
    331  exception = null;
    332  try {
    333    roMatrix.a = 1;
    334  } catch (e) {
    335    exception = e;
    336  }
    337  ok(exception === null,
    338     "Unexpected exception " + exception + " modifying orphaned matrix");
    339 }
    340 
    341 function testFailedSet(g) {
    342  // Check that a parse failure results in the attribute being empty
    343 
    344  // Set initial value
    345  g.setAttribute("transform", "translate(50 90)");
    346  var list = g.transform.baseVal;
    347  is(list.numberOfItems, 1, "Unexpected initial length of list");
    348 
    349  // Attempt to set bad value
    350  g.setAttribute("transform", "translate(40 50) scale(a)");
    351  is(list.numberOfItems, 0,
    352     "Transform list should be empty after setting bad value");
    353  is(g.transform.animVal.numberOfItems, 0,
    354     "Animated transform list should also be empty after setting bad value");
    355 }
    356 
    357 function testMutationEvents(g) {
    358  // Check mutation events
    359 
    360  // Set initial value
    361  g.setAttribute("transform", "translate(50 90)");
    362  var list = g.transform.baseVal;
    363  is(list.numberOfItems, 1, "Unexpected initial length of list");
    364 
    365  // consolidate
    366  //
    367  // Consolidate happens to generate two modification events in our
    368  // implementation--it's not ideal but it's better than none
    369  g.setAttribute("transform", "translate(10 10) translate(10 10)");
    370  list.consolidate();
    371 
    372  // In the following, each of the operations is performed twice but only one
    373  // mutation event is expected. This is to check that redundant mutation
    374  // events are not sent.
    375 
    376  // transform.setMatrix
    377  var mx = $("svg").createSVGMatrix();
    378  list[0].setMatrix(mx);
    379  list[0].setMatrix(mx);
    380  [
    381    {a: 1, m11: 2},
    382    {a: Infinity},
    383    {b: 0, m12: -1},
    384    {c: Infinity, m21: -Infinity},
    385    {d: 0, m22: NaN},
    386    {e: 1, m41: 1.00000001},
    387    {f: 0, m42: Number.MIN_VALUE},
    388  ].forEach(dict => {
    389    let exception = null;
    390    try {
    391      list[0].setMatrix(dict);
    392    } catch (e) {
    393      exception = e;
    394    }
    395    ok(exception,
    396      "Failed to throw for invalid input to setMatrix");
    397  });
    398 
    399  // transform.setTranslate
    400  list[0].setTranslate(10, 10);
    401  list[0].setTranslate(10, 10);
    402 
    403  // transform.setScale
    404  list[0].setScale(2, 2);
    405  list[0].setScale(2, 2);
    406 
    407  // transform.setRotate
    408  list[0].setRotate(45, 1, 2);
    409  list[0].setRotate(45, 1, 2);
    410 
    411  // transform.setSkewX
    412  list[0].setSkewX(45);
    413  list[0].setSkewX(45);
    414 
    415  // transform.setSkewY
    416  list[0].setSkewY(25);
    417  list[0].setSkewY(25);
    418 
    419  // transform.matrix
    420  list[0].matrix.a = 1;
    421  list[0].matrix.a = 1;
    422  list[0].matrix.e = 5;
    423  list[0].matrix.e = 5;
    424 
    425  // setAttribute interaction
    426  list[0].setMatrix(mx);
    427  g.setAttribute("transform", "matrix(1, 0, 0, 1, 0, 0)");
    428  list[0].setMatrix(mx);
    429 
    430  // Attribute removal
    431  g.removeAttribute("transform");
    432 
    433  // Non-existent attribute removal
    434  g.removeAttribute("transform");
    435  g.removeAttributeNS(null, "transform");
    436 }
    437 
    438 window.addEventListener("load",
    439  () => SimpleTest.executeSoon(main)
    440 );
    441 
    442 ]]>
    443 </script>
    444 </pre>
    445 </body>
    446 </html>