Test Selection.deleteFromDocument
authorAryeh Gregor <AryehGregor+gitcommit@gmail.com>
Thu, 10 Nov 2011 12:50:31 -0700
changeset 675 9860f92c4b82
parent 674 9008a98bdbc9
child 676 0c4c345c2c63
Test Selection.deleteFromDocument

As usual, Gecko is the sanest implementation. The spec seems correct in
this case, although Gecko behaves weirdly in some cases with collapsed
selections.
selecttest/common.js
selecttest/deleteFromDocument.html
selecttest/test-iframe.html
--- a/selecttest/common.js	Wed Nov 09 12:42:35 2011 -0700
+++ b/selecttest/common.js	Thu Nov 10 12:50:31 2011 -0700
@@ -118,7 +118,7 @@
 		"[document.documentElement, 0, document.documentElement, 2]",
 		"[document.documentElement, 1, document.documentElement, 2]",
 		"[document.head, 1, document.head, 1]",
-		"[document.body, 4, document.body, 5]",
+		"[document.body, 0, document.body, 1]",
 		"[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
 		"[foreignDoc.head, 1, foreignDoc.head, 1]",
 		"[foreignDoc.body, 0, foreignDoc.body, 0]",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/deleteFromDocument.html	Thu Nov 10 12:50:31 2011 -0700
@@ -0,0 +1,97 @@
+<!doctype html>
+<title>Selection.deleteFromDocument() tests</title>
+<link rel=author title="Aryeh Gregor" [email protected]>
+<p>To debug test failures, add a query parameter with the test id (like
+"?5").  Only that test will be run.  Then you can look at the resulting
+iframes in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+<script>
+"use strict";
+
+// We need to use explicit_done, because in Chrome 16 dev and Opera 12.00, the
+// second iframe doesn't block the load event -- even though it is added before
+// the load event.
+setup({explicit_done: true});
+
+// Specified by WebIDL
+test(function() {
+	assert_equals(Selection.prototype.deleteFromDocument.length, 0,
+		"Selection.prototype.deleteFromDocument.length must equal 0");
+}, "Selection.prototype.deleteFromDocument.length must equal 0");
+
+testDiv.parentNode.removeChild(testDiv);
+
+// Test an empty selection too
+testRanges.unshift("empty");
+
+var actualIframe = document.createElement("iframe");
+
+var expectedIframe = document.createElement("iframe");
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+	expectedIframe.onload = function() {
+		for (var i = 0; i < testRanges.length; i++) {
+			if (location.search && i != Number(location.search)) {
+				continue;
+			}
+
+			test(function() {
+				initializeIframe(actualIframe, testRanges[i]);
+				initializeIframe(expectedIframe, testRanges[i]);
+
+				var actualRange = actualIframe.contentWindow.testRange;
+				var expectedRange = expectedIframe.contentWindow.testRange;
+
+				assert_equals(actualIframe.contentWindow.unexpectedException, null,
+					"Unexpected exception thrown when setting up Range for actual deleteFromDocument");
+				assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+					"Unexpected exception thrown when setting up Range for simulated deleteFromDocument");
+
+				actualIframe.contentWindow.getSelection().removeAllRanges();
+				if (testRanges[i] != "empty") {
+					assert_equals(typeof actualRange, "object",
+						"Range produced in actual iframe must be an object");
+					assert_equals(typeof expectedRange, "object",
+						"Range produced in expected iframe must be an object");
+					assert_true(actualRange instanceof actualIframe.contentWindow.Range,
+						"Range produced in actual iframe must be instanceof Range");
+					assert_true(expectedRange instanceof expectedIframe.contentWindow.Range,
+						"Range produced in expected iframe must be instanceof Range");
+					actualIframe.contentWindow.getSelection().addRange(actualIframe.contentWindow.testRange);
+					expectedIframe.contentWindow.testRange.deleteContents();
+				}
+				actualIframe.contentWindow.getSelection().deleteFromDocument();
+
+				assertNodesEqual(actualIframe.contentDocument, expectedIframe.contentDocument, "DOM contents");
+			}, "Range " + i + ": " + testRanges[i]);
+		}
+		actualIframe.style.display = "none";
+		expectedIframe.style.display = "none";
+		done();
+	};
+	expectedIframe.src = "test-iframe.html";
+	document.body.appendChild(expectedIframe);
+	referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+};
+actualIframe.src = "test-iframe.html";
+document.body.appendChild(actualIframe);
+
+function initializeIframe(iframe, endpoints) {
+	while (iframe.contentDocument.firstChild) {
+		iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+	}
+	iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+	iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+	iframe.contentWindow.setupRangeTests();
+	if (endpoints != "empty") {
+		iframe.contentWindow.testRangeInput = endpoints;
+		iframe.contentWindow.run();
+	}
+}
+</script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/selecttest/test-iframe.html	Thu Nov 10 12:50:31 2011 -0700
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>Selection test iframe</title>
+<link rel=author title="Aryeh Gregor" [email protected]>
+<body>
+<script src=common.js></script>
+<script>
+"use strict";
+
+// This script only exists because we want to evaluate the range endpoints
+// in each iframe using that iframe's local variables set up by common.js.  It
+// just creates a range with the endpoints given by
+// eval(window.testRangeInput), and assigns the result to window.testRange.  If
+// there's an exception, it's assigned to window.unexpectedException.
+// Everything else is to be done by the script that created the iframe.
+window.unexpectedException = null;
+
+function run() {
+	window.unexpectedException = null;
+	try {
+		window.testRange = rangeFromEndpoints(eval(window.testRangeInput));
+	} catch(e) {
+		window.unexpectedException = e;
+	}
+}
+
+// Remove the scripts so they don't run repeatedly when the iframe is
+// reinitialized
+[].forEach.call(document.querySelectorAll("script"), function(script) {
+	script.parentNode.removeChild(script);
+});
+
+testDiv.style.display = "none";
+</script>