<!doctype html>
<title>SVG*List array method tests</title>
<script src=../../resources/testharness.js></script>
<script src=../../resources/testharnessreport.js></script>
<div id="testcontainer"></div>
<div id=log></div>
<script>
function createSvg() {
  document.getElementById("testcontainer").innerHTML = '<svg id="svg" width="1" height="1" visibility="hidden"><polygon id="polygon" points="10 10 450 212 24 103 45 32 62 42 123 52 62 52 57 72 12 548 85 12" visibility="hidden" systemLanguage="sv, en, fr, de, zn, jp"/><path id="path" d="M 10 10 L 450 212 24 103 45 32 62 42 123 52 62 52 57 72 12 548 85 12" transform="scale(0.5) rotate(34) translate(10 10)" visibility="hidden"/><text id="text" dx="10 10 450 212 24 103 45 32 62 42 123 52 62 52 57 72 12 548 85 12" rotate="10 66 2 23 546 54657 567 546 3 2 2 2 23" visibility="hidden"/></svg>';
}
setup(createSvg);
var svg = document.getElementById("svg");
var polygon = document.getElementById("polygon");
var path = document.getElementById("path");
var text = document.getElementById("text");
function createSVGPoint(x,y) {
    var o;
    try {
        o = new SVGPoint(x,y);
    }
    catch(e) {
        o = svg.createSVGPoint();
        o.x = x;
        o.y = y;
    }
    return o;
}
function createSVGLength(value) {
    var o;
    try {
        o = new SVGLength(value);
    }
    catch(e) {
        o = svg.createSVGLength();
        o.value = value;
    }
    return o;
}
function createSVGNumber(value) {
    var o;
    try {
        o = new SVGNumber(value);
    }
    catch(e) {
        o = svg.createSVGNumber();
        o.value = value;
    }
    return o;
}
function createSVGTransformTranslate(tx,ty) {
    var o;
    try {
        o = new SVGTransform();
    }
    catch(e) {
        o = svg.createSVGTransform();
    }
    o.setTranslate(tx, ty);
    return o;
}
var lists = {
    "SVGPointList":
        { "impl": polygon.points,
          "type": "SVGPoint",
          "length": 10,
          "insert_value": createSVGPoint(5, 5),
          "equals": function(a,b) { return a.x == b.x && a.y == b.y; }
        },
    "SVGStringList":
        { "impl": polygon.systemLanguage,
          "type": "DOMString",
          "length": 6,
          "insert_value": "uk",
          "equals": function(a,b) { return a == b; }
        },
    "SVGTransformList":
        { "impl": path.transform.baseVal,
          "type": "SVGTransform",
          "length": 3,
          "insert_value": createSVGTransformTranslate(5,5),
          "equals": function(a,b) { return a.matrix.a == b.matrix.a &&
                                           a.matrix.b == b.matrix.b &&
                                           a.matrix.c == b.matrix.c &&
                                           a.matrix.d == b.matrix.d &&
                                           a.matrix.e == b.matrix.e &&
                                           a.matrix.f == b.matrix.f; }
        },
    "SVGLengthList":
        { "impl": text.dx.baseVal,
          "type": "SVGLength",
          "length": 20,
          "insert_value": createSVGLength(5),
          "equals": function(a,b) { return a.valueInSpecifiedUnits == b.valueInSpecifiedUnits &&
                                           a.unitType == b.unitType; }
        },
    "SVGNumberList":
        { "impl": text.rotate.baseVal,
          "type": "SVGNumber",
          "length": 13,
          "insert_value": createSVGNumber(5),
          "equals": function(a,b) { return a.value == b.value; }
        }
};

for (list_type in lists) {
    test(function() {
        assert_idl_attribute(lists[list_type].impl, "length");
    }, list_type + " has length attribute");
    test(function() {
        assert_idl_attribute(lists[list_type].impl, "numberOfItems");
    }, list_type + " has numberOfItems attribute");
    test(function() {
      assert_equals(lists[list_type].impl.length, lists[list_type].impl.numberOfItems);
      assert_equals(lists[list_type].impl.length, lists[list_type].length);
    }, list_type + ".length equals " + list_type + ".numberOfItems.");
    test(function() {
        assert_true(lists[list_type].equals(lists[list_type].impl.getItem(0), lists[list_type].impl[0]));
    }, list_type + " has array getter");
    test(function() {
        var old_value = lists[list_type].impl[0];
        var new_value = lists[list_type].insert_value;
        lists[list_type].impl[0] = lists[list_type].insert_value;
        assert_false(lists[list_type].equals(old_value, new_value));
        assert_true(lists[list_type].equals(lists[list_type].impl[0], new_value));
        assert_equals(lists[list_type].impl.length, lists[list_type].length);
    }, list_type + " has array setter");
}

</script>
