OLD | NEW |
(Empty) | |
| 1 <!doctype html> |
| 2 <title>Selection extend() tests</title> |
| 3 <meta charset=utf-8> |
| 4 <meta name=timeout content=long> |
| 5 <body> |
| 6 <script src=/resources/testharness.js></script> |
| 7 <script src=/resources/testharnessreport.js></script> |
| 8 <script src=common.js></script> |
| 9 <div id=log></div> |
| 10 <script> |
| 11 "use strict"; |
| 12 |
| 13 // Also test a selection with no ranges |
| 14 testRanges.unshift("[]"); |
| 15 |
| 16 /** |
| 17 * We test Selections that go both forwards and backwards here. In the latter |
| 18 * case we need to use extend() to force it to go backwards, which is fair |
| 19 * enough, since that's what we're testing. We test collapsed selections only |
| 20 * once. |
| 21 */ |
| 22 for (var i = 0; i < testRanges.length; i++) { |
| 23 var endpoints = eval(testRanges[i]); |
| 24 for (var j = 0; j < testPoints.length; j++) { |
| 25 if (endpoints[0] == endpoints[2] |
| 26 && endpoints[1] == endpoints[3]) { |
| 27 // Test collapsed selections only once |
| 28 test(function() { |
| 29 setSelectionForwards(endpoints); |
| 30 testExtend(endpoints, eval(testPoints[j])); |
| 31 }, "extend() with range " + i + " " + testRanges[i] |
| 32 + " and point " + j + " " + testPoints[j]); |
| 33 } else { |
| 34 test(function() { |
| 35 setSelectionForwards(endpoints); |
| 36 testExtend(endpoints, eval(testPoints[j])); |
| 37 }, "extend() forwards with range " + i + " " + testRanges[i] |
| 38 + " and point " + j + " " + testPoints[j]); |
| 39 |
| 40 test(function() { |
| 41 setSelectionBackwards(endpoints); |
| 42 testExtend(endpoints, eval(testPoints[j])); |
| 43 }, "extend() backwards with range " + i + " " + testRanges[i] |
| 44 + " and point " + j + " " + testPoints[j]); |
| 45 } |
| 46 } |
| 47 } |
| 48 |
| 49 function testExtend(endpoints, target) { |
| 50 assert_equals(getSelection().rangeCount, endpoints.length/4, |
| 51 "Sanity check: rangeCount must be correct"); |
| 52 |
| 53 var node = target[0]; |
| 54 var offset = target[1]; |
| 55 |
| 56 // "If the context object's range is null, throw an InvalidStateError |
| 57 // exception and abort these steps." |
| 58 if (getSelection().rangeCount == 0) { |
| 59 assert_throws("INVALID_STATE_ERR", function() { |
| 60 selection.extend(node, offset); |
| 61 }, "extend() when rangeCount is 0 must throw InvalidStateError"); |
| 62 return; |
| 63 } |
| 64 |
| 65 assert_equals(getSelection().getRangeAt(0).startContainer, endpoints[0], |
| 66 "Sanity check: startContainer must be correct"); |
| 67 assert_equals(getSelection().getRangeAt(0).startOffset, endpoints[1], |
| 68 "Sanity check: startOffset must be correct"); |
| 69 assert_equals(getSelection().getRangeAt(0).endContainer, endpoints[2], |
| 70 "Sanity check: endContainer must be correct"); |
| 71 assert_equals(getSelection().getRangeAt(0).endOffset, endpoints[3], |
| 72 "Sanity check: endOffset must be correct"); |
| 73 |
| 74 // "Let anchor and focus be the context object's anchor and focus, and let |
| 75 // new focus be the boundary point (node, offset)." |
| 76 var anchorNode = getSelection().anchorNode; |
| 77 var anchorOffset = getSelection().anchorOffset; |
| 78 var focusNode = getSelection().focusNode; |
| 79 var focusOffset = getSelection().focusOffset; |
| 80 |
| 81 // "Let new range be a new range." |
| 82 // |
| 83 // We'll always be setting either new range's start or its end to new |
| 84 // focus, so we'll always throw at some point. Test that now. |
| 85 // |
| 86 // From DOM4's "set the start or end of a range": "If node is a doctype, |
| 87 // throw an "InvalidNodeTypeError" exception and terminate these steps." |
| 88 if (node.nodeType == Node.DOCUMENT_TYPE_NODE) { |
| 89 assert_throws("INVALID_NODE_TYPE_ERR", function() { |
| 90 selection.extend(node, offset); |
| 91 }, "extend() to a doctype must throw InvalidNodeTypeError"); |
| 92 return; |
| 93 } |
| 94 |
| 95 // From DOM4's "set the start or end of a range": "If offset is greater |
| 96 // than node's length, throw an "IndexSizeError" exception and terminate |
| 97 // these steps." |
| 98 // |
| 99 // FIXME: We should be casting offset to an unsigned int per WebIDL. Until |
| 100 // we do, we need the offset < 0 check too. |
| 101 if (offset < 0 || offset > getNodeLength(node)) { |
| 102 assert_throws("INDEX_SIZE_ERR", function() { |
| 103 selection.extend(node, offset); |
| 104 }, "extend() to an offset that's greater than node length (" + getNodeLe
ngth(node) + ") must throw IndexSizeError"); |
| 105 return; |
| 106 } |
| 107 |
| 108 // Now back to the editing spec. |
| 109 var originalRange = getSelection().getRangeAt(0); |
| 110 |
| 111 // "If node's root is not the same as the context object's range's root, |
| 112 // set new range's start and end to (node, offset)." |
| 113 // |
| 114 // "Otherwise, if anchor is before or equal to new focus, set new range's |
| 115 // start to anchor, then set its end to new focus." |
| 116 // |
| 117 // "Otherwise, set new range's start to new focus, then set its end to |
| 118 // anchor." |
| 119 // |
| 120 // "Set the context object's range to new range." |
| 121 // |
| 122 // "If new focus is before anchor, set the context object's direction to |
| 123 // backwards. Otherwise, set it to forwards." |
| 124 // |
| 125 // The upshot of all these is summed up by just testing the anchor and |
| 126 // offset. |
| 127 getSelection().extend(node, offset); |
| 128 |
| 129 if (furthestAncestor(anchorNode) == furthestAncestor(node)) { |
| 130 assert_equals(getSelection().anchorNode, anchorNode, |
| 131 "anchorNode must not change if the node passed to extend() has the s
ame root as the original range"); |
| 132 assert_equals(getSelection().anchorOffset, anchorOffset, |
| 133 "anchorOffset must not change if the node passed to extend() has the
same root as the original range"); |
| 134 } else { |
| 135 assert_equals(getSelection().anchorNode, node, |
| 136 "anchorNode must be the node passed to extend() if it has a differen
t root from the original range"); |
| 137 assert_equals(getSelection().anchorOffset, offset, |
| 138 "anchorOffset must be the offset passed to extend() if the node has
a different root from the original range"); |
| 139 } |
| 140 assert_equals(getSelection().focusNode, node, |
| 141 "focusNode must be the node passed to extend()"); |
| 142 assert_equals(getSelection().focusOffset, offset, |
| 143 "focusOffset must be the offset passed to extend()"); |
| 144 assert_not_equals(getSelection().getRangeAt(0), originalRange, |
| 145 "extend() must replace any existing range with a new one, not mutate the
existing one"); |
| 146 } |
| 147 |
| 148 testDiv.style.display = "none"; |
| 149 </script> |
OLD | NEW |