--- a/selecttest/Selection-addRange.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-<!doctype html>
-<title>Selection.addRange() tests</title>
-<div id=log></div>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script src=common.js></script>
-<script>
-"use strict";
-
-function testAddRange(exception, range, endpoints, qualifier, testName) {
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
-
- selection.addRange(range);
-
- assert_equals(range.startContainer, endpoints[0],
- "addRange() must not modify the startContainer of the Range it's given");
- assert_equals(range.startOffset, endpoints[1],
- "addRange() must not modify the startOffset of the Range it's given");
- assert_equals(range.endContainer, endpoints[2],
- "addRange() must not modify the endContainer of the Range it's given");
- assert_equals(range.endOffset, endpoints[3],
- "addRange() must not modify the endOffset of the Range it's given");
- }, testName + ": " + qualifier + " addRange() must not throw exceptions or modify the range it's given");
-
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
-
- assert_equals(selection.rangeCount, 1, "rangeCount must be 1");
- }, testName + ": " + qualifier + " addRange() must result in rangeCount being 1");
-
- // From here on out we check selection.getRangeAt(selection.rangeCount - 1)
- // so as not to double-fail Gecko.
-
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
- assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
-
- var newRange = selection.getRangeAt(selection.rangeCount - 1);
-
- assert_not_equals(newRange, null,
- "getRangeAt(rangeCount - 1) must not return null");
- assert_equals(typeof newRange, "object",
- "getRangeAt(rangeCount - 1) must return an object");
-
- assert_equals(newRange.startContainer, range.startContainer,
- "startContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.startOffset, range.startOffset,
- "startOffset of the Selection's last Range must match the added Range");
- assert_equals(newRange.endContainer, range.endContainer,
- "endContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.endOffset, range.endOffset,
- "endOffset of the Selection's last Range must match the added Range");
- }, testName + ": " + qualifier + " addRange() must result in the selection's last range having the specified endpoints");
-
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
- assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
-
- assert_equals(selection.getRangeAt(selection.rangeCount - 1), range,
- "getRangeAt(rangeCount - 1) must return the same object we added");
- }, testName + ": " + qualifier + " addRange() must result in the selection's last range being the same object we added");
-
- // Let's not test many different modifications -- one should be enough.
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
- assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
-
- if (range.startContainer == paras[0].firstChild
- && range.startOffset == 0
- && range.endContainer == paras[0].firstChild
- && range.endOffset == 2) {
- // Just in case . . .
- range.setStart(paras[0].firstChild, 1);
- } else {
- range.setStart(paras[0].firstChild, 0);
- range.setEnd(paras[0].firstChild, 2);
- }
-
- var newRange = selection.getRangeAt(selection.rangeCount - 1);
-
- assert_equals(newRange.startContainer, range.startContainer,
- "After mutating the " + qualifier + " added Range, startContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.startOffset, range.startOffset,
- "After mutating the " + qualifier + " added Range, startOffset of the Selection's last Range must match the added Range");
- assert_equals(newRange.endContainer, range.endContainer,
- "After mutating the " + qualifier + " added Range, endContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.endOffset, range.endOffset,
- "After mutating the " + qualifier + " added Range, endOffset of the Selection's last Range must match the added Range");
- }, testName + ": modifying the " + qualifier + " added range must modify the Selection's last Range");
-
- // Now test the other way too.
- test(function() {
- assert_equals(exception, null, "Test setup must not throw exceptions");
- assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
-
- var newRange = selection.getRangeAt(selection.rangeCount - 1);
-
- if (newRange.startContainer == paras[0].firstChild
- && newRange.startOffset == 4
- && newRange.endContainer == paras[0].firstChild
- && newRange.endOffset == 6) {
- newRange.setStart(paras[0].firstChild, 5);
- } else {
- newRange.setStart(paras[0].firstChild, 4);
- newRange.setStart(paras[0].firstChild, 6);
- }
-
- assert_equals(newRange.startContainer, range.startContainer,
- "After " + qualifier + " addRange(), after mutating the Selection's last Range, startContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.startOffset, range.startOffset,
- "After " + qualifier + " addRange(), after mutating the Selection's last Range, startOffset of the Selection's last Range must match the added Range");
- assert_equals(newRange.endContainer, range.endContainer,
- "After " + qualifier + " addRange(), after mutating the Selection's last Range, endContainer of the Selection's last Range must match the added Range");
- assert_equals(newRange.endOffset, range.endOffset,
- "After " + qualifier + " addRange(), after mutating the Selection's last Range, endOffset of the Selection's last Range must match the added Range");
- }, testName + ": modifying the Selection's last Range must modify the " + qualifier + " added Range");
-}
-
-// Do only n evals, not n^2
-var testRangesEvaled = testRanges.map(eval);
-
-for (var i = 0; i < testRanges.length; i++) {
- for (var j = 0; j < testRanges.length; j++) {
- var testName = "Range " + i + " " + testRanges[i]
- + " followed by Range " + j + " " + testRanges[j];
-
- var exception = null;
- try {
- selection.removeAllRanges();
-
- var endpoints1 = testRangesEvaled[i];
- var range1 = ownerDocument(endpoints1[0]).createRange();
- range1.setStart(endpoints1[0], endpoints1[1]);
- range1.setEnd(endpoints1[2], endpoints1[3]);
-
- if (range1.startContainer !== endpoints1[0]) {
- throw "Sanity check: the first Range we created must have the desired startContainer";
- }
- if (range1.startOffset !== endpoints1[1]) {
- throw "Sanity check: the first Range we created must have the desired startOffset";
- }
- if (range1.endContainer !== endpoints1[2]) {
- throw "Sanity check: the first Range we created must have the desired endContainer";
- }
- if (range1.endOffset !== endpoints1[3]) {
- throw "Sanity check: the first Range we created must have the desired endOffset";
- }
-
- var endpoints2 = testRangesEvaled[j];
- var range2 = ownerDocument(endpoints2[0]).createRange();
- range2.setStart(endpoints2[0], endpoints2[1]);
- range2.setEnd(endpoints2[2], endpoints2[3]);
-
- if (range2.startContainer !== endpoints2[0]) {
- throw "Sanity check: the second Range we created must have the desired startContainer";
- }
- if (range2.startOffset !== endpoints2[1]) {
- throw "Sanity check: the second Range we created must have the desired startOffset";
- }
- if (range2.endContainer !== endpoints2[2]) {
- throw "Sanity check: the second Range we created must have the desired endContainer";
- }
- if (range2.endOffset !== endpoints2[3]) {
- throw "Sanity check: the second Range we created must have the desired endOffset";
- }
- } catch (e) {
- exception = e;
- }
-
- testAddRange(exception, range1, endpoints1, "first", testName);
- testAddRange(exception, range2, endpoints2, "second", testName);
- }
-}
-
-testDiv.style.display = "none";
-</script>
--- a/selecttest/Selection-collapse.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-<!doctype html>
-<title>Selection.collapse() tests</title>
-<div id=log></div>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script src=common.js></script>
-<script>
-"use strict";
-
-function testCollapse(range, point) {
- selection.removeAllRanges();
- var addedRange;
- if (range) {
- addedRange = range.cloneRange();
- selection.addRange(addedRange);
- }
-
- if (point[0].nodeType == Node.DOCUMENT_TYPE_NODE
- || point[0].nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
- assert_throws("INVALID_NODE_TYPE_ERR", function() {
- selection.collapse(point[0], point[1]);
- }, "Must throw INVALID_NODE_TYPE_ERR when collapse()ing if the node is a DocumentType or ProcessingInstruction");
- return;
- }
-
- if (point[1] < 0 || point[1] > nodeLength(point[0])) {
- assert_throws("INDEX_SIZE_ERR", function() {
- selection.collapse(point[0], point[1]);
- }, "Must throw INDEX_SIZE_ERR when collapse()ing if the offset is negative or greater than the node's length");
- return;
- }
-
- selection.collapse(point[0], point[1]);
-
- assert_equals(selection.rangeCount, 1,
- "selection.rangeCount must equal 1 after collapse()");
- assert_equals(selection.focusNode, point[0],
- "focusNode must equal the node we collapse()d to");
- assert_equals(selection.focusOffset, point[1],
- "focusOffset must equal the offset we collapse()d to");
- assert_equals(selection.focusNode, selection.anchorNode,
- "focusNode and anchorNode must be equal after collapse()");
- assert_equals(selection.focusOffset, selection.anchorOffset,
- "focusOffset and anchorOffset must be equal after collapse()");
- if (range) {
- assert_equals(addedRange.startContainer, range.startContainer,
- "collapse() must not change the startContainer of a preexisting Range");
- assert_equals(addedRange.endContainer, range.endContainer,
- "collapse() must not change the endContainer of a preexisting Range");
- assert_equals(addedRange.startOffset, range.startOffset,
- "collapse() must not change the startOffset of a preexisting Range");
- assert_equals(addedRange.endOffset, range.endOffset,
- "collapse() must not change the endOffset of a preexisting Range");
- }
-}
-
-// Also test a selection with no ranges
-testRanges.unshift("[]");
-
-// Don't want to eval() each point a bazillion times
-var testPointsCached = [];
-for (var i = 0; i < testPoints.length; i++) {
- testPointsCached.push(eval(testPoints[i]));
-}
-
-var tests = [];
-for (var i = 0; i < testRanges.length; i++) {
- var endpoints = eval(testRanges[i]);
- var range;
- test(function() {
- if (endpoints.length) {
- range = ownerDocument(endpoints[0]).createRange();
- range.setStart(endpoints[0], endpoints[1]);
- range.setEnd(endpoints[2], endpoints[3]);
- } else {
- // Empty selection
- range = null;
- }
- }, "Set up range " + i + " " + testRanges[i]);
- for (var j = 0; j < testPoints.length; j++) {
- tests.push(["Range " + i + " " + testRanges[i] + ", point " + j + " " + testPoints[j], range, testPointsCached[j]]);
- }
-}
-
-generate_tests(testCollapse, tests);
-
-testDiv.style.display = "none";
-</script>
--- a/selecttest/Selection-collapseToStartEnd.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-<!doctype html>
-<title>Selection.collapseTo(Start|End)() tests</title>
-<div id=log></div>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script src=common.js></script>
-<script>
-"use strict";
-
-function testCollapseToStartEnd(range) {
-}
-
-// Also test a selection with no ranges
-testRanges.unshift("[]");
-
-for (var i = 0; i < testRanges.length; i++) {
- test(function() {
- selection.removeAllRanges();
- var endpoints = eval(testRanges[i]);
- if (!endpoints.length) {
- assert_throws("INVALID_STATE_ERR", function() {
- selection.collapseToStart();
- }, "Must throw InvalidStateErr if the selection's range is null");
- return;
- }
-
- var addedRange = ownerDocument(endpoints[0]).createRange();
- addedRange.setStart(endpoints[0], endpoints[1]);
- addedRange.setEnd(endpoints[2], endpoints[3]);
- selection.addRange(addedRange);
-
- // We don't penalize browsers here for mishandling addRange() and
- // adding a different range than we specified. They fail addRange()
- // tests for that, and don't have to fail collapseToStart/End() tests
- // too. They do fail if they throw unexpectedly, though. I also fail
- // them if there's no range at all, because otherwise they could pass
- // all tests if addRange() always does nothing and collapseToStart()
- // always throws.
- assert_equals(selection.rangeCount, 1,
- "Sanity check: rangeCount must equal 1 after addRange()");
-
- var expectedEndpoint = [
- selection.getRangeAt(0).startContainer,
- selection.getRangeAt(0).startOffset
- ];
-
- selection.collapseToStart();
-
- assert_equals(selection.rangeCount, 1,
- "selection.rangeCount must equal 1");
- assert_equals(selection.focusNode, expectedEndpoint[0],
- "focusNode must equal the original start node");
- assert_equals(selection.focusOffset, expectedEndpoint[1],
- "focusOffset must equal the original start offset");
- assert_equals(selection.anchorNode, expectedEndpoint[0],
- "anchorNode must equal the original start node");
- assert_equals(selection.anchorOffset, expectedEndpoint[1],
- "anchorOffset must equal the original start offset");
- assert_equals(addedRange.startContainer, endpoints[0],
- "collapseToStart() must not change the startContainer of the selection's original range");
- assert_equals(addedRange.startOffset, endpoints[1],
- "collapseToStart() must not change the startOffset of the selection's original range");
- assert_equals(addedRange.endContainer, endpoints[2],
- "collapseToStart() must not change the endContainer of the selection's original range");
- assert_equals(addedRange.endOffset, endpoints[3],
- "collapseToStart() must not change the endOffset of the selection's original range");
- }, "Range " + i + " " + testRanges[i] + " collapseToStart()");
-
- // Copy-paste of above
- test(function() {
- selection.removeAllRanges();
- var endpoints = eval(testRanges[i]);
- if (!endpoints.length) {
- assert_throws("INVALID_STATE_ERR", function() {
- selection.collapseToEnd();
- }, "Must throw InvalidStateErr if the selection's range is null");
- return;
- }
-
- var addedRange = ownerDocument(endpoints[0]).createRange();
- addedRange.setStart(endpoints[0], endpoints[1]);
- addedRange.setEnd(endpoints[2], endpoints[3]);
- selection.addRange(addedRange);
-
- // We don't penalize browsers here for mishandling addRange() and
- // adding a different range than we specified. They fail addRange()
- // tests for that, and don't have to fail collapseToStart/End() tests
- // too. They do fail if they throw unexpectedly, though. I also fail
- // them if there's no range at all, because otherwise they could pass
- // all tests if addRange() always does nothing and collapseToStart()
- // always throws.
- assert_equals(selection.rangeCount, 1,
- "Sanity check: rangeCount must equal 1 after addRange()");
-
- var expectedEndpoint = [
- selection.getRangeAt(0).endContainer,
- selection.getRangeAt(0).endOffset
- ];
-
- selection.collapseToEnd();
-
- assert_equals(selection.rangeCount, 1,
- "selection.rangeCount must equal 1");
- assert_equals(selection.focusNode, expectedEndpoint[0],
- "focusNode must equal the original end node");
- assert_equals(selection.focusOffset, expectedEndpoint[1],
- "focusOffset must equal the original end offset");
- assert_equals(selection.anchorNode, expectedEndpoint[0],
- "anchorNode must equal the original end node");
- assert_equals(selection.anchorOffset, expectedEndpoint[1],
- "anchorOffset must equal the original end offset");
- assert_equals(addedRange.startContainer, endpoints[0],
- "collapseToEnd() must not change the startContainer of the selection's original range");
- assert_equals(addedRange.startOffset, endpoints[1],
- "collapseToEnd() must not change the startOffset of the selection's original range");
- assert_equals(addedRange.endContainer, endpoints[2],
- "collapseToEnd() must not change the endContainer of the selection's original range");
- assert_equals(addedRange.endOffset, endpoints[3],
- "collapseToEnd() must not change the endOffset of the selection's original range");
- }, "Range " + i + " " + testRanges[i] + " collapseToEnd()");
-}
-
-testDiv.style.display = "none";
-</script>
--- a/selecttest/Selection-dir.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-<!doctype html>
-<title>Selection direction tests</title>
-<meta charset=utf-8>
-<div id=test>
- <p>This is a manual test, since there's no way to synthesize keyboard or
- mouse input. Click after the letter "c" in the following paragraph and
- drag backwards so that both the "b" and the "c" are highlighted, then click
- the "Test" button:
-
- <p>abcd <button onclick=testDirection()>Test</button>
-
- <p>efghi
-</div>
-<div id=log></div>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script>
-setup({explicit_done: true});
-
-function testDirection() {
- var testDiv = document.getElementById("test");
- var p = testDiv.getElementsByTagName("p")[1].firstChild;
- var selection = getSelection();
- var range = selection.getRangeAt(0);
- test(function() {
- assert_equals(range.toString(), "bc");
- }, "The expected range is selected");
- test(function() {
- assert_equals(selection.anchorNode, p);
- assert_equals(selection.focusNode, p);
- }, "Expected node is initially selected");
- test(function() {
- assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [1, 3]);
- }, "Expected offsets are initially selected (maybe not in order)");
- test(function() {
- assert_equals(selection.anchorOffset, 3);
- assert_equals(selection.focusOffset, 1);
- }, "Offsets are backwards for initial selection"),
- test(function() {
- assert_equals(selection.anchorNode, range.endContainer);
- assert_equals(selection.anchorOffset, range.endOffset);
- assert_equals(selection.focusNode, range.startContainer);
- assert_equals(selection.focusOffset, range.startOffset);
- }, "Offsets match the range for initial selection");
-
- // Per spec, the direction of the selection remains even if you zap a range
- // and add a new one.
- test(function() {
- selection.removeRange(range);
- range = document.createRange();
- p = testDiv.getElementsByTagName("p")[0].firstChild;
- range.setStart(p, 0);
- range.setEnd(p, 4);
- assert_equals(range.toString(), "This");
- selection.addRange(range);
- }, "removeRange()/addRange() successful");
- test(function() {
- assert_equals(selection.anchorNode, p);
- assert_equals(selection.focusNode, p);
- }, "Expected node is selected after remove/addRange()");
- test(function() {
- assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [0, 4]);
- }, "Expected offsets are selected after remove/addRange() (maybe not in order)");
- test(function() {
- assert_equals(selection.anchorOffset, 4);
- assert_equals(selection.focusOffset, 0);
- }, "Offsets are backwards after remove/addRange()"),
- test(function() {
- assert_equals(selection.anchorNode, range.endContainer);
- assert_equals(selection.anchorOffset, range.endOffset);
- assert_equals(selection.focusNode, range.startContainer);
- assert_equals(selection.focusOffset, range.startOffset);
- }, "Offsets match the range after remove/addRange()");
-
- // But if you call removeAllRanges(), the direction should reset to
- // forwards.
- test(function() {
- selection.removeAllRanges();
- range = document.createRange();
- p = testDiv.getElementsByTagName("p")[2].firstChild;
- range.setStart(p, 2);
- range.setEnd(p, 5);
- assert_equals(range.toString(), "ghi");
- selection.addRange(range);
- }, "removeAllRanges() successful");
- test(function() {
- assert_equals(selection.anchorNode, p);
- assert_equals(selection.focusNode, p);
- }, "Expected node is selected after removeAllRanges()");
- test(function() {
- assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [2, 5]);
- }, "Expected offsets are selected after removeAllRanges() (maybe not in order)");
- test(function() {
- assert_equals(selection.anchorOffset, 2);
- assert_equals(selection.focusOffset, 5);
- }, "Offsets are forwards after removeAllRanges()");
- test(function() {
- assert_equals(selection.anchorNode, range.startContainer);
- assert_equals(selection.anchorOffset, range.startOffset);
- assert_equals(selection.focusNode, range.endContainer);
- assert_equals(selection.focusOffset, range.endOffset);
- }, "Offsets match the range after removeAllRanges()");
-
- done();
-}
-</script>
--- a/selecttest/Selection-extend.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-<!doctype html>
-<title>Selection extend() tests</title>
-<meta charset=utf-8>
-<body>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script src=common.js></script>
-<div id=log></div>
-<script>
-/**
- * Returns "forwards" if the selection direction is forwards, "backwards" if
- * it's backwards. This appears not to work in WebKit at all, because there
- * seems to be no way of adding a range or replacing the current range without
- * calling removeAllRanges(), which resets the direction. So we're nice and
- * look at the current range if possible; otherwise we do some stuff that
- * involves calling removeRange(), which doesn't exist in WebKit, so it will
- * fail the test.
- */
-function getSelectionDirection() {
- if (selection.anchorNode != selection.focusNode
- || selection.anchorOffset != selection.focusOffset) {
- var range = selection.getRangeAt(selection.rangeCount - 1);
- // We can determine the direction without mangling anything.
- if (selection.anchorNode == range.startContainer
- && selection.anchorOffset == range.startOffset) {
- return "forwards";
- }
- if (selection.anchorNode == range.endContainer
- && selection.anchorOffset == range.endOffset) {
- return "backwards";
- }
- throw "Something buggy with directions";
- }
-
- var range = document.createRange();
- range.setStart(paras[0].firstChild, 0);
- range.setEnd(paras[0].firstChild, 1);
- selection.addRange(range);
- if (selection.anchorOffset == range.startOffset) {
- selection.removeRange(range);
- return "forwards";
- }
- if (selection.anchorOffset == range.endOffset) {
- selection.removeRange(range);
- return "backwards";
- }
-}
-
-/**
- * We test Selections that go both forwards and backwards here. In the latter
- * case we need to use extend() to force it to go backwards, which is fair
- * enough, since that's what we're testing.
- */
-
-var originalSelectionDirection;
-
-function testExtendForwards(initialRanges, extendTarget) {
- originalSelectionDirection = "forwards";
- selection.removeAllRanges();
-
- for (var i = 0; i < initialRanges.length; i += 4) {
- var range = ownerDocument(initialRanges[i]).createRange();
- range.setStart(initialRanges[i], initialRanges[i + 1]);
- range.setEnd(initialRanges[i + 2], initialRanges[i + 3]);
- selection.addRange(range);
- }
-
- testExtend(extendTarget, initialRanges.length/4);
-}
-
-function testExtendBackwards(initialRanges, extendTarget) {
- originalSelectionDirection = "backwards";
- selection.removeAllRanges();
-
- for (var i = 0; i < initialRanges.length; i += 4) {
- // To get a backwards selection, we add ranges by appending a
- // zero-length range at the end, then extend()ing backwards to the
- // start. This fails in Opera, since Opera ignores addRange() on a
- // collapsed range. FIXME: This doesn't actually make the initial
- // selection backwards, if the range we're given is collapsed.
- var range = ownerDocument(initialRanges[i]).createRange();
- range.setStart(initialRanges[i + 2], initialRanges[i + 3]);
- range.setEnd(initialRanges[i + 2], initialRanges[i + 3]);
- selection.addRange(range);
- selection.extend(initialRanges[i], initialRanges[i + 1]);
- }
-
- testExtend(extendTarget, initialRanges.length/4);
-}
-
-function testExtend(extendTarget, numRanges) {
- assert_equals(selection.rangeCount, numRanges,
- "Failed sanity check: selection.rangeCount is wrong. Perhaps addRange() failed.");
-
- var node = extendTarget[0];
- var offset = extendTarget[1];
-
- if (node === null) {
- assert_throws("TYPE_MISMATCH_ERR", function() {
- selection.extend(node, offset);
- }, "extend(null, foo) must throw TYPE_MISMATCH_ERR");
- return;
- }
-
- if (selection.rangeCount == 0) {
- assert_throws("INVALID_STATE_ERR", function() {
- selection.extend(node, offset);
- }, "extend() when rangeCount is 0 must throw INVALID_STATE_ERR");
- return;
- }
-
- if (node.nodeType == Node.DOCUMENT_TYPE_NODE
- || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
- assert_throws("INVALID_NODE_TYPE_ERR", function() {
- selection.extend(node, offset);
- }, "extend() to a doctype or PI must throw INVALID_NODE_TYPE_ERR");
- return;
- }
-
- if (offset < 0 || offset > nodeLength(node)) {
- assert_throws("INDEX_SIZE_ERR", function() {
- selection.extend(node, offset);
- }, "extend() to an offset that's negative or greater than node length (" + nodeLength(node) + ") must throw INDEX_SIZE_ERR");
- return;
- }
-
- var range = selection.getRangeAt(selection.rangeCount - 1);
- var rangeRoot = furthestAncestor(range.startContainer);
- var nodeRoot = furthestAncestor(node);
-
- assert_equals(rangeRoot, furthestAncestor(range.endContainer),
- "The furthest ancestor of a Range's start and end must always be the same (I think)");
-
- if (rangeRoot != nodeRoot) {
- selection.extend(node, offset);
- assert_equals(selection.anchorNode, node,
- "If the furthest ancestors of the range and extend() target differ, anchorNode must be set to the target node");
- assert_equals(selection.anchorOffset, offset,
- "If the furthest ancestors of the range and extend() target differ, anchorOffset must be set to the target offset");
- assert_equals(selection.focusNode, node,
- "If the furthest ancestors of the range and extend() target differ, focusNode must be set to the target node");
- assert_equals(selection.focusOffset, offset,
- "If the furthest ancestors of the range and extend() target differ, focusOffset must be set to the target offset");
- assert_equals(getSelectionDirection(), "backwards",
- "If the furthest ancestors of the range and extent() target differ, the new selection must be backwards");
- return;
- }
-
- if (selection.focusNode == node && selection.focusOffset == offset) {
- // extend() must do nothing.
- var oldFocusNode = selection.focusNode;
- var oldFocusOffset = selection.focusOffset;
- var oldAnchorNode = selection.anchorNode;
- var oldAnchorOffset = selection.anchorOffset;
- var oldRanges = [];
- for (var i = 0; i < selection.rangeCount; i++) {
- oldRanges.push(selection.getRangeAt(i));
- }
- selection.extend(node, offset);
- assert_equals(selection.focusNode, oldFocusNode,
- "extend() to the current focus must not change focusNode");
- assert_equals(selection.focusOffset, oldFocusOffset,
- "extend() to the current focus must not change focusOffset");
- assert_equals(selection.anchorNode, oldAnchorNode,
- "extend() to the current focus must not change anchorNode");
- assert_equals(selection.anchorOffset, oldAnchorOffset,
- "extend() to the current focus must not change anchorOffset");
- assert_equals(selection.rangeCount, oldRanges.length,
- "extend() to the current focus must not change rangeCount");
- for (var i = 0; i < oldRanges.length; i++) {
- assert_equals(selection.getRangeAt(i), oldRanges[i],
- "extend() to the current focus must not change any Ranges");
- }
- assert_equals(getSelectionDirection(), originalSelectionDirection,
- "extend() of a selection to the current focus must not change direction");
- return;
- }
-
- var oldAnchorNode = selection.anchorNode;
- var oldAnchorOffset = selection.anchorOffset;
- var oldFocusNode = selection.focusNode;
- var oldFocusOffset = selection.focusOffset;
- var oldRanges = [];
- for (var i = 0; i < selection.rangeCount; i++) {
- oldRanges.push(selection.getRangeAt(i));
- }
- selection.extend(node, offset);
- assert_equals(selection.anchorNode, oldAnchorNode,
- "extend() must not change anchorNode in the usual case");
- assert_equals(selection.anchorOffset, oldAnchorOffset,
- "extend() must not change anchorOffset in the usual case");
- assert_equals(selection.rangeCount, oldRanges.length,
- "extend() must not change rangeCount in the usual case");
- for (var i = 0; i < oldRanges.length - 1; i++) {
- assert_equals(selection.getRangeAt(i), oldRanges[i],
- "extend() must not change any Range but the last in the usual case");
- }
- assert_equals(selection.focusNode, node,
- "extend() must update focusNode to the target node in the usual case");
- assert_equals(selection.focusOffset, offset,
- "extend() must update focusOffset to the target offset in the usual case");
-
- var expectedDirection;
- var range = document.createRange();
- range.setStart(oldAnchorNode, oldAnchorOffset);
- range.setEnd(oldAnchorNode, oldAnchorOffset);
- if (range.comparePoint(node, offset) >= 0) {
- expectedDirection = "forwards";
- } else {
- expectedDirection = "backwards";
- }
- assert_equals(getSelectionDirection(), expectedDirection,
- "extend() must set direction appropriately in the usual case");
-}
-
-// Also test a selection with no ranges
-testRanges.unshift("[]");
-
-var tests = [];
-for (var i = 0; i < testRanges.length; i++) {
- for (var j = 0; j < testPoints.length; j++) {
- tests.push([
- "extend() forwards with range " + i + " " + testRanges[i] + " and point " + j + " " + testPoints[j],
- eval(testRanges[i]),
- eval(testPoints[j])
- ]);
- }
-}
-generate_tests(testExtendForwards, tests);
-
-// Copy-pasted with "forwards" changed to "backwards" :/
-var tests = [];
-for (var i = 0; i < testRanges.length; i++) {
- for (var j = 0; j < testPoints.length; j++) {
- tests.push([
- "extend() backwards with range " + i + " " + testRanges[i] + " and point " + j + " " + testPoints[j],
- eval(testRanges[i]),
- eval(testPoints[j])
- ]);
- }
-}
-generate_tests(testExtendBackwards, tests);
-
-// Let's be tidy.
-testDiv.style.display = "none";
-</script>
--- a/selecttest/Selection-getRangeAt.html Tue Oct 11 15:30:30 2011 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<title>The getRangeAt method</title>
-<div id=log></div>
-<script src=http://w3c-test.org/resources/testharness.js></script>
-<script>
-test(function() {
- var sel = getSelection();
- var range = document.createRange();
- sel.addRange(range);
- assert_throws("INDEX_SIZE_ERR", function() { sel.getRangeAt(-1); })
- assert_throws("INDEX_SIZE_ERR", function() { sel.getRangeAt(1); })
-});
-</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/addRange.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,176 @@
+<!doctype html>
+<title>Selection.addRange() tests</title>
+<div id=log></div>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script src=common.js></script>
+<script>
+"use strict";
+
+function testAddRange(exception, range, endpoints, qualifier, testName) {
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+
+ selection.addRange(range);
+
+ assert_equals(range.startContainer, endpoints[0],
+ "addRange() must not modify the startContainer of the Range it's given");
+ assert_equals(range.startOffset, endpoints[1],
+ "addRange() must not modify the startOffset of the Range it's given");
+ assert_equals(range.endContainer, endpoints[2],
+ "addRange() must not modify the endContainer of the Range it's given");
+ assert_equals(range.endOffset, endpoints[3],
+ "addRange() must not modify the endOffset of the Range it's given");
+ }, testName + ": " + qualifier + " addRange() must not throw exceptions or modify the range it's given");
+
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+
+ assert_equals(selection.rangeCount, 1, "rangeCount must be 1");
+ }, testName + ": " + qualifier + " addRange() must result in rangeCount being 1");
+
+ // From here on out we check selection.getRangeAt(selection.rangeCount - 1)
+ // so as not to double-fail Gecko.
+
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+ assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
+
+ var newRange = selection.getRangeAt(selection.rangeCount - 1);
+
+ assert_not_equals(newRange, null,
+ "getRangeAt(rangeCount - 1) must not return null");
+ assert_equals(typeof newRange, "object",
+ "getRangeAt(rangeCount - 1) must return an object");
+
+ assert_equals(newRange.startContainer, range.startContainer,
+ "startContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.startOffset, range.startOffset,
+ "startOffset of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endContainer, range.endContainer,
+ "endContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endOffset, range.endOffset,
+ "endOffset of the Selection's last Range must match the added Range");
+ }, testName + ": " + qualifier + " addRange() must result in the selection's last range having the specified endpoints");
+
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+ assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
+
+ assert_equals(selection.getRangeAt(selection.rangeCount - 1), range,
+ "getRangeAt(rangeCount - 1) must return the same object we added");
+ }, testName + ": " + qualifier + " addRange() must result in the selection's last range being the same object we added");
+
+ // Let's not test many different modifications -- one should be enough.
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+ assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
+
+ if (range.startContainer == paras[0].firstChild
+ && range.startOffset == 0
+ && range.endContainer == paras[0].firstChild
+ && range.endOffset == 2) {
+ // Just in case . . .
+ range.setStart(paras[0].firstChild, 1);
+ } else {
+ range.setStart(paras[0].firstChild, 0);
+ range.setEnd(paras[0].firstChild, 2);
+ }
+
+ var newRange = selection.getRangeAt(selection.rangeCount - 1);
+
+ assert_equals(newRange.startContainer, range.startContainer,
+ "After mutating the " + qualifier + " added Range, startContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.startOffset, range.startOffset,
+ "After mutating the " + qualifier + " added Range, startOffset of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endContainer, range.endContainer,
+ "After mutating the " + qualifier + " added Range, endContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endOffset, range.endOffset,
+ "After mutating the " + qualifier + " added Range, endOffset of the Selection's last Range must match the added Range");
+ }, testName + ": modifying the " + qualifier + " added range must modify the Selection's last Range");
+
+ // Now test the other way too.
+ test(function() {
+ assert_equals(exception, null, "Test setup must not throw exceptions");
+ assert_not_equals(selection.rangeCount, 0, "Cannot proceed with tests if rangeCount is 0");
+
+ var newRange = selection.getRangeAt(selection.rangeCount - 1);
+
+ if (newRange.startContainer == paras[0].firstChild
+ && newRange.startOffset == 4
+ && newRange.endContainer == paras[0].firstChild
+ && newRange.endOffset == 6) {
+ newRange.setStart(paras[0].firstChild, 5);
+ } else {
+ newRange.setStart(paras[0].firstChild, 4);
+ newRange.setStart(paras[0].firstChild, 6);
+ }
+
+ assert_equals(newRange.startContainer, range.startContainer,
+ "After " + qualifier + " addRange(), after mutating the Selection's last Range, startContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.startOffset, range.startOffset,
+ "After " + qualifier + " addRange(), after mutating the Selection's last Range, startOffset of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endContainer, range.endContainer,
+ "After " + qualifier + " addRange(), after mutating the Selection's last Range, endContainer of the Selection's last Range must match the added Range");
+ assert_equals(newRange.endOffset, range.endOffset,
+ "After " + qualifier + " addRange(), after mutating the Selection's last Range, endOffset of the Selection's last Range must match the added Range");
+ }, testName + ": modifying the Selection's last Range must modify the " + qualifier + " added Range");
+}
+
+// Do only n evals, not n^2
+var testRangesEvaled = testRanges.map(eval);
+
+for (var i = 0; i < testRanges.length; i++) {
+ for (var j = 0; j < testRanges.length; j++) {
+ var testName = "Range " + i + " " + testRanges[i]
+ + " followed by Range " + j + " " + testRanges[j];
+
+ var exception = null;
+ try {
+ selection.removeAllRanges();
+
+ var endpoints1 = testRangesEvaled[i];
+ var range1 = ownerDocument(endpoints1[0]).createRange();
+ range1.setStart(endpoints1[0], endpoints1[1]);
+ range1.setEnd(endpoints1[2], endpoints1[3]);
+
+ if (range1.startContainer !== endpoints1[0]) {
+ throw "Sanity check: the first Range we created must have the desired startContainer";
+ }
+ if (range1.startOffset !== endpoints1[1]) {
+ throw "Sanity check: the first Range we created must have the desired startOffset";
+ }
+ if (range1.endContainer !== endpoints1[2]) {
+ throw "Sanity check: the first Range we created must have the desired endContainer";
+ }
+ if (range1.endOffset !== endpoints1[3]) {
+ throw "Sanity check: the first Range we created must have the desired endOffset";
+ }
+
+ var endpoints2 = testRangesEvaled[j];
+ var range2 = ownerDocument(endpoints2[0]).createRange();
+ range2.setStart(endpoints2[0], endpoints2[1]);
+ range2.setEnd(endpoints2[2], endpoints2[3]);
+
+ if (range2.startContainer !== endpoints2[0]) {
+ throw "Sanity check: the second Range we created must have the desired startContainer";
+ }
+ if (range2.startOffset !== endpoints2[1]) {
+ throw "Sanity check: the second Range we created must have the desired startOffset";
+ }
+ if (range2.endContainer !== endpoints2[2]) {
+ throw "Sanity check: the second Range we created must have the desired endContainer";
+ }
+ if (range2.endOffset !== endpoints2[3]) {
+ throw "Sanity check: the second Range we created must have the desired endOffset";
+ }
+ } catch (e) {
+ exception = e;
+ }
+
+ testAddRange(exception, range1, endpoints1, "first", testName);
+ testAddRange(exception, range2, endpoints2, "second", testName);
+ }
+}
+
+testDiv.style.display = "none";
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/collapse.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,87 @@
+<!doctype html>
+<title>Selection.collapse() tests</title>
+<div id=log></div>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script src=common.js></script>
+<script>
+"use strict";
+
+function testCollapse(range, point) {
+ selection.removeAllRanges();
+ var addedRange;
+ if (range) {
+ addedRange = range.cloneRange();
+ selection.addRange(addedRange);
+ }
+
+ if (point[0].nodeType == Node.DOCUMENT_TYPE_NODE
+ || point[0].nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ selection.collapse(point[0], point[1]);
+ }, "Must throw INVALID_NODE_TYPE_ERR when collapse()ing if the node is a DocumentType or ProcessingInstruction");
+ return;
+ }
+
+ if (point[1] < 0 || point[1] > nodeLength(point[0])) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ selection.collapse(point[0], point[1]);
+ }, "Must throw INDEX_SIZE_ERR when collapse()ing if the offset is negative or greater than the node's length");
+ return;
+ }
+
+ selection.collapse(point[0], point[1]);
+
+ assert_equals(selection.rangeCount, 1,
+ "selection.rangeCount must equal 1 after collapse()");
+ assert_equals(selection.focusNode, point[0],
+ "focusNode must equal the node we collapse()d to");
+ assert_equals(selection.focusOffset, point[1],
+ "focusOffset must equal the offset we collapse()d to");
+ assert_equals(selection.focusNode, selection.anchorNode,
+ "focusNode and anchorNode must be equal after collapse()");
+ assert_equals(selection.focusOffset, selection.anchorOffset,
+ "focusOffset and anchorOffset must be equal after collapse()");
+ if (range) {
+ assert_equals(addedRange.startContainer, range.startContainer,
+ "collapse() must not change the startContainer of a preexisting Range");
+ assert_equals(addedRange.endContainer, range.endContainer,
+ "collapse() must not change the endContainer of a preexisting Range");
+ assert_equals(addedRange.startOffset, range.startOffset,
+ "collapse() must not change the startOffset of a preexisting Range");
+ assert_equals(addedRange.endOffset, range.endOffset,
+ "collapse() must not change the endOffset of a preexisting Range");
+ }
+}
+
+// Also test a selection with no ranges
+testRanges.unshift("[]");
+
+// Don't want to eval() each point a bazillion times
+var testPointsCached = [];
+for (var i = 0; i < testPoints.length; i++) {
+ testPointsCached.push(eval(testPoints[i]));
+}
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+ var endpoints = eval(testRanges[i]);
+ var range;
+ test(function() {
+ if (endpoints.length) {
+ range = ownerDocument(endpoints[0]).createRange();
+ range.setStart(endpoints[0], endpoints[1]);
+ range.setEnd(endpoints[2], endpoints[3]);
+ } else {
+ // Empty selection
+ range = null;
+ }
+ }, "Set up range " + i + " " + testRanges[i]);
+ for (var j = 0; j < testPoints.length; j++) {
+ tests.push(["Range " + i + " " + testRanges[i] + ", point " + j + " " + testPoints[j], range, testPointsCached[j]]);
+ }
+}
+
+generate_tests(testCollapse, tests);
+
+testDiv.style.display = "none";
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/collapseToStartEnd.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,123 @@
+<!doctype html>
+<title>Selection.collapseTo(Start|End)() tests</title>
+<div id=log></div>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script src=common.js></script>
+<script>
+"use strict";
+
+function testCollapseToStartEnd(range) {
+}
+
+// Also test a selection with no ranges
+testRanges.unshift("[]");
+
+for (var i = 0; i < testRanges.length; i++) {
+ test(function() {
+ selection.removeAllRanges();
+ var endpoints = eval(testRanges[i]);
+ if (!endpoints.length) {
+ assert_throws("INVALID_STATE_ERR", function() {
+ selection.collapseToStart();
+ }, "Must throw InvalidStateErr if the selection's range is null");
+ return;
+ }
+
+ var addedRange = ownerDocument(endpoints[0]).createRange();
+ addedRange.setStart(endpoints[0], endpoints[1]);
+ addedRange.setEnd(endpoints[2], endpoints[3]);
+ selection.addRange(addedRange);
+
+ // We don't penalize browsers here for mishandling addRange() and
+ // adding a different range than we specified. They fail addRange()
+ // tests for that, and don't have to fail collapseToStart/End() tests
+ // too. They do fail if they throw unexpectedly, though. I also fail
+ // them if there's no range at all, because otherwise they could pass
+ // all tests if addRange() always does nothing and collapseToStart()
+ // always throws.
+ assert_equals(selection.rangeCount, 1,
+ "Sanity check: rangeCount must equal 1 after addRange()");
+
+ var expectedEndpoint = [
+ selection.getRangeAt(0).startContainer,
+ selection.getRangeAt(0).startOffset
+ ];
+
+ selection.collapseToStart();
+
+ assert_equals(selection.rangeCount, 1,
+ "selection.rangeCount must equal 1");
+ assert_equals(selection.focusNode, expectedEndpoint[0],
+ "focusNode must equal the original start node");
+ assert_equals(selection.focusOffset, expectedEndpoint[1],
+ "focusOffset must equal the original start offset");
+ assert_equals(selection.anchorNode, expectedEndpoint[0],
+ "anchorNode must equal the original start node");
+ assert_equals(selection.anchorOffset, expectedEndpoint[1],
+ "anchorOffset must equal the original start offset");
+ assert_equals(addedRange.startContainer, endpoints[0],
+ "collapseToStart() must not change the startContainer of the selection's original range");
+ assert_equals(addedRange.startOffset, endpoints[1],
+ "collapseToStart() must not change the startOffset of the selection's original range");
+ assert_equals(addedRange.endContainer, endpoints[2],
+ "collapseToStart() must not change the endContainer of the selection's original range");
+ assert_equals(addedRange.endOffset, endpoints[3],
+ "collapseToStart() must not change the endOffset of the selection's original range");
+ }, "Range " + i + " " + testRanges[i] + " collapseToStart()");
+
+ // Copy-paste of above
+ test(function() {
+ selection.removeAllRanges();
+ var endpoints = eval(testRanges[i]);
+ if (!endpoints.length) {
+ assert_throws("INVALID_STATE_ERR", function() {
+ selection.collapseToEnd();
+ }, "Must throw InvalidStateErr if the selection's range is null");
+ return;
+ }
+
+ var addedRange = ownerDocument(endpoints[0]).createRange();
+ addedRange.setStart(endpoints[0], endpoints[1]);
+ addedRange.setEnd(endpoints[2], endpoints[3]);
+ selection.addRange(addedRange);
+
+ // We don't penalize browsers here for mishandling addRange() and
+ // adding a different range than we specified. They fail addRange()
+ // tests for that, and don't have to fail collapseToStart/End() tests
+ // too. They do fail if they throw unexpectedly, though. I also fail
+ // them if there's no range at all, because otherwise they could pass
+ // all tests if addRange() always does nothing and collapseToStart()
+ // always throws.
+ assert_equals(selection.rangeCount, 1,
+ "Sanity check: rangeCount must equal 1 after addRange()");
+
+ var expectedEndpoint = [
+ selection.getRangeAt(0).endContainer,
+ selection.getRangeAt(0).endOffset
+ ];
+
+ selection.collapseToEnd();
+
+ assert_equals(selection.rangeCount, 1,
+ "selection.rangeCount must equal 1");
+ assert_equals(selection.focusNode, expectedEndpoint[0],
+ "focusNode must equal the original end node");
+ assert_equals(selection.focusOffset, expectedEndpoint[1],
+ "focusOffset must equal the original end offset");
+ assert_equals(selection.anchorNode, expectedEndpoint[0],
+ "anchorNode must equal the original end node");
+ assert_equals(selection.anchorOffset, expectedEndpoint[1],
+ "anchorOffset must equal the original end offset");
+ assert_equals(addedRange.startContainer, endpoints[0],
+ "collapseToEnd() must not change the startContainer of the selection's original range");
+ assert_equals(addedRange.startOffset, endpoints[1],
+ "collapseToEnd() must not change the startOffset of the selection's original range");
+ assert_equals(addedRange.endContainer, endpoints[2],
+ "collapseToEnd() must not change the endContainer of the selection's original range");
+ assert_equals(addedRange.endOffset, endpoints[3],
+ "collapseToEnd() must not change the endOffset of the selection's original range");
+ }, "Range " + i + " " + testRanges[i] + " collapseToEnd()");
+}
+
+testDiv.style.display = "none";
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/dir.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,105 @@
+<!doctype html>
+<title>Selection direction tests</title>
+<meta charset=utf-8>
+<div id=test>
+ <p>This is a manual test, since there's no way to synthesize keyboard or
+ mouse input. Click after the letter "c" in the following paragraph and
+ drag backwards so that both the "b" and the "c" are highlighted, then click
+ the "Test" button:
+
+ <p>abcd <button onclick=testDirection()>Test</button>
+
+ <p>efghi
+</div>
+<div id=log></div>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script>
+setup({explicit_done: true});
+
+function testDirection() {
+ var testDiv = document.getElementById("test");
+ var p = testDiv.getElementsByTagName("p")[1].firstChild;
+ var selection = getSelection();
+ var range = selection.getRangeAt(0);
+ test(function() {
+ assert_equals(range.toString(), "bc");
+ }, "The expected range is selected");
+ test(function() {
+ assert_equals(selection.anchorNode, p);
+ assert_equals(selection.focusNode, p);
+ }, "Expected node is initially selected");
+ test(function() {
+ assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [1, 3]);
+ }, "Expected offsets are initially selected (maybe not in order)");
+ test(function() {
+ assert_equals(selection.anchorOffset, 3);
+ assert_equals(selection.focusOffset, 1);
+ }, "Offsets are backwards for initial selection"),
+ test(function() {
+ assert_equals(selection.anchorNode, range.endContainer);
+ assert_equals(selection.anchorOffset, range.endOffset);
+ assert_equals(selection.focusNode, range.startContainer);
+ assert_equals(selection.focusOffset, range.startOffset);
+ }, "Offsets match the range for initial selection");
+
+ // Per spec, the direction of the selection remains even if you zap a range
+ // and add a new one.
+ test(function() {
+ selection.removeRange(range);
+ range = document.createRange();
+ p = testDiv.getElementsByTagName("p")[0].firstChild;
+ range.setStart(p, 0);
+ range.setEnd(p, 4);
+ assert_equals(range.toString(), "This");
+ selection.addRange(range);
+ }, "removeRange()/addRange() successful");
+ test(function() {
+ assert_equals(selection.anchorNode, p);
+ assert_equals(selection.focusNode, p);
+ }, "Expected node is selected after remove/addRange()");
+ test(function() {
+ assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [0, 4]);
+ }, "Expected offsets are selected after remove/addRange() (maybe not in order)");
+ test(function() {
+ assert_equals(selection.anchorOffset, 4);
+ assert_equals(selection.focusOffset, 0);
+ }, "Offsets are backwards after remove/addRange()"),
+ test(function() {
+ assert_equals(selection.anchorNode, range.endContainer);
+ assert_equals(selection.anchorOffset, range.endOffset);
+ assert_equals(selection.focusNode, range.startContainer);
+ assert_equals(selection.focusOffset, range.startOffset);
+ }, "Offsets match the range after remove/addRange()");
+
+ // But if you call removeAllRanges(), the direction should reset to
+ // forwards.
+ test(function() {
+ selection.removeAllRanges();
+ range = document.createRange();
+ p = testDiv.getElementsByTagName("p")[2].firstChild;
+ range.setStart(p, 2);
+ range.setEnd(p, 5);
+ assert_equals(range.toString(), "ghi");
+ selection.addRange(range);
+ }, "removeAllRanges() successful");
+ test(function() {
+ assert_equals(selection.anchorNode, p);
+ assert_equals(selection.focusNode, p);
+ }, "Expected node is selected after removeAllRanges()");
+ test(function() {
+ assert_array_equals([selection.anchorOffset, selection.focusOffset].sort(), [2, 5]);
+ }, "Expected offsets are selected after removeAllRanges() (maybe not in order)");
+ test(function() {
+ assert_equals(selection.anchorOffset, 2);
+ assert_equals(selection.focusOffset, 5);
+ }, "Offsets are forwards after removeAllRanges()");
+ test(function() {
+ assert_equals(selection.anchorNode, range.startContainer);
+ assert_equals(selection.anchorOffset, range.startOffset);
+ assert_equals(selection.focusNode, range.endContainer);
+ assert_equals(selection.focusOffset, range.endOffset);
+ }, "Offsets match the range after removeAllRanges()");
+
+ done();
+}
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/extend.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,245 @@
+<!doctype html>
+<title>Selection extend() tests</title>
+<meta charset=utf-8>
+<body>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script src=common.js></script>
+<div id=log></div>
+<script>
+/**
+ * Returns "forwards" if the selection direction is forwards, "backwards" if
+ * it's backwards. This appears not to work in WebKit at all, because there
+ * seems to be no way of adding a range or replacing the current range without
+ * calling removeAllRanges(), which resets the direction. So we're nice and
+ * look at the current range if possible; otherwise we do some stuff that
+ * involves calling removeRange(), which doesn't exist in WebKit, so it will
+ * fail the test.
+ */
+function getSelectionDirection() {
+ if (selection.anchorNode != selection.focusNode
+ || selection.anchorOffset != selection.focusOffset) {
+ var range = selection.getRangeAt(selection.rangeCount - 1);
+ // We can determine the direction without mangling anything.
+ if (selection.anchorNode == range.startContainer
+ && selection.anchorOffset == range.startOffset) {
+ return "forwards";
+ }
+ if (selection.anchorNode == range.endContainer
+ && selection.anchorOffset == range.endOffset) {
+ return "backwards";
+ }
+ throw "Something buggy with directions";
+ }
+
+ var range = document.createRange();
+ range.setStart(paras[0].firstChild, 0);
+ range.setEnd(paras[0].firstChild, 1);
+ selection.addRange(range);
+ if (selection.anchorOffset == range.startOffset) {
+ selection.removeRange(range);
+ return "forwards";
+ }
+ if (selection.anchorOffset == range.endOffset) {
+ selection.removeRange(range);
+ return "backwards";
+ }
+}
+
+/**
+ * We test Selections that go both forwards and backwards here. In the latter
+ * case we need to use extend() to force it to go backwards, which is fair
+ * enough, since that's what we're testing.
+ */
+
+var originalSelectionDirection;
+
+function testExtendForwards(initialRanges, extendTarget) {
+ originalSelectionDirection = "forwards";
+ selection.removeAllRanges();
+
+ for (var i = 0; i < initialRanges.length; i += 4) {
+ var range = ownerDocument(initialRanges[i]).createRange();
+ range.setStart(initialRanges[i], initialRanges[i + 1]);
+ range.setEnd(initialRanges[i + 2], initialRanges[i + 3]);
+ selection.addRange(range);
+ }
+
+ testExtend(extendTarget, initialRanges.length/4);
+}
+
+function testExtendBackwards(initialRanges, extendTarget) {
+ originalSelectionDirection = "backwards";
+ selection.removeAllRanges();
+
+ for (var i = 0; i < initialRanges.length; i += 4) {
+ // To get a backwards selection, we add ranges by appending a
+ // zero-length range at the end, then extend()ing backwards to the
+ // start. This fails in Opera, since Opera ignores addRange() on a
+ // collapsed range. FIXME: This doesn't actually make the initial
+ // selection backwards, if the range we're given is collapsed.
+ var range = ownerDocument(initialRanges[i]).createRange();
+ range.setStart(initialRanges[i + 2], initialRanges[i + 3]);
+ range.setEnd(initialRanges[i + 2], initialRanges[i + 3]);
+ selection.addRange(range);
+ selection.extend(initialRanges[i], initialRanges[i + 1]);
+ }
+
+ testExtend(extendTarget, initialRanges.length/4);
+}
+
+function testExtend(extendTarget, numRanges) {
+ assert_equals(selection.rangeCount, numRanges,
+ "Failed sanity check: selection.rangeCount is wrong. Perhaps addRange() failed.");
+
+ var node = extendTarget[0];
+ var offset = extendTarget[1];
+
+ if (node === null) {
+ assert_throws("TYPE_MISMATCH_ERR", function() {
+ selection.extend(node, offset);
+ }, "extend(null, foo) must throw TYPE_MISMATCH_ERR");
+ return;
+ }
+
+ if (selection.rangeCount == 0) {
+ assert_throws("INVALID_STATE_ERR", function() {
+ selection.extend(node, offset);
+ }, "extend() when rangeCount is 0 must throw INVALID_STATE_ERR");
+ return;
+ }
+
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE
+ || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ selection.extend(node, offset);
+ }, "extend() to a doctype or PI must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ if (offset < 0 || offset > nodeLength(node)) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ selection.extend(node, offset);
+ }, "extend() to an offset that's negative or greater than node length (" + nodeLength(node) + ") must throw INDEX_SIZE_ERR");
+ return;
+ }
+
+ var range = selection.getRangeAt(selection.rangeCount - 1);
+ var rangeRoot = furthestAncestor(range.startContainer);
+ var nodeRoot = furthestAncestor(node);
+
+ assert_equals(rangeRoot, furthestAncestor(range.endContainer),
+ "The furthest ancestor of a Range's start and end must always be the same (I think)");
+
+ if (rangeRoot != nodeRoot) {
+ selection.extend(node, offset);
+ assert_equals(selection.anchorNode, node,
+ "If the furthest ancestors of the range and extend() target differ, anchorNode must be set to the target node");
+ assert_equals(selection.anchorOffset, offset,
+ "If the furthest ancestors of the range and extend() target differ, anchorOffset must be set to the target offset");
+ assert_equals(selection.focusNode, node,
+ "If the furthest ancestors of the range and extend() target differ, focusNode must be set to the target node");
+ assert_equals(selection.focusOffset, offset,
+ "If the furthest ancestors of the range and extend() target differ, focusOffset must be set to the target offset");
+ assert_equals(getSelectionDirection(), "backwards",
+ "If the furthest ancestors of the range and extent() target differ, the new selection must be backwards");
+ return;
+ }
+
+ if (selection.focusNode == node && selection.focusOffset == offset) {
+ // extend() must do nothing.
+ var oldFocusNode = selection.focusNode;
+ var oldFocusOffset = selection.focusOffset;
+ var oldAnchorNode = selection.anchorNode;
+ var oldAnchorOffset = selection.anchorOffset;
+ var oldRanges = [];
+ for (var i = 0; i < selection.rangeCount; i++) {
+ oldRanges.push(selection.getRangeAt(i));
+ }
+ selection.extend(node, offset);
+ assert_equals(selection.focusNode, oldFocusNode,
+ "extend() to the current focus must not change focusNode");
+ assert_equals(selection.focusOffset, oldFocusOffset,
+ "extend() to the current focus must not change focusOffset");
+ assert_equals(selection.anchorNode, oldAnchorNode,
+ "extend() to the current focus must not change anchorNode");
+ assert_equals(selection.anchorOffset, oldAnchorOffset,
+ "extend() to the current focus must not change anchorOffset");
+ assert_equals(selection.rangeCount, oldRanges.length,
+ "extend() to the current focus must not change rangeCount");
+ for (var i = 0; i < oldRanges.length; i++) {
+ assert_equals(selection.getRangeAt(i), oldRanges[i],
+ "extend() to the current focus must not change any Ranges");
+ }
+ assert_equals(getSelectionDirection(), originalSelectionDirection,
+ "extend() of a selection to the current focus must not change direction");
+ return;
+ }
+
+ var oldAnchorNode = selection.anchorNode;
+ var oldAnchorOffset = selection.anchorOffset;
+ var oldFocusNode = selection.focusNode;
+ var oldFocusOffset = selection.focusOffset;
+ var oldRanges = [];
+ for (var i = 0; i < selection.rangeCount; i++) {
+ oldRanges.push(selection.getRangeAt(i));
+ }
+ selection.extend(node, offset);
+ assert_equals(selection.anchorNode, oldAnchorNode,
+ "extend() must not change anchorNode in the usual case");
+ assert_equals(selection.anchorOffset, oldAnchorOffset,
+ "extend() must not change anchorOffset in the usual case");
+ assert_equals(selection.rangeCount, oldRanges.length,
+ "extend() must not change rangeCount in the usual case");
+ for (var i = 0; i < oldRanges.length - 1; i++) {
+ assert_equals(selection.getRangeAt(i), oldRanges[i],
+ "extend() must not change any Range but the last in the usual case");
+ }
+ assert_equals(selection.focusNode, node,
+ "extend() must update focusNode to the target node in the usual case");
+ assert_equals(selection.focusOffset, offset,
+ "extend() must update focusOffset to the target offset in the usual case");
+
+ var expectedDirection;
+ var range = document.createRange();
+ range.setStart(oldAnchorNode, oldAnchorOffset);
+ range.setEnd(oldAnchorNode, oldAnchorOffset);
+ if (range.comparePoint(node, offset) >= 0) {
+ expectedDirection = "forwards";
+ } else {
+ expectedDirection = "backwards";
+ }
+ assert_equals(getSelectionDirection(), expectedDirection,
+ "extend() must set direction appropriately in the usual case");
+}
+
+// Also test a selection with no ranges
+testRanges.unshift("[]");
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+ for (var j = 0; j < testPoints.length; j++) {
+ tests.push([
+ "extend() forwards with range " + i + " " + testRanges[i] + " and point " + j + " " + testPoints[j],
+ eval(testRanges[i]),
+ eval(testPoints[j])
+ ]);
+ }
+}
+generate_tests(testExtendForwards, tests);
+
+// Copy-pasted with "forwards" changed to "backwards" :/
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+ for (var j = 0; j < testPoints.length; j++) {
+ tests.push([
+ "extend() backwards with range " + i + " " + testRanges[i] + " and point " + j + " " + testPoints[j],
+ eval(testRanges[i]),
+ eval(testPoints[j])
+ ]);
+ }
+}
+generate_tests(testExtendBackwards, tests);
+
+// Let's be tidy.
+testDiv.style.display = "none";
+</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/getRangeAt.html Tue Oct 11 15:35:33 2011 -0600
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>The getRangeAt method</title>
+<div id=log></div>
+<script src=http://w3c-test.org/resources/testharness.js></script>
+<script>
+test(function() {
+ var sel = getSelection();
+ var range = document.createRange();
+ sel.addRange(range);
+ assert_throws("INDEX_SIZE_ERR", function() { sel.getRangeAt(-1); })
+ assert_throws("INDEX_SIZE_ERR", function() { sel.getRangeAt(1); })
+});
+</script>