mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 751842 part 6 - Import editing spec tests; r=Ms2ger
This commit is contained in:
parent
c2de3df2b1
commit
14e6b7e0df
@ -9,11 +9,14 @@ VPATH = @srcdir@
|
||||
relativesrcdir = dom/imported-tests
|
||||
|
||||
DIRS = \
|
||||
failures/editing/conformancetest \
|
||||
failures/editing/selecttest \
|
||||
failures/webapps/WebStorage/tests/submissions/Ms2ger \
|
||||
failures/webapps/WebStorage/tests/submissions/Infraware \
|
||||
failures/webapps/DOMCore/tests/submissions/Opera \
|
||||
$(NULL)
|
||||
|
||||
include $(srcdir)/editing.mk
|
||||
include $(srcdir)/html.mk
|
||||
include $(srcdir)/webapps.mk
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
3
dom/imptests/editing.mk
Normal file
3
dom/imptests/editing.mk
Normal file
@ -0,0 +1,3 @@
|
||||
DIRS += \
|
||||
editing/ \
|
||||
$(NULL)
|
2
dom/imptests/editing.txt
Normal file
2
dom/imptests/editing.txt
Normal file
@ -0,0 +1,2 @@
|
||||
https://dvcs.w3.org/hg/editing|editing
|
||||
|
28
dom/imptests/editing/Makefile.in
Normal file
28
dom/imptests/editing/Makefile.in
Normal file
@ -0,0 +1,28 @@
|
||||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
|
||||
DEPTH = ../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/editing
|
||||
|
||||
DIRS = \
|
||||
css \
|
||||
conformancetest \
|
||||
selecttest \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
$(NULL)
|
||||
|
||||
_TESTS += \
|
||||
implementation.js \
|
||||
tests.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
26
dom/imptests/editing/conformancetest/Makefile.in
Normal file
26
dom/imptests/editing/conformancetest/Makefile.in
Normal file
@ -0,0 +1,26 @@
|
||||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
|
||||
DEPTH = ../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/editing/conformancetest
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
test_runtest.html \
|
||||
test_event.html \
|
||||
$(NULL)
|
||||
|
||||
_TESTS += \
|
||||
data.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
30067
dom/imptests/editing/conformancetest/data.js
Normal file
30067
dom/imptests/editing/conformancetest/data.js
Normal file
File diff suppressed because it is too large
Load Diff
289
dom/imptests/editing/conformancetest/test_event.html
Normal file
289
dom/imptests/editing/conformancetest/test_event.html
Normal file
@ -0,0 +1,289 @@
|
||||
<!doctype html>
|
||||
<title>Editing event tests</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id=test></div>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var div = document.querySelector("#test");
|
||||
add_completion_callback(function() { div.parentNode.removeChild(div) });
|
||||
|
||||
function copyEvent(e) {
|
||||
var ret = {};
|
||||
ret.original = e;
|
||||
["type", "target", "currentTarget", "eventPhase", "bubbles", "cancelable",
|
||||
"defaultPrevented", "isTrusted", "command", "value"].forEach(function(k) {
|
||||
ret[k] = e[k];
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{
|
||||
name: "Simple editable div",
|
||||
html: "<div contenteditable>foo<b>bar</b>baz</div>",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("b").firstChild, 0);
|
||||
range.setEnd(div.querySelector("b"), 1);
|
||||
},
|
||||
target: function() { return div.firstChild },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "Editable b",
|
||||
html: "foo<b contenteditable>bar</b>baz",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("b").firstChild, 0);
|
||||
range.setEnd(div.querySelector("b"), 1);
|
||||
},
|
||||
target: function() { return div.querySelector("b") },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "No editable content",
|
||||
html: "foo<b>bar</b>baz",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("b").firstChild, 0);
|
||||
range.setEnd(div.querySelector("b"), 1);
|
||||
},
|
||||
target: function() { return null },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "Partially-selected editable content",
|
||||
html: "foo<b contenteditable>bar</b>baz",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("b").firstChild, 0);
|
||||
range.setEnd(div, 3);
|
||||
},
|
||||
target: function() { return null },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "Selection spans two editing hosts",
|
||||
html: "<div contenteditable>foo</div><div contenteditable>bar</div>",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("div").firstChild, 2);
|
||||
range.setEnd(div.querySelector("div + div").firstChild, 1);
|
||||
},
|
||||
target: function() { return null },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "Selection includes two editing hosts",
|
||||
html: "foo<div contenteditable>bar</div>baz<div contenteditable>quz</div>qoz",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.firstChild, 2);
|
||||
range.setEnd(div.lastChild, 1);
|
||||
},
|
||||
target: function() { return null },
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
name: "Changing selection from handler",
|
||||
html: "<div contenteditable>foo</div><div contenteditable>bar</div>",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("div").firstChild, 0);
|
||||
range.setEnd(div.querySelector("div").firstChild, 3);
|
||||
},
|
||||
target: function() { return div.firstChild },
|
||||
finalTarget: function() { return div.lastChild },
|
||||
beforeInputAction: function() {
|
||||
getSelection().removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(div.querySelector("div + div").firstChild, 0);
|
||||
range.setEnd(div.querySelector("div + div").firstChild, 3);
|
||||
getSelection().addRange(range);
|
||||
},
|
||||
command: "bold",
|
||||
value: "",
|
||||
},
|
||||
];
|
||||
|
||||
var commandTests = {
|
||||
backColor: ["green"],
|
||||
createLink: ["http://www.w3.org/community/editing/"],
|
||||
fontName: ["serif", "Helvetica"],
|
||||
fontSize: ["6", "15px"],
|
||||
foreColor: ["green"],
|
||||
hiliteColor: ["green"],
|
||||
italic: [],
|
||||
removeFormat: [],
|
||||
strikeThrough: [],
|
||||
subscript: [],
|
||||
superscript: [],
|
||||
underline: [],
|
||||
unlink: [],
|
||||
delete: [],
|
||||
formatBlock: ["p"],
|
||||
forwardDelete: [],
|
||||
indent: [],
|
||||
insertHorizontalRule: ["id"],
|
||||
insertHTML: ["<b>hi</b>"],
|
||||
insertImage: ["http://example.com/some-image"],
|
||||
insertLineBreak: [],
|
||||
insertOrderedList: [],
|
||||
insertParagraph: [],
|
||||
insertText: ["abc"],
|
||||
insertUnorderedList: [],
|
||||
justifyCenter: [],
|
||||
justifyFull: [],
|
||||
justifyLeft: [],
|
||||
justifyRight: [],
|
||||
outdent: [],
|
||||
redo: [],
|
||||
selectAll: [],
|
||||
styleWithCSS: [],
|
||||
undo: [],
|
||||
useCSS: [],
|
||||
};
|
||||
|
||||
Object.keys(commandTests).forEach(function(command) {
|
||||
commandTests[command] = ["", "quasit"].concat(commandTests[command]);
|
||||
commandTests[command].forEach(function(value) {
|
||||
tests.push({
|
||||
name: "Command " + command + ", value " + format_value(value),
|
||||
html: "<div contenteditable>foo<b>bar</b>baz</div>",
|
||||
initRange: function(range) {
|
||||
range.setStart(div.querySelector("b").firstChild, 0);
|
||||
range.setEnd(div.querySelector("b"), 1);
|
||||
},
|
||||
target: function() {
|
||||
return ["redo", "selectAll", "styleWithCSS", "undo", "useCSS"]
|
||||
.indexOf(command) == -1 ? div.firstChild : null;
|
||||
},
|
||||
command: command,
|
||||
value: value,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tests.forEach(function(obj) {
|
||||
[true, false].forEach(function(cancel) {
|
||||
// Kill all event handlers first
|
||||
var newDiv = div.cloneNode(false);
|
||||
div.parentNode.insertBefore(newDiv, div);
|
||||
div.parentNode.removeChild(div);
|
||||
div = newDiv;
|
||||
|
||||
div.innerHTML = obj.html;
|
||||
|
||||
var originalContents = div.cloneNode(true);
|
||||
|
||||
getSelection().removeAllRanges();
|
||||
var range = document.createRange();
|
||||
obj.initRange(range);
|
||||
getSelection().addRange(range);
|
||||
|
||||
var target = obj.target();
|
||||
var finalTarget = "finalTarget" in obj ? obj.finalTarget() : target;
|
||||
var command = obj.command;
|
||||
var value = obj.value;
|
||||
|
||||
var beforeInputEvents = [];
|
||||
var inputEvents = [];
|
||||
div.addEventListener("beforeinput", function(e) {
|
||||
var copied = copyEvent(e);
|
||||
copied.inputEventsLength = inputEvents.length;
|
||||
beforeInputEvents.push(copied);
|
||||
if (cancel) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if ("beforeInputAction" in obj) {
|
||||
obj.beforeInputAction();
|
||||
}
|
||||
});
|
||||
div.addEventListener("input", function(e) { inputEvents.push(copyEvent(e)) });
|
||||
|
||||
// Uncomment this code instead of the execCommand() to make all the
|
||||
// tests pass, as a sanity check
|
||||
//var e = new Event("beforeinput", {bubbles: true, cancelable: true});
|
||||
//e.command = command;
|
||||
//e.value = value;
|
||||
//var ret = target ? target.dispatchEvent(e) : false;
|
||||
//if (ret) {
|
||||
// var e = new Event("input", {bubbles: true});
|
||||
// e.command = command;
|
||||
// e.value = value;
|
||||
// finalTarget.dispatchEvent(e);
|
||||
//}
|
||||
|
||||
var exception = null;
|
||||
try {
|
||||
document.execCommand(command, false, value);
|
||||
} catch(e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
test(function() {
|
||||
assert_equals(exception, null, "Unexpected exception");
|
||||
}, obj.name + ": execCommand() must not throw, "
|
||||
+ (cancel ? "canceled" : "uncanceled"));
|
||||
|
||||
test(function() {
|
||||
assert_equals(beforeInputEvents.length, target ? 1 : 0,
|
||||
"number of beforeinput events fired");
|
||||
if (beforeInputEvents.length == 0) {
|
||||
assert_equals(inputEvents.length, 0, "number of input events fired");
|
||||
return;
|
||||
}
|
||||
var e = beforeInputEvents[0];
|
||||
assert_equals(e.inputEventsLength, 0, "number of input events fired");
|
||||
assert_equals(e.type, "beforeinput", "event.type");
|
||||
assert_equals(e.target, target, "event.target");
|
||||
assert_equals(e.currentTarget, div, "event.currentTarget");
|
||||
assert_equals(e.eventPhase, Event.BUBBLING_PHASE, "event.eventPhase");
|
||||
assert_equals(e.bubbles, true, "event.bubbles");
|
||||
assert_equals(e.cancelable, true, "event.cancelable");
|
||||
assert_equals(e.defaultPrevented, false, "event.defaultPrevented");
|
||||
assert_equals(e.command, command, "e.command");
|
||||
assert_equals(e.value, value, "e.value");
|
||||
assert_own_property(window, "EditingBeforeInputEvent",
|
||||
"window.EditingBeforeInputEvent must exist");
|
||||
assert_equals(Object.getPrototypeOf(e.original),
|
||||
EditingBeforeInputEvent.prototype,
|
||||
"event prototype");
|
||||
assert_true(originalContents.isEqualNode(div),
|
||||
"div contents not yet changed");
|
||||
assert_equals(e.isTrusted, true, "event.isTrusted");
|
||||
}, obj.name + ": beforeinput event, " + (cancel ? "canceled" : "uncanceled"));
|
||||
|
||||
test(function() {
|
||||
assert_equals(inputEvents.length, target && !cancel ? 1 : 0,
|
||||
"number of input events fired");
|
||||
if (!target || cancel) {
|
||||
assert_true(originalContents.isEqualNode(div),
|
||||
"div contents must not be changed");
|
||||
return;
|
||||
}
|
||||
var e = inputEvents[0];
|
||||
assert_equals(e.type, "input", "event.type");
|
||||
assert_equals(e.target, finalTarget, "event.target");
|
||||
assert_equals(e.currentTarget, div, "event.currentTarget");
|
||||
assert_equals(e.eventPhase, Event.BUBBLING_PHASE, "event.eventPhase");
|
||||
assert_equals(e.bubbles, true, "event.bubbles");
|
||||
assert_equals(e.cancelable, false, "event.cancelable");
|
||||
assert_equals(e.defaultPrevented, false, "event.defaultPrevented");
|
||||
assert_equals(e.command, command, "e.command");
|
||||
assert_equals(e.value, value, "e.value");
|
||||
assert_own_property(window, "EditingInputEvent",
|
||||
"window.EditingInputEvent must exist");
|
||||
assert_equals(Object.getPrototypeOf(e.original),
|
||||
EditingInputEvent.prototype,
|
||||
"event prototype");
|
||||
assert_equals(e.isTrusted, true, "event.isTrusted");
|
||||
}, obj.name + ": input event, " + (cancel ? "canceled" : "uncanceled"));
|
||||
});
|
||||
});
|
||||
|
||||
// Thanks, Gecko.
|
||||
document.body.bgColor = "";
|
||||
</script>
|
48
dom/imptests/editing/conformancetest/test_runtest.html
Normal file
48
dom/imptests/editing/conformancetest/test_runtest.html
Normal file
@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<link rel=stylesheet href=../css/reset.css>
|
||||
<title>HTML editing conformance tests</title>
|
||||
<p>See the <a href=editing.html#tests>Tests</a> section of the specification
|
||||
for documentation.
|
||||
|
||||
<p id=timing></p>
|
||||
|
||||
<div id=log></div>
|
||||
|
||||
<div id=test-container></div>
|
||||
|
||||
<script src=../implementation.js></script>
|
||||
<script>var testsJsLibraryOnly = true</script>
|
||||
<script src=../tests.js></script>
|
||||
<script src=data.js></script>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
runTests();
|
||||
|
||||
function runTests() {
|
||||
var startTime = Date.now();
|
||||
|
||||
// Make document.body.innerHTML more tidy by removing unnecessary things.
|
||||
// We can't remove the testharness.js script, because at the time of this
|
||||
// writing, for some reason that stops it from adding appropriate CSS.
|
||||
[].forEach.call(document.querySelectorAll("script"), function(node) {
|
||||
if (!/testharness\.js$/.test(node.src)) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
});
|
||||
|
||||
browserTests.forEach(runConformanceTest);
|
||||
|
||||
document.getElementById("test-container").parentNode
|
||||
.removeChild(document.getElementById("test-container"));
|
||||
|
||||
var elapsed = Math.round(Date.now() - startTime)/1000;
|
||||
document.getElementById("timing").textContent =
|
||||
"Time elapsed: " + Math.floor(elapsed/60) + ":"
|
||||
+ ((elapsed % 60) < 10 ? "0" : "")
|
||||
+ (elapsed % 60).toFixed(3) + " min.";
|
||||
}
|
||||
</script>
|
24
dom/imptests/editing/css/Makefile.in
Normal file
24
dom/imptests/editing/css/Makefile.in
Normal file
@ -0,0 +1,24 @@
|
||||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
|
||||
DEPTH = ../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/editing/css
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
$(NULL)
|
||||
|
||||
_TESTS += \
|
||||
reset.css \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
27
dom/imptests/editing/css/reset.css
Normal file
27
dom/imptests/editing/css/reset.css
Normal file
@ -0,0 +1,27 @@
|
||||
/* Make sure various CSS values are what are expected, so that tests work
|
||||
* right. */
|
||||
body { font-family: serif }
|
||||
/* http://www.w3.org/Bugs/Public/show_bug.cgi?id=12154
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=589124
|
||||
* https://bugs.webkit.org/show_bug.cgi?id=56400 */
|
||||
b, strong { font-weight: bold }
|
||||
.bold { font-weight: bold }
|
||||
.notbold { font-weight: normal }
|
||||
.underline { text-decoration: underline }
|
||||
.line-through { text-decoration: line-through }
|
||||
.underline-and-line-through { text-decoration: underline line-through }
|
||||
#purple { color: purple }
|
||||
/* https://bugs.webkit.org/show_bug.cgi?id=56670 */
|
||||
dfn { font-style: italic }
|
||||
/* Opera has weird default blockquote style */
|
||||
blockquote { margin: 1em 40px }
|
||||
/* Some tests assume links are blue, for the sake of argument, but they aren't
|
||||
* blue in any browser. And :visited definitely isn't blue, except in engines
|
||||
* like Gecko that lie.
|
||||
*
|
||||
* This should really be #00e, probably. See:
|
||||
* http://www.w3.org/Bugs/Public/show_bug.cgi?id=13330 */
|
||||
:link, :visited { color: blue }
|
||||
/* http://www.w3.org/Bugs/Public/show_bug.cgi?id=14066
|
||||
* https://bugs.webkit.org/show_bug.cgi?id=68392 */
|
||||
quasit { text-align: inherit }
|
8436
dom/imptests/editing/implementation.js
Normal file
8436
dom/imptests/editing/implementation.js
Normal file
File diff suppressed because it is too large
Load Diff
37
dom/imptests/editing/selecttest/Makefile.in
Normal file
37
dom/imptests/editing/selecttest/Makefile.in
Normal file
@ -0,0 +1,37 @@
|
||||
# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
|
||||
|
||||
DEPTH = ../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/editing/selecttest
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
test_addRange.html \
|
||||
test_collapse.html \
|
||||
test_collapseToStartEnd.html \
|
||||
test_deleteFromDocument.html \
|
||||
test_Document-open.html \
|
||||
test_extend.html \
|
||||
test_getRangeAt.html \
|
||||
test_getSelection.html \
|
||||
test_interfaces.html \
|
||||
test_isCollapsed.html \
|
||||
test_removeAllRanges.html \
|
||||
test_selectAllChildren.html \
|
||||
$(NULL)
|
||||
|
||||
_TESTS += \
|
||||
common.js \
|
||||
test-iframe.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
952
dom/imptests/editing/selecttest/common.js
Normal file
952
dom/imptests/editing/selecttest/common.js
Normal file
@ -0,0 +1,952 @@
|
||||
"use strict";
|
||||
// TODO: iframes, contenteditable/designMode
|
||||
|
||||
// Everything is done in functions in this test harness, so we have to declare
|
||||
// all the variables before use to make sure they can be reused.
|
||||
var selection;
|
||||
var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
|
||||
foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement,
|
||||
detachedXmlElement, detachedTextNode, foreignTextNode,
|
||||
detachedForeignTextNode, xmlTextNode, detachedXmlTextNode,
|
||||
processingInstruction, detachedProcessingInstruction, comment,
|
||||
detachedComment, foreignComment, detachedForeignComment, xmlComment,
|
||||
detachedXmlComment, docfrag, foreignDocfrag, xmlDocfrag, doctype,
|
||||
foreignDoctype, xmlDoctype;
|
||||
var testRanges, testPoints, testNodes;
|
||||
|
||||
function setupRangeTests() {
|
||||
selection = getSelection();
|
||||
testDiv = document.querySelector("#test");
|
||||
if (testDiv) {
|
||||
testDiv.parentNode.removeChild(testDiv);
|
||||
}
|
||||
testDiv = document.createElement("div");
|
||||
testDiv.id = "test";
|
||||
document.body.insertBefore(testDiv, document.body.firstChild);
|
||||
// Test some diacritics, to make sure browsers are using code units here
|
||||
// and not something like grapheme clusters.
|
||||
testDiv.innerHTML = "<p id=a>Äb̈c̈d̈ëf̈g̈ḧ\n"
|
||||
+ "<p id=b style=display:none>Ijklmnop\n"
|
||||
+ "<p id=c>Qrstuvwx"
|
||||
+ "<p id=d style=display:none>Yzabcdef"
|
||||
+ "<p id=e style=display:none>Ghijklmn";
|
||||
paras = testDiv.querySelectorAll("p");
|
||||
|
||||
detachedDiv = document.createElement("div");
|
||||
detachedPara1 = document.createElement("p");
|
||||
detachedPara1.appendChild(document.createTextNode("Opqrstuv"));
|
||||
detachedPara2 = document.createElement("p");
|
||||
detachedPara2.appendChild(document.createTextNode("Wxyzabcd"));
|
||||
detachedDiv.appendChild(detachedPara1);
|
||||
detachedDiv.appendChild(detachedPara2);
|
||||
|
||||
// Opera doesn't automatically create a doctype for a new HTML document,
|
||||
// contrary to spec. It also doesn't let you add doctypes to documents
|
||||
// after the fact through any means I've tried. So foreignDoc in Opera
|
||||
// will have no doctype, foreignDoctype will be null, and Opera will fail
|
||||
// some tests somewhat mysteriously as a result.
|
||||
foreignDoc = document.implementation.createHTMLDocument("");
|
||||
foreignPara1 = foreignDoc.createElement("p");
|
||||
foreignPara1.appendChild(foreignDoc.createTextNode("Efghijkl"));
|
||||
foreignPara2 = foreignDoc.createElement("p");
|
||||
foreignPara2.appendChild(foreignDoc.createTextNode("Mnopqrst"));
|
||||
foreignDoc.body.appendChild(foreignPara1);
|
||||
foreignDoc.body.appendChild(foreignPara2);
|
||||
|
||||
// Now we get to do really silly stuff, which nobody in the universe is
|
||||
// ever going to actually do, but the spec defines behavior, so too bad.
|
||||
// Testing is fun!
|
||||
xmlDoctype = document.implementation.createDocumentType("qorflesnorf", "abcde", "x\"'y");
|
||||
xmlDoc = document.implementation.createDocument(null, null, xmlDoctype);
|
||||
detachedXmlElement = xmlDoc.createElement("everyone-hates-hyphenated-element-names");
|
||||
detachedTextNode = document.createTextNode("Uvwxyzab");
|
||||
detachedForeignTextNode = foreignDoc.createTextNode("Cdefghij");
|
||||
detachedXmlTextNode = xmlDoc.createTextNode("Klmnopqr");
|
||||
// PIs only exist in XML documents, so don't bother with document or
|
||||
// foreignDoc.
|
||||
detachedProcessingInstruction = xmlDoc.createProcessingInstruction("whippoorwill", "chirp chirp chirp");
|
||||
detachedComment = document.createComment("Stuvwxyz");
|
||||
// Hurrah, we finally got to "z" at the end!
|
||||
detachedForeignComment = foreignDoc.createComment("אריה יהודה");
|
||||
detachedXmlComment = xmlDoc.createComment("בן חיים אליעזר");
|
||||
|
||||
// We should also test with document fragments that actually contain stuff
|
||||
// . . . but, maybe later.
|
||||
docfrag = document.createDocumentFragment();
|
||||
foreignDocfrag = foreignDoc.createDocumentFragment();
|
||||
xmlDocfrag = xmlDoc.createDocumentFragment();
|
||||
|
||||
xmlElement = xmlDoc.createElement("igiveuponcreativenames");
|
||||
xmlTextNode = xmlDoc.createTextNode("do re mi fa so la ti");
|
||||
xmlElement.appendChild(xmlTextNode);
|
||||
processingInstruction = xmlDoc.createProcessingInstruction("somePI", 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?');
|
||||
xmlDoc.appendChild(xmlElement);
|
||||
xmlDoc.appendChild(processingInstruction);
|
||||
xmlComment = xmlDoc.createComment("I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt");
|
||||
xmlDoc.appendChild(xmlComment);
|
||||
|
||||
comment = document.createComment("Alphabet soup?");
|
||||
testDiv.appendChild(comment);
|
||||
|
||||
foreignComment = foreignDoc.createComment('"Commenter" and "commentator" mean different things. I\'ve seen non-native speakers trip up on this.');
|
||||
foreignDoc.appendChild(foreignComment);
|
||||
foreignTextNode = foreignDoc.createTextNode("I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.");
|
||||
foreignDoc.body.appendChild(foreignTextNode);
|
||||
|
||||
doctype = document.doctype;
|
||||
foreignDoctype = foreignDoc.doctype;
|
||||
|
||||
testRanges = [
|
||||
// Various ranges within the text node children of different
|
||||
// paragraphs. All should be valid.
|
||||
"[paras[0].firstChild, 0, paras[0].firstChild, 0]",
|
||||
"[paras[0].firstChild, 0, paras[0].firstChild, 1]",
|
||||
"[paras[0].firstChild, 2, paras[0].firstChild, 8]",
|
||||
"[paras[0].firstChild, 2, paras[0].firstChild, 9]",
|
||||
"[paras[1].firstChild, 0, paras[1].firstChild, 0]",
|
||||
"[paras[1].firstChild, 0, paras[1].firstChild, 1]",
|
||||
"[paras[1].firstChild, 2, paras[1].firstChild, 8]",
|
||||
"[paras[1].firstChild, 2, paras[1].firstChild, 9]",
|
||||
"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
|
||||
"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
|
||||
"[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
|
||||
"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
|
||||
"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
|
||||
"[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
|
||||
// Now try testing some elements, not just text nodes.
|
||||
"[document.documentElement, 0, document.documentElement, 1]",
|
||||
"[document.documentElement, 0, document.documentElement, 2]",
|
||||
"[document.documentElement, 1, document.documentElement, 2]",
|
||||
"[document.head, 1, document.head, 1]",
|
||||
"[document.body, 0, document.body, 1]",
|
||||
"[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
|
||||
"[foreignDoc.head, 1, foreignDoc.head, 1]",
|
||||
"[foreignDoc.body, 0, foreignDoc.body, 0]",
|
||||
"[paras[0], 0, paras[0], 0]",
|
||||
"[paras[0], 0, paras[0], 1]",
|
||||
"[detachedPara1, 0, detachedPara1, 0]",
|
||||
"[detachedPara1, 0, detachedPara1, 1]",
|
||||
// Now try some ranges that span elements.
|
||||
"[paras[0].firstChild, 0, paras[1].firstChild, 0]",
|
||||
"[paras[0].firstChild, 0, paras[1].firstChild, 8]",
|
||||
"[paras[0].firstChild, 3, paras[3], 1]",
|
||||
// How about something that spans a node and its descendant?
|
||||
"[paras[0], 0, paras[0].firstChild, 7]",
|
||||
"[testDiv, 2, paras[4], 1]",
|
||||
"[testDiv, 1, paras[2].firstChild, 5]",
|
||||
"[document.documentElement, 1, document.body, 0]",
|
||||
"[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
|
||||
// Then a few more interesting things just for good measure.
|
||||
"[document, 0, document, 1]",
|
||||
"[document, 0, document, 2]",
|
||||
"[document, 1, document, 2]",
|
||||
"[testDiv, 0, comment, 5]",
|
||||
"[paras[2].firstChild, 4, comment, 2]",
|
||||
"[paras[3], 1, comment, 8]",
|
||||
"[foreignDoc, 0, foreignDoc, 0]",
|
||||
"[foreignDoc, 1, foreignComment, 2]",
|
||||
"[foreignDoc.body, 0, foreignTextNode, 36]",
|
||||
"[xmlDoc, 0, xmlDoc, 0]",
|
||||
// Opera 11 crashes if you extractContents() a range that ends at offset
|
||||
// zero in a comment. Comment out this line to run the tests successfully.
|
||||
"[xmlDoc, 1, xmlComment, 0]",
|
||||
"[detachedTextNode, 0, detachedTextNode, 8]",
|
||||
"[detachedForeignTextNode, 7, detachedForeignTextNode, 7]",
|
||||
"[detachedForeignTextNode, 0, detachedForeignTextNode, 8]",
|
||||
"[detachedXmlTextNode, 7, detachedXmlTextNode, 7]",
|
||||
"[detachedXmlTextNode, 0, detachedXmlTextNode, 8]",
|
||||
"[detachedComment, 3, detachedComment, 4]",
|
||||
"[detachedComment, 5, detachedComment, 5]",
|
||||
"[detachedForeignComment, 0, detachedForeignComment, 1]",
|
||||
"[detachedForeignComment, 4, detachedForeignComment, 4]",
|
||||
"[detachedXmlComment, 2, detachedXmlComment, 6]",
|
||||
"[docfrag, 0, docfrag, 0]",
|
||||
"[foreignDocfrag, 0, foreignDocfrag, 0]",
|
||||
"[xmlDocfrag, 0, xmlDocfrag, 0]",
|
||||
];
|
||||
|
||||
testPoints = [
|
||||
// Various positions within the page, some invalid. Remember that
|
||||
// paras[0] is visible, and paras[1] is display: none.
|
||||
"[paras[0].firstChild, -1]",
|
||||
"[paras[0].firstChild, 0]",
|
||||
"[paras[0].firstChild, 1]",
|
||||
"[paras[0].firstChild, 2]",
|
||||
"[paras[0].firstChild, 8]",
|
||||
"[paras[0].firstChild, 9]",
|
||||
"[paras[0].firstChild, 10]",
|
||||
"[paras[0].firstChild, 65535]",
|
||||
"[paras[1].firstChild, -1]",
|
||||
"[paras[1].firstChild, 0]",
|
||||
"[paras[1].firstChild, 1]",
|
||||
"[paras[1].firstChild, 2]",
|
||||
"[paras[1].firstChild, 8]",
|
||||
"[paras[1].firstChild, 9]",
|
||||
"[paras[1].firstChild, 10]",
|
||||
"[paras[1].firstChild, 65535]",
|
||||
"[detachedPara1.firstChild, 0]",
|
||||
"[detachedPara1.firstChild, 1]",
|
||||
"[detachedPara1.firstChild, 8]",
|
||||
"[detachedPara1.firstChild, 9]",
|
||||
"[foreignPara1.firstChild, 0]",
|
||||
"[foreignPara1.firstChild, 1]",
|
||||
"[foreignPara1.firstChild, 8]",
|
||||
"[foreignPara1.firstChild, 9]",
|
||||
// Now try testing some elements, not just text nodes.
|
||||
"[document.documentElement, -1]",
|
||||
"[document.documentElement, 0]",
|
||||
"[document.documentElement, 1]",
|
||||
"[document.documentElement, 2]",
|
||||
"[document.documentElement, 7]",
|
||||
"[document.head, 1]",
|
||||
"[document.body, 3]",
|
||||
"[foreignDoc.documentElement, 0]",
|
||||
"[foreignDoc.documentElement, 1]",
|
||||
"[foreignDoc.head, 0]",
|
||||
"[foreignDoc.body, 1]",
|
||||
"[paras[0], 0]",
|
||||
"[paras[0], 1]",
|
||||
"[paras[0], 2]",
|
||||
"[paras[1], 0]",
|
||||
"[paras[1], 1]",
|
||||
"[paras[1], 2]",
|
||||
"[detachedPara1, 0]",
|
||||
"[detachedPara1, 1]",
|
||||
"[testDiv, 0]",
|
||||
"[testDiv, 3]",
|
||||
// Then a few more interesting things just for good measure.
|
||||
"[document, -1]",
|
||||
"[document, 0]",
|
||||
"[document, 1]",
|
||||
"[document, 2]",
|
||||
"[document, 3]",
|
||||
"[comment, -1]",
|
||||
"[comment, 0]",
|
||||
"[comment, 4]",
|
||||
"[comment, 96]",
|
||||
"[foreignDoc, 0]",
|
||||
"[foreignDoc, 1]",
|
||||
"[foreignComment, 2]",
|
||||
"[foreignTextNode, 0]",
|
||||
"[foreignTextNode, 36]",
|
||||
"[xmlDoc, -1]",
|
||||
"[xmlDoc, 0]",
|
||||
"[xmlDoc, 1]",
|
||||
"[xmlDoc, 5]",
|
||||
"[xmlComment, 0]",
|
||||
"[xmlComment, 4]",
|
||||
"[processingInstruction, 0]",
|
||||
"[processingInstruction, 5]",
|
||||
"[processingInstruction, 9]",
|
||||
"[detachedTextNode, 0]",
|
||||
"[detachedTextNode, 8]",
|
||||
"[detachedForeignTextNode, 0]",
|
||||
"[detachedForeignTextNode, 8]",
|
||||
"[detachedXmlTextNode, 0]",
|
||||
"[detachedXmlTextNode, 8]",
|
||||
"[detachedProcessingInstruction, 12]",
|
||||
"[detachedComment, 3]",
|
||||
"[detachedComment, 5]",
|
||||
"[detachedForeignComment, 0]",
|
||||
"[detachedForeignComment, 4]",
|
||||
"[detachedXmlComment, 2]",
|
||||
"[docfrag, 0]",
|
||||
"[foreignDocfrag, 0]",
|
||||
"[xmlDocfrag, 0]",
|
||||
"[doctype, 0]",
|
||||
"[doctype, -17]",
|
||||
"[doctype, 1]",
|
||||
"[foreignDoctype, 0]",
|
||||
"[xmlDoctype, 0]",
|
||||
];
|
||||
|
||||
testNodes = [
|
||||
"paras[0]",
|
||||
"paras[0].firstChild",
|
||||
"paras[1]",
|
||||
"paras[1].firstChild",
|
||||
"foreignPara1",
|
||||
"foreignPara1.firstChild",
|
||||
"detachedPara1",
|
||||
"detachedPara1.firstChild",
|
||||
"detachedPara1",
|
||||
"detachedPara1.firstChild",
|
||||
"testDiv",
|
||||
"document",
|
||||
"detachedDiv",
|
||||
"detachedPara2",
|
||||
"foreignDoc",
|
||||
"foreignPara2",
|
||||
"xmlDoc",
|
||||
"xmlElement",
|
||||
"detachedXmlElement",
|
||||
"detachedTextNode",
|
||||
"foreignTextNode",
|
||||
"detachedForeignTextNode",
|
||||
"xmlTextNode",
|
||||
"detachedXmlTextNode",
|
||||
"processingInstruction",
|
||||
"detachedProcessingInstruction",
|
||||
"comment",
|
||||
"detachedComment",
|
||||
"foreignComment",
|
||||
"detachedForeignComment",
|
||||
"xmlComment",
|
||||
"detachedXmlComment",
|
||||
"docfrag",
|
||||
"foreignDocfrag",
|
||||
"xmlDocfrag",
|
||||
"doctype",
|
||||
"foreignDoctype",
|
||||
"xmlDoctype",
|
||||
];
|
||||
}
|
||||
if ("setup" in window) {
|
||||
setup(setupRangeTests);
|
||||
} else {
|
||||
// Presumably we're running from within an iframe or something
|
||||
setupRangeTests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of a node as specified in DOM Range.
|
||||
*/
|
||||
function getNodeLength(node) {
|
||||
if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
|
||||
return 0;
|
||||
}
|
||||
if (node.nodeType == Node.TEXT_NODE || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE || node.nodeType == Node.COMMENT_NODE) {
|
||||
return node.length;
|
||||
}
|
||||
return node.childNodes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the furthest ancestor of a Node as defined by the spec.
|
||||
*/
|
||||
function furthestAncestor(node) {
|
||||
var root = node;
|
||||
while (root.parentNode != null) {
|
||||
root = root.parentNode;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* "The ancestor containers of a Node are the Node itself and all its
|
||||
* ancestors."
|
||||
*
|
||||
* Is node1 an ancestor container of node2?
|
||||
*/
|
||||
function isAncestorContainer(node1, node2) {
|
||||
return node1 == node2 ||
|
||||
(node2.compareDocumentPosition(node1) & Node.DOCUMENT_POSITION_CONTAINS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first Node that's after node in tree order, or null if node is
|
||||
* the last Node.
|
||||
*/
|
||||
function nextNode(node) {
|
||||
if (node.hasChildNodes()) {
|
||||
return node.firstChild;
|
||||
}
|
||||
return nextNodeDescendants(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last Node that's before node in tree order, or null if node is
|
||||
* the first Node.
|
||||
*/
|
||||
function previousNode(node) {
|
||||
if (node.previousSibling) {
|
||||
node = node.previousSibling;
|
||||
while (node.hasChildNodes()) {
|
||||
node = node.lastChild;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
return node.parentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next Node that's after node and all its descendants in tree
|
||||
* order, or null if node is the last Node or an ancestor of it.
|
||||
*/
|
||||
function nextNodeDescendants(node) {
|
||||
while (node && !node.nextSibling) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
return node.nextSibling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ownerDocument of the Node, or the Node itself if it's a
|
||||
* Document.
|
||||
*/
|
||||
function ownerDocument(node) {
|
||||
return node.nodeType == Node.DOCUMENT_NODE
|
||||
? node
|
||||
: node.ownerDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if ancestor is an ancestor of descendant, false otherwise.
|
||||
*/
|
||||
function isAncestor(ancestor, descendant) {
|
||||
if (!ancestor || !descendant) {
|
||||
return false;
|
||||
}
|
||||
while (descendant && descendant != ancestor) {
|
||||
descendant = descendant.parentNode;
|
||||
}
|
||||
return descendant == ancestor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if descendant is a descendant of ancestor, false otherwise.
|
||||
*/
|
||||
function isDescendant(descendant, ancestor) {
|
||||
return isAncestor(ancestor, descendant);
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of two boundary points relative to one another, as defined by
|
||||
* the spec.
|
||||
*/
|
||||
function getPosition(nodeA, offsetA, nodeB, offsetB) {
|
||||
// "If node A is the same as node B, return equal if offset A equals offset
|
||||
// B, before if offset A is less than offset B, and after if offset A is
|
||||
// greater than offset B."
|
||||
if (nodeA == nodeB) {
|
||||
if (offsetA == offsetB) {
|
||||
return "equal";
|
||||
}
|
||||
if (offsetA < offsetB) {
|
||||
return "before";
|
||||
}
|
||||
if (offsetA > offsetB) {
|
||||
return "after";
|
||||
}
|
||||
}
|
||||
|
||||
// "If node A is after node B in tree order, compute the position of (node
|
||||
// B, offset B) relative to (node A, offset A). If it is before, return
|
||||
// after. If it is after, return before."
|
||||
if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
||||
var pos = getPosition(nodeB, offsetB, nodeA, offsetA);
|
||||
if (pos == "before") {
|
||||
return "after";
|
||||
}
|
||||
if (pos == "after") {
|
||||
return "before";
|
||||
}
|
||||
}
|
||||
|
||||
// "If node A is an ancestor of node B:"
|
||||
if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_CONTAINS) {
|
||||
// "Let child equal node B."
|
||||
var child = nodeB;
|
||||
|
||||
// "While child is not a child of node A, set child to its parent."
|
||||
while (child.parentNode != nodeA) {
|
||||
child = child.parentNode;
|
||||
}
|
||||
|
||||
// "If the index of child is less than offset A, return after."
|
||||
if (indexOf(child) < offsetA) {
|
||||
return "after";
|
||||
}
|
||||
}
|
||||
|
||||
// "Return before."
|
||||
return "before";
|
||||
}
|
||||
|
||||
/**
|
||||
* "contained" as defined by DOM Range: "A Node node is contained in a range
|
||||
* range if node's furthest ancestor is the same as range's root, and (node, 0)
|
||||
* is after range's start, and (node, length of node) is before range's end."
|
||||
*/
|
||||
function isContained(node, range) {
|
||||
var pos1 = getPosition(node, 0, range.startContainer, range.startOffset);
|
||||
var pos2 = getPosition(node, getNodeLength(node), range.endContainer, range.endOffset);
|
||||
|
||||
return furthestAncestor(node) == furthestAncestor(range.startContainer)
|
||||
&& pos1 == "after"
|
||||
&& pos2 == "before";
|
||||
}
|
||||
|
||||
/**
|
||||
* "partially contained" as defined by DOM Range: "A Node is partially
|
||||
* contained in a range if it is an ancestor container of the range's start but
|
||||
* not its end, or vice versa."
|
||||
*/
|
||||
function isPartiallyContained(node, range) {
|
||||
var cond1 = isAncestorContainer(node, range.startContainer);
|
||||
var cond2 = isAncestorContainer(node, range.endContainer);
|
||||
return (cond1 && !cond2) || (cond2 && !cond1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Index of a node as defined by the spec.
|
||||
*/
|
||||
function indexOf(node) {
|
||||
if (!node.parentNode) {
|
||||
// No preceding sibling nodes, right?
|
||||
return 0;
|
||||
}
|
||||
var i = 0;
|
||||
while (node != node.parentNode.childNodes[i]) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* extractContents() implementation, following the spec. If an exception is
|
||||
* supposed to be thrown, will return a string with the name (e.g.,
|
||||
* "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also
|
||||
* return an arbitrary human-readable string if a condition is hit that implies
|
||||
* a spec bug.
|
||||
*/
|
||||
function myExtractContents(range) {
|
||||
// "If the context object's detached flag is set, raise an
|
||||
// INVALID_STATE_ERR exception and abort these steps."
|
||||
try {
|
||||
range.collapsed;
|
||||
} catch (e) {
|
||||
return "INVALID_STATE_ERR";
|
||||
}
|
||||
|
||||
// "Let frag be a new DocumentFragment whose ownerDocument is the same as
|
||||
// the ownerDocument of the context object's start node."
|
||||
var ownerDoc = range.startContainer.nodeType == Node.DOCUMENT_NODE
|
||||
? range.startContainer
|
||||
: range.startContainer.ownerDocument;
|
||||
var frag = ownerDoc.createDocumentFragment();
|
||||
|
||||
// "If the context object's start and end are the same, abort this method,
|
||||
// returning frag."
|
||||
if (range.startContainer == range.endContainer
|
||||
&& range.startOffset == range.endOffset) {
|
||||
return frag;
|
||||
}
|
||||
|
||||
// "Let original start node, original start offset, original end node, and
|
||||
// original end offset be the context object's start and end nodes and
|
||||
// offsets, respectively."
|
||||
var originalStartNode = range.startContainer;
|
||||
var originalStartOffset = range.startOffset;
|
||||
var originalEndNode = range.endContainer;
|
||||
var originalEndOffset = range.endOffset;
|
||||
|
||||
// "If original start node and original end node are the same, and they are
|
||||
// a Text or Comment node:"
|
||||
if (range.startContainer == range.endContainer
|
||||
&& (range.startContainer.nodeType == Node.TEXT_NODE
|
||||
|| range.startContainer.nodeType == Node.COMMENT_NODE)) {
|
||||
// "Let clone be the result of calling cloneNode(false) on original
|
||||
// start node."
|
||||
var clone = originalStartNode.cloneNode(false);
|
||||
|
||||
// "Set the data of clone to the result of calling
|
||||
// substringData(original start offset, original end offset − original
|
||||
// start offset) on original start node."
|
||||
clone.data = originalStartNode.substringData(originalStartOffset,
|
||||
originalEndOffset - originalStartOffset);
|
||||
|
||||
// "Append clone as the last child of frag."
|
||||
frag.appendChild(clone);
|
||||
|
||||
// "Call deleteData(original start offset, original end offset −
|
||||
// original start offset) on original start node."
|
||||
originalStartNode.deleteData(originalStartOffset,
|
||||
originalEndOffset - originalStartOffset);
|
||||
|
||||
// "Abort this method, returning frag."
|
||||
return frag;
|
||||
}
|
||||
|
||||
// "Let common ancestor equal original start node."
|
||||
var commonAncestor = originalStartNode;
|
||||
|
||||
// "While common ancestor is not an ancestor container of original end
|
||||
// node, set common ancestor to its own parent."
|
||||
while (!isAncestorContainer(commonAncestor, originalEndNode)) {
|
||||
commonAncestor = commonAncestor.parentNode;
|
||||
}
|
||||
|
||||
// "If original start node is an ancestor container of original end node,
|
||||
// let first partially contained child be null."
|
||||
var firstPartiallyContainedChild;
|
||||
if (isAncestorContainer(originalStartNode, originalEndNode)) {
|
||||
firstPartiallyContainedChild = null;
|
||||
// "Otherwise, let first partially contained child be the first child of
|
||||
// common ancestor that is partially contained in the context object."
|
||||
} else {
|
||||
for (var i = 0; i < commonAncestor.childNodes.length; i++) {
|
||||
if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
|
||||
firstPartiallyContainedChild = commonAncestor.childNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!firstPartiallyContainedChild) {
|
||||
throw "Spec bug: no first partially contained child!";
|
||||
}
|
||||
}
|
||||
|
||||
// "If original end node is an ancestor container of original start node,
|
||||
// let last partially contained child be null."
|
||||
var lastPartiallyContainedChild;
|
||||
if (isAncestorContainer(originalEndNode, originalStartNode)) {
|
||||
lastPartiallyContainedChild = null;
|
||||
// "Otherwise, let last partially contained child be the last child of
|
||||
// common ancestor that is partially contained in the context object."
|
||||
} else {
|
||||
for (var i = commonAncestor.childNodes.length - 1; i >= 0; i--) {
|
||||
if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
|
||||
lastPartiallyContainedChild = commonAncestor.childNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lastPartiallyContainedChild) {
|
||||
throw "Spec bug: no last partially contained child!";
|
||||
}
|
||||
}
|
||||
|
||||
// "Let contained children be a list of all children of common ancestor
|
||||
// that are contained in the context object, in tree order."
|
||||
//
|
||||
// "If any member of contained children is a DocumentType, raise a
|
||||
// HIERARCHY_REQUEST_ERR exception and abort these steps."
|
||||
var containedChildren = [];
|
||||
for (var i = 0; i < commonAncestor.childNodes.length; i++) {
|
||||
if (isContained(commonAncestor.childNodes[i], range)) {
|
||||
if (commonAncestor.childNodes[i].nodeType
|
||||
== Node.DOCUMENT_TYPE_NODE) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
containedChildren.push(commonAncestor.childNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// "If original start node is an ancestor container of original end node,
|
||||
// set new node to original start node and new offset to original start
|
||||
// offset."
|
||||
var newNode, newOffset;
|
||||
if (isAncestorContainer(originalStartNode, originalEndNode)) {
|
||||
newNode = originalStartNode;
|
||||
newOffset = originalStartOffset;
|
||||
// "Otherwise:"
|
||||
} else {
|
||||
// "Let reference node equal original start node."
|
||||
var referenceNode = originalStartNode;
|
||||
|
||||
// "While reference node's parent is not null and is not an ancestor
|
||||
// container of original end node, set reference node to its parent."
|
||||
while (referenceNode.parentNode
|
||||
&& !isAncestorContainer(referenceNode.parentNode, originalEndNode)) {
|
||||
referenceNode = referenceNode.parentNode;
|
||||
}
|
||||
|
||||
// "Set new node to the parent of reference node, and new offset to one
|
||||
// plus the index of reference node."
|
||||
newNode = referenceNode.parentNode;
|
||||
newOffset = 1 + indexOf(referenceNode);
|
||||
}
|
||||
|
||||
// "If first partially contained child is a Text or Comment node:"
|
||||
if (firstPartiallyContainedChild
|
||||
&& (firstPartiallyContainedChild.nodeType == Node.TEXT_NODE
|
||||
|| firstPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
|
||||
// "Let clone be the result of calling cloneNode(false) on original
|
||||
// start node."
|
||||
var clone = originalStartNode.cloneNode(false);
|
||||
|
||||
// "Set the data of clone to the result of calling substringData() on
|
||||
// original start node, with original start offset as the first
|
||||
// argument and (length of original start node − original start offset)
|
||||
// as the second."
|
||||
clone.data = originalStartNode.substringData(originalStartOffset,
|
||||
getNodeLength(originalStartNode) - originalStartOffset);
|
||||
|
||||
// "Append clone as the last child of frag."
|
||||
frag.appendChild(clone);
|
||||
|
||||
// "Call deleteData() on original start node, with original start
|
||||
// offset as the first argument and (length of original start node −
|
||||
// original start offset) as the second."
|
||||
originalStartNode.deleteData(originalStartOffset,
|
||||
getNodeLength(originalStartNode) - originalStartOffset);
|
||||
// "Otherwise, if first partially contained child is not null:"
|
||||
} else if (firstPartiallyContainedChild) {
|
||||
// "Let clone be the result of calling cloneNode(false) on first
|
||||
// partially contained child."
|
||||
var clone = firstPartiallyContainedChild.cloneNode(false);
|
||||
|
||||
// "Append clone as the last child of frag."
|
||||
frag.appendChild(clone);
|
||||
|
||||
// "Let subrange be a new Range whose start is (original start node,
|
||||
// original start offset) and whose end is (first partially contained
|
||||
// child, length of first partially contained child)."
|
||||
var subrange = ownerDoc.createRange();
|
||||
subrange.setStart(originalStartNode, originalStartOffset);
|
||||
subrange.setEnd(firstPartiallyContainedChild,
|
||||
getNodeLength(firstPartiallyContainedChild));
|
||||
|
||||
// "Let subfrag be the result of calling extractContents() on
|
||||
// subrange."
|
||||
var subfrag = myExtractContents(subrange);
|
||||
|
||||
// "For each child of subfrag, in order, append that child to clone as
|
||||
// its last child."
|
||||
for (var i = 0; i < subfrag.childNodes.length; i++) {
|
||||
clone.appendChild(subfrag.childNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// "For each contained child in contained children, append contained child
|
||||
// as the last child of frag."
|
||||
for (var i = 0; i < containedChildren.length; i++) {
|
||||
frag.appendChild(containedChildren[i]);
|
||||
}
|
||||
|
||||
// "If last partially contained child is a Text or Comment node:"
|
||||
if (lastPartiallyContainedChild
|
||||
&& (lastPartiallyContainedChild.nodeType == Node.TEXT_NODE
|
||||
|| lastPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
|
||||
// "Let clone be the result of calling cloneNode(false) on original
|
||||
// end node."
|
||||
var clone = originalEndNode.cloneNode(false);
|
||||
|
||||
// "Set the data of clone to the result of calling substringData(0,
|
||||
// original end offset) on original end node."
|
||||
clone.data = originalEndNode.substringData(0, originalEndOffset);
|
||||
|
||||
// "Append clone as the last child of frag."
|
||||
frag.appendChild(clone);
|
||||
|
||||
// "Call deleteData(0, original end offset) on original end node."
|
||||
originalEndNode.deleteData(0, originalEndOffset);
|
||||
// "Otherwise, if last partially contained child is not null:"
|
||||
} else if (lastPartiallyContainedChild) {
|
||||
// "Let clone be the result of calling cloneNode(false) on last
|
||||
// partially contained child."
|
||||
var clone = lastPartiallyContainedChild.cloneNode(false);
|
||||
|
||||
// "Append clone as the last child of frag."
|
||||
frag.appendChild(clone);
|
||||
|
||||
// "Let subrange be a new Range whose start is (last partially
|
||||
// contained child, 0) and whose end is (original end node, original
|
||||
// end offset)."
|
||||
var subrange = ownerDoc.createRange();
|
||||
subrange.setStart(lastPartiallyContainedChild, 0);
|
||||
subrange.setEnd(originalEndNode, originalEndOffset);
|
||||
|
||||
// "Let subfrag be the result of calling extractContents() on
|
||||
// subrange."
|
||||
var subfrag = myExtractContents(subrange);
|
||||
|
||||
// "For each child of subfrag, in order, append that child to clone as
|
||||
// its last child."
|
||||
for (var i = 0; i < subfrag.childNodes.length; i++) {
|
||||
clone.appendChild(subfrag.childNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// "Set the context object's start and end to (new node, new offset)."
|
||||
range.setStart(newNode, newOffset);
|
||||
range.setEnd(newNode, newOffset);
|
||||
|
||||
// "Return frag."
|
||||
return frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* insertNode() implementation, following the spec. If an exception is
|
||||
* supposed to be thrown, will return a string with the name (e.g.,
|
||||
* "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also
|
||||
* return an arbitrary human-readable string if a condition is hit that implies
|
||||
* a spec bug.
|
||||
*/
|
||||
function myInsertNode(range, newNode) {
|
||||
// "If the context object's detached flag is set, raise an
|
||||
// INVALID_STATE_ERR exception and abort these steps."
|
||||
//
|
||||
// Assume that if accessing collapsed throws, it's detached.
|
||||
try {
|
||||
range.collapsed;
|
||||
} catch (e) {
|
||||
return "INVALID_STATE_ERR";
|
||||
}
|
||||
|
||||
// "If the context object's start node is a Text or Comment node and its
|
||||
// parent is null, raise an HIERARCHY_REQUEST_ERR exception and abort these
|
||||
// steps."
|
||||
if ((range.startContainer.nodeType == Node.TEXT_NODE
|
||||
|| range.startContainer.nodeType == Node.COMMENT_NODE)
|
||||
&& !range.startContainer.parentNode) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If the context object's start node is a Text node, run splitText() on
|
||||
// it with the context object's start offset as its argument, and let
|
||||
// reference node be the result."
|
||||
var referenceNode;
|
||||
if (range.startContainer.nodeType == Node.TEXT_NODE) {
|
||||
// We aren't testing how ranges vary under mutations, and browsers vary
|
||||
// in how they mutate for splitText, so let's just force the correct
|
||||
// way.
|
||||
var start = [range.startContainer, range.startOffset];
|
||||
var end = [range.endContainer, range.endOffset];
|
||||
|
||||
referenceNode = range.startContainer.splitText(range.startOffset);
|
||||
|
||||
if (start[0] == end[0]
|
||||
&& end[1] > start[1]) {
|
||||
end[0] = referenceNode;
|
||||
end[1] -= start[1];
|
||||
} else if (end[0] == start[0].parentNode
|
||||
&& end[1] > indexOf(referenceNode)) {
|
||||
end[1]++;
|
||||
}
|
||||
range.setStart(start[0], start[1]);
|
||||
range.setEnd(end[0], end[1]);
|
||||
// "Otherwise, if the context object's start node is a Comment, let
|
||||
// reference node be the context object's start node."
|
||||
} else if (range.startContainer.nodeType == Node.COMMENT_NODE) {
|
||||
referenceNode = range.startContainer;
|
||||
// "Otherwise, let reference node be the child of the context object's
|
||||
// start node with index equal to the context object's start offset, or
|
||||
// null if there is no such child."
|
||||
} else {
|
||||
referenceNode = range.startContainer.childNodes[range.startOffset];
|
||||
if (typeof referenceNode == "undefined") {
|
||||
referenceNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
// "If reference node is null, let parent node be the context object's
|
||||
// start node."
|
||||
var parentNode;
|
||||
if (!referenceNode) {
|
||||
parentNode = range.startContainer;
|
||||
// "Otherwise, let parent node be the parent of reference node."
|
||||
} else {
|
||||
parentNode = referenceNode.parentNode;
|
||||
}
|
||||
|
||||
// "Call insertBefore(newNode, reference node) on parent node, re-raising
|
||||
// any exceptions that call raised."
|
||||
try {
|
||||
parentNode.insertBefore(newNode, referenceNode);
|
||||
} catch (e) {
|
||||
return getDomExceptionName(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that two nodes are equal, in the sense of isEqualNode(). If they
|
||||
* aren't, tries to print a relatively informative reason why not. TODO: Move
|
||||
* this to testharness.js?
|
||||
*/
|
||||
function assertNodesEqual(actual, expected, msg) {
|
||||
if (!actual.isEqualNode(expected)) {
|
||||
msg = "Actual and expected mismatch for " + msg + ". ";
|
||||
|
||||
while (actual && expected) {
|
||||
assert_true(actual.nodeType === expected.nodeType
|
||||
&& actual.nodeName === expected.nodeName
|
||||
&& actual.nodeValue === expected.nodeValue
|
||||
&& actual.childNodes.length === expected.childNodes.length,
|
||||
"First differing node: expected " + format_value(expected)
|
||||
+ ", got " + format_value(actual));
|
||||
actual = nextNode(actual);
|
||||
expected = nextNode(expected);
|
||||
}
|
||||
|
||||
assert_unreached("DOMs were not equal but we couldn't figure out why");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a DOMException, return the name (e.g., "HIERARCHY_REQUEST_ERR"). In
|
||||
* theory this should be just e.name, but in practice it's not. So I could
|
||||
* legitimately just return e.name, but then every engine but WebKit would fail
|
||||
* every test, since no one seems to care much for standardizing DOMExceptions.
|
||||
* Instead I mangle it to account for browser bugs, so as not to fail
|
||||
* insertNode() tests (for instance) for insertBefore() bugs. Of course, a
|
||||
* standards-compliant browser will work right in any event.
|
||||
*
|
||||
* If the exception has no string property called "name" or "message", we just
|
||||
* re-throw it.
|
||||
*/
|
||||
function getDomExceptionName(e) {
|
||||
if (typeof e.name == "string"
|
||||
&& /^[A-Z_]+_ERR$/.test(e.name)) {
|
||||
// Either following the standard, or prefixing NS_ERROR_DOM (I'm
|
||||
// looking at you, Gecko).
|
||||
return e.name.replace(/^NS_ERROR_DOM_/, "");
|
||||
}
|
||||
|
||||
if (typeof e.message == "string"
|
||||
&& /^[A-Z_]+_ERR$/.test(e.message)) {
|
||||
// Opera
|
||||
return e.message;
|
||||
}
|
||||
|
||||
if (typeof e.message == "string"
|
||||
&& /^DOM Exception:/.test(e.message)) {
|
||||
// IE
|
||||
return /[A-Z_]+_ERR/.exec(e.message)[0];
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of endpoint data [start container, start offset, end
|
||||
* container, end offset], returns a Range with those endpoints.
|
||||
*/
|
||||
function rangeFromEndpoints(endpoints) {
|
||||
// If we just use document instead of the ownerDocument of endpoints[0],
|
||||
// WebKit will throw on setStart/setEnd. This is a WebKit bug, but it's in
|
||||
// range, not selection, so we don't want to fail anything for it.
|
||||
var range = ownerDocument(endpoints[0]).createRange();
|
||||
range.setStart(endpoints[0], endpoints[1]);
|
||||
range.setEnd(endpoints[2], endpoints[3]);
|
||||
return range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of endpoint data [start container, start offset, end
|
||||
* container, end offset], sets the selection to have those endpoints. Uses
|
||||
* addRange, so the range will be forwards. Accepts an empty array for
|
||||
* endpoints, in which case the selection will just be emptied.
|
||||
*/
|
||||
function setSelectionForwards(endpoints) {
|
||||
selection.removeAllRanges();
|
||||
if (endpoints.length) {
|
||||
selection.addRange(rangeFromEndpoints(endpoints));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of endpoint data [start container, start offset, end
|
||||
* container, end offset], sets the selection to have those endpoints, with the
|
||||
* direction backwards. Uses extend, so it will throw in IE. Accepts an empty
|
||||
* array for endpoints, in which case the selection will just be emptied.
|
||||
*/
|
||||
function setSelectionBackwards(endpoints) {
|
||||
selection.removeAllRanges();
|
||||
if (endpoints.length) {
|
||||
selection.collapse(endpoints[2], endpoints[3]);
|
||||
selection.extend(endpoints[0], endpoints[1]);
|
||||
}
|
||||
}
|
33
dom/imptests/editing/selecttest/test-iframe.html
Normal file
33
dom/imptests/editing/selecttest/test-iframe.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!doctype html>
|
||||
<title>Selection test iframe</title>
|
||||
<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
|
||||
<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>
|
44
dom/imptests/editing/selecttest/test_Document-open.html
Normal file
44
dom/imptests/editing/selecttest/test_Document-open.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<title>Selection Document.open() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// This tests the HTML spec requirement "Replace the Document's singleton
|
||||
// objects with new instances of those objects. (This includes in particular
|
||||
// the Window, Location, History, ApplicationCache, and Navigator, objects, the
|
||||
// various BarProp objects, the two Storage objects, the various HTMLCollection
|
||||
// objects, and objects defined by other specifications, like Selection and the
|
||||
// document's UndoManager. It also includes all the Web IDL prototypes in the
|
||||
// JavaScript binding, including the Document object's prototype.)" in the
|
||||
// document.open() algorithm.
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
var t = async_test("Selection must be replaced with a new object after document.open()");
|
||||
iframe.onload = function() {
|
||||
t.step(function() {
|
||||
var originalSelection = iframe.contentWindow.getSelection();
|
||||
assert_equals(originalSelection.rangeCount, 0,
|
||||
"Sanity check: rangeCount must be initially 0");
|
||||
iframe.contentDocument.body.appendChild(
|
||||
iframe.contentDocument.createTextNode("foo"));
|
||||
var range = iframe.contentDocument.createRange();
|
||||
range.selectNodeContents(iframe.contentDocument.body);
|
||||
iframe.contentWindow.getSelection().addRange(range);
|
||||
assert_equals(originalSelection.rangeCount, 1,
|
||||
"Sanity check: rangeCount must be 1 after adding a range");
|
||||
|
||||
iframe.contentDocument.open();
|
||||
|
||||
assert_not_equals(iframe.contentWindow.getSelection(), originalSelection,
|
||||
"After document.open(), the Selection object must no longer be the same");
|
||||
assert_equals(iframe.contentWindow.getSelection().rangeCount, 0,
|
||||
"After document.open(), rangeCount must be 0 again");
|
||||
});
|
||||
t.done();
|
||||
document.body.removeChild(iframe);
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
</script>
|
177
dom/imptests/editing/selecttest/test_addRange.html
Normal file
177
dom/imptests/editing/selecttest/test_addRange.html
Normal file
@ -0,0 +1,177 @@
|
||||
<!doctype html>
|
||||
<title>Selection.addRange() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.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>
|
87
dom/imptests/editing/selecttest/test_collapse.html
Normal file
87
dom/imptests/editing/selecttest/test_collapse.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!doctype html>
|
||||
<title>Selection.collapse() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.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) {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
if (point[1] < 0 || point[1] > getNodeLength(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>
|
121
dom/imptests/editing/selecttest/test_collapseToStartEnd.html
Normal file
121
dom/imptests/editing/selecttest/test_collapseToStartEnd.html
Normal file
@ -0,0 +1,121 @@
|
||||
<!doctype html>
|
||||
<title>Selection.collapseTo(Start|End)() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=common.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// 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>
|
97
dom/imptests/editing/selecttest/test_deleteFromDocument.html
Normal file
97
dom/imptests/editing/selecttest/test_deleteFromDocument.html
Normal file
@ -0,0 +1,97 @@
|
||||
<!doctype html>
|
||||
<title>Selection.deleteFromDocument() tests</title>
|
||||
<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
|
||||
<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>
|
148
dom/imptests/editing/selecttest/test_extend.html
Normal file
148
dom/imptests/editing/selecttest/test_extend.html
Normal file
@ -0,0 +1,148 @@
|
||||
<!doctype html>
|
||||
<title>Selection extend() tests</title>
|
||||
<meta charset=utf-8>
|
||||
<body>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=common.js></script>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// Also test a selection with no ranges
|
||||
testRanges.unshift("[]");
|
||||
|
||||
/**
|
||||
* 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. We test collapsed selections only
|
||||
* once.
|
||||
*/
|
||||
for (var i = 0; i < testRanges.length; i++) {
|
||||
var endpoints = eval(testRanges[i]);
|
||||
for (var j = 0; j < testPoints.length; j++) {
|
||||
if (endpoints[0] == endpoints[2]
|
||||
&& endpoints[1] == endpoints[3]) {
|
||||
// Test collapsed selections only once
|
||||
test(function() {
|
||||
setSelectionForwards(endpoints);
|
||||
testExtend(endpoints, eval(testPoints[j]));
|
||||
}, "extend() with range " + i + " " + testRanges[i]
|
||||
+ " and point " + j + " " + testPoints[j]);
|
||||
} else {
|
||||
test(function() {
|
||||
setSelectionForwards(endpoints);
|
||||
testExtend(endpoints, eval(testPoints[j]));
|
||||
}, "extend() forwards with range " + i + " " + testRanges[i]
|
||||
+ " and point " + j + " " + testPoints[j]);
|
||||
|
||||
test(function() {
|
||||
setSelectionBackwards(endpoints);
|
||||
testExtend(endpoints, eval(testPoints[j]));
|
||||
}, "extend() backwards with range " + i + " " + testRanges[i]
|
||||
+ " and point " + j + " " + testPoints[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testExtend(endpoints, target) {
|
||||
assert_equals(getSelection().rangeCount, endpoints.length/4,
|
||||
"Sanity check: rangeCount must be correct");
|
||||
|
||||
var node = target[0];
|
||||
var offset = target[1];
|
||||
|
||||
// "If the context object's range is null, throw an InvalidStateError
|
||||
// exception and abort these steps."
|
||||
if (getSelection().rangeCount == 0) {
|
||||
assert_throws("INVALID_STATE_ERR", function() {
|
||||
selection.extend(node, offset);
|
||||
}, "extend() when rangeCount is 0 must throw InvalidStateError");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_equals(getSelection().getRangeAt(0).startContainer, endpoints[0],
|
||||
"Sanity check: startContainer must be correct");
|
||||
assert_equals(getSelection().getRangeAt(0).startOffset, endpoints[1],
|
||||
"Sanity check: startOffset must be correct");
|
||||
assert_equals(getSelection().getRangeAt(0).endContainer, endpoints[2],
|
||||
"Sanity check: endContainer must be correct");
|
||||
assert_equals(getSelection().getRangeAt(0).endOffset, endpoints[3],
|
||||
"Sanity check: endOffset must be correct");
|
||||
|
||||
// "Let anchor and focus be the context object's anchor and focus, and let
|
||||
// new focus be the boundary point (node, offset)."
|
||||
var anchorNode = getSelection().anchorNode;
|
||||
var anchorOffset = getSelection().anchorOffset;
|
||||
var focusNode = getSelection().focusNode;
|
||||
var focusOffset = getSelection().focusOffset;
|
||||
|
||||
// "Let new range be a new range."
|
||||
//
|
||||
// We'll always be setting either new range's start or its end to new
|
||||
// focus, so we'll always throw at some point. Test that now.
|
||||
//
|
||||
// From DOM4's "set the start or end of a range": "If node is a doctype,
|
||||
// throw an "InvalidNodeTypeError" exception and terminate these steps."
|
||||
if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
|
||||
assert_throws("INVALID_NODE_TYPE_ERR", function() {
|
||||
selection.extend(node, offset);
|
||||
}, "extend() to a doctype must throw InvalidNodeTypeError");
|
||||
return;
|
||||
}
|
||||
|
||||
// From DOM4's "set the start or end of a range": "If offset is greater
|
||||
// than node's length, throw an "IndexSizeError" exception and terminate
|
||||
// these steps."
|
||||
//
|
||||
// FIXME: We should be casting offset to an unsigned int per WebIDL. Until
|
||||
// we do, we need the offset < 0 check too.
|
||||
if (offset < 0 || offset > getNodeLength(node)) {
|
||||
assert_throws("INDEX_SIZE_ERR", function() {
|
||||
selection.extend(node, offset);
|
||||
}, "extend() to an offset that's greater than node length (" + getNodeLength(node) + ") must throw IndexSizeError");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now back to the editing spec.
|
||||
var originalRange = getSelection().getRangeAt(0);
|
||||
|
||||
// "If node's root is not the same as the context object's range's root,
|
||||
// set new range's start and end to (node, offset)."
|
||||
//
|
||||
// "Otherwise, if anchor is before or equal to new focus, set new range's
|
||||
// start to anchor, then set its end to new focus."
|
||||
//
|
||||
// "Otherwise, set new range's start to new focus, then set its end to
|
||||
// anchor."
|
||||
//
|
||||
// "Set the context object's range to new range."
|
||||
//
|
||||
// "If new focus is before anchor, set the context object's direction to
|
||||
// backwards. Otherwise, set it to forwards."
|
||||
//
|
||||
// The upshot of all these is summed up by just testing the anchor and
|
||||
// offset.
|
||||
getSelection().extend(node, offset);
|
||||
|
||||
if (furthestAncestor(anchorNode) == furthestAncestor(node)) {
|
||||
assert_equals(getSelection().anchorNode, anchorNode,
|
||||
"anchorNode must not change if the node passed to extend() has the same root as the original range");
|
||||
assert_equals(getSelection().anchorOffset, anchorOffset,
|
||||
"anchorOffset must not change if the node passed to extend() has the same root as the original range");
|
||||
} else {
|
||||
assert_equals(getSelection().anchorNode, node,
|
||||
"anchorNode must be the node passed to extend() if it has a different root from the original range");
|
||||
assert_equals(getSelection().anchorOffset, offset,
|
||||
"anchorOffset must be the offset passed to extend() if the node has a different root from the original range");
|
||||
}
|
||||
assert_equals(getSelection().focusNode, node,
|
||||
"focusNode must be the node passed to extend()");
|
||||
assert_equals(getSelection().focusOffset, offset,
|
||||
"focusOffset must be the offset passed to extend()");
|
||||
assert_not_equals(getSelection().getRangeAt(0), originalRange,
|
||||
"extend() must replace any existing range with a new one, not mutate the existing one");
|
||||
}
|
||||
|
||||
testDiv.style.display = "none";
|
||||
</script>
|
14
dom/imptests/editing/selecttest/test_getRangeAt.html
Normal file
14
dom/imptests/editing/selecttest/test_getRangeAt.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<title>The getRangeAt method</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.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>
|
160
dom/imptests/editing/selecttest/test_getSelection.html
Normal file
160
dom/imptests/editing/selecttest/test_getSelection.html
Normal file
@ -0,0 +1,160 @@
|
||||
<!doctype html>
|
||||
<title>getSelection() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// TODO: Figure out more places where defaultView is or is not guaranteed to be
|
||||
// null, and test whether getSelection() is null.
|
||||
//
|
||||
// TODO: Figure out a good way to test display: none iframes.
|
||||
|
||||
test(function() {
|
||||
// Sanity checks like this are to flag known browser bugs with clearer
|
||||
// error messages, instead of throwing inscrutable exceptions.
|
||||
assert_true("Selection" in window,
|
||||
"Sanity check: window must have Selection property");
|
||||
|
||||
assert_true(window.getSelection() instanceof Selection);
|
||||
}, "window.getSelection() instanceof Selection");
|
||||
|
||||
test(function() {
|
||||
assert_equals(window.getSelection(), window.getSelection());
|
||||
}, "window.getSelection() === window.getSelection()");
|
||||
|
||||
test(function() {
|
||||
assert_true("Selection" in window,
|
||||
"Sanity check: window must have Selection property");
|
||||
// This sanity check (which occurs a number of times below, too) is because
|
||||
// document.getSelection() is supposed to return null if defaultView is
|
||||
// null, so we need to figure out whether defaultView is null or not before
|
||||
// we can make correct assertions about getSelection().
|
||||
assert_not_equals(document.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
|
||||
assert_equals(typeof document.getSelection(), "object",
|
||||
"document.getSelection() must be an object");
|
||||
assert_true(document.getSelection() instanceof Selection);
|
||||
}, "document.getSelection() instanceof Selection");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(document.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
assert_equals(document.getSelection(), document.getSelection());
|
||||
}, "document.getSelection() === document.getSelection()");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(document.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
assert_equals(window.getSelection(), document.getSelection());
|
||||
}, "window.getSelection() === document.getSelection()");
|
||||
|
||||
// "Each selection is associated with a single range, which may be null and is
|
||||
// initially null."
|
||||
//
|
||||
// "The rangeCount attribute must return 0 if the context object's range is
|
||||
// null, otherwise 1."
|
||||
test(function() {
|
||||
assert_equals(window.getSelection().rangeCount, 0,
|
||||
"window.getSelection().rangeCount must initially be 0");
|
||||
assert_equals(typeof document.getSelection(), "object",
|
||||
"Sanity check: document.getSelection() must be an object");
|
||||
assert_equals(document.getSelection().rangeCount, 0,
|
||||
"document.getSelection().rangeCount must initially be 0");
|
||||
}, "Selection's range must initially be null");
|
||||
|
||||
test(function() {
|
||||
var doc = document.implementation.createHTMLDocument("");
|
||||
assert_equals(doc.defaultView, null,
|
||||
"Sanity check: defaultView of created HTML document must be null");
|
||||
assert_equals(doc.getSelection(), null);
|
||||
}, "getSelection() on HTML document with null defaultView must be null");
|
||||
|
||||
test(function() {
|
||||
var xmlDoc = document.implementation.createDocument(null, "", null);
|
||||
|
||||
assert_true("getSelection" in xmlDoc, "XML document must have getSelection()");
|
||||
|
||||
assert_equals(xmlDoc.defaultView, null,
|
||||
"Sanity check: defaultView of created XML document must be null");
|
||||
assert_equals(xmlDoc.getSelection(), null);
|
||||
}, "getSelection() on XML document with null defaultView must be null");
|
||||
|
||||
|
||||
// Run a bunch of iframe tests, once immediately after the iframe is appended
|
||||
// to the document and once onload. This makes a difference, because browsers
|
||||
// differ (at the time of this writing) in whether they load about:blank in
|
||||
// iframes synchronously or not. Per the HTML spec, there must be a browsing
|
||||
// context associated with the iframe as soon as it's appended to the document,
|
||||
// so there should be a selection too.
|
||||
var iframe = document.createElement("iframe");
|
||||
add_completion_callback(function() {
|
||||
document.body.removeChild(iframe);
|
||||
});
|
||||
|
||||
var testDescs = [];
|
||||
var testFuncs = [];
|
||||
testDescs.push("window.getSelection() instanceof Selection in an iframe");
|
||||
testFuncs.push(function() {
|
||||
assert_true("Selection" in iframe.contentWindow,
|
||||
"Sanity check: window must have Selection property");
|
||||
assert_not_equals(iframe.contentWindow.document.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
assert_not_equals(iframe.contentWindow.getSelection(), null,
|
||||
"window.getSelection() must not be null");
|
||||
assert_true(iframe.contentWindow.getSelection() instanceof iframe.contentWindow.Selection);
|
||||
});
|
||||
|
||||
testDescs.push("document.getSelection() instanceof Selection in an iframe");
|
||||
testFuncs.push(function() {
|
||||
assert_true("Selection" in iframe.contentWindow,
|
||||
"Sanity check: window must have Selection property");
|
||||
assert_not_equals(iframe.contentDocument.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
assert_not_equals(iframe.contentDocument.getSelection(), null,
|
||||
"document.getSelection() must not be null");
|
||||
assert_equals(typeof iframe.contentDocument.getSelection(), "object",
|
||||
"document.getSelection() must be an object");
|
||||
assert_true(iframe.contentDocument.getSelection() instanceof iframe.contentWindow.Selection);
|
||||
});
|
||||
|
||||
testDescs.push("window.getSelection() === document.getSelection() in an iframe");
|
||||
testFuncs.push(function() {
|
||||
assert_not_equals(iframe.contentDocument.defaultView, null,
|
||||
"Sanity check: document.defaultView must not be null");
|
||||
assert_equals(iframe.contentWindow.getSelection(), iframe.contentDocument.getSelection());
|
||||
});
|
||||
|
||||
testDescs.push("getSelection() inside and outside iframe must return different objects");
|
||||
testFuncs.push(function() {
|
||||
assert_not_equals(iframe.contentWindow.getSelection(), getSelection());
|
||||
});
|
||||
|
||||
testDescs.push("getSelection() on HTML document with null defaultView must be null inside an iframe");
|
||||
testFuncs.push(function() {
|
||||
var doc = iframe.contentDocument.implementation.createHTMLDocument("");
|
||||
assert_equals(doc.defaultView, null,
|
||||
"Sanity check: defaultView of created HTML document must be null");
|
||||
assert_equals(doc.getSelection(), null);
|
||||
});
|
||||
|
||||
var asyncTests = [];
|
||||
testDescs.forEach(function(desc) {
|
||||
asyncTests.push(async_test(desc + " onload"));
|
||||
});
|
||||
|
||||
iframe.onload = function() {
|
||||
asyncTests.forEach(function(t, i) {
|
||||
t.step(testFuncs[i]);
|
||||
t.done();
|
||||
});
|
||||
};
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
testDescs.forEach(function(desc, i) {
|
||||
test(testFuncs[i], desc + " immediately after appendChild");
|
||||
});
|
||||
</script>
|
41
dom/imptests/editing/selecttest/test_interfaces.html
Normal file
41
dom/imptests/editing/selecttest/test_interfaces.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!doctype html>
|
||||
<title>Selection interface tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/WebIDLParser.js></script>
|
||||
<script src=/resources/idlharness.js></script>
|
||||
<script type=text/plain>
|
||||
interface Selection {
|
||||
readonly attribute Node? anchorNode;
|
||||
readonly attribute unsigned long anchorOffset;
|
||||
readonly attribute Node? focusNode;
|
||||
readonly attribute unsigned long focusOffset;
|
||||
|
||||
readonly attribute boolean isCollapsed;
|
||||
void collapse(Node node, unsigned long offset);
|
||||
void collapseToStart();
|
||||
void collapseToEnd();
|
||||
|
||||
void extend(Node node, unsigned long offset);
|
||||
|
||||
void selectAllChildren(Node node);
|
||||
void deleteFromDocument();
|
||||
|
||||
readonly attribute unsigned long rangeCount;
|
||||
Range getRangeAt(unsigned long index);
|
||||
void addRange(Range range);
|
||||
void removeRange(Range range);
|
||||
void removeAllRanges();
|
||||
|
||||
stringifier;
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var idlArray = new IdlArray();
|
||||
idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent);
|
||||
idlArray.add_objects({Selection: ['getSelection()']});
|
||||
idlArray.test();
|
||||
</script>
|
31
dom/imptests/editing/selecttest/test_isCollapsed.html
Normal file
31
dom/imptests/editing/selecttest/test_isCollapsed.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!doctype html>
|
||||
<title>Selection.isCollapsed tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=common.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(function() {
|
||||
selection.removeAllRanges();
|
||||
assert_true(selection.isCollapsed, "isCollapsed must be true if both anchor and focus are null");
|
||||
}, "Empty selection");
|
||||
|
||||
for (var i = 0; i < testRanges.length; i++) {
|
||||
test(function() {
|
||||
selection.removeAllRanges();
|
||||
var endpoints = eval(testRanges[i]);
|
||||
var range = ownerDocument(endpoints[0]).createRange();
|
||||
range.setStart(endpoints[0], endpoints[1]);
|
||||
range.setEnd(endpoints[2], endpoints[3]);
|
||||
selection.addRange(range);
|
||||
|
||||
assert_equals(selection.isCollapsed,
|
||||
endpoints[0] === endpoints[2] && endpoints[1] === endpoints[3],
|
||||
"Value of isCollapsed");
|
||||
}, "Range " + i + " " + testRanges[i]);
|
||||
}
|
||||
|
||||
testDiv.style.display = "none";
|
||||
</script>
|
45
dom/imptests/editing/selecttest/test_removeAllRanges.html
Normal file
45
dom/imptests/editing/selecttest/test_removeAllRanges.html
Normal file
@ -0,0 +1,45 @@
|
||||
<!doctype html>
|
||||
<title>Selection.removeAllRanges() tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=common.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// Also test a selection with no ranges
|
||||
testRanges.unshift("[]");
|
||||
|
||||
var range = rangeFromEndpoints([paras[0].firstChild, 0, paras[0].firstChild, 1]);
|
||||
|
||||
for (var i = 0; i < testRanges.length; i++) {
|
||||
test(function() {
|
||||
setSelectionForwards(eval(testRanges[i]));
|
||||
selection.removeAllRanges();
|
||||
assert_equals(selection.rangeCount, 0,
|
||||
"After removeAllRanges(), rangeCount must be 0");
|
||||
// Test that it's forwards
|
||||
selection.addRange(range);
|
||||
assert_equals(selection.anchorOffset, selection.getRangeAt(0).startOffset,
|
||||
"After removeAllRanges(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset");
|
||||
assert_equals(selection.focusOffset, selection.getRangeAt(0).endOffset,
|
||||
"After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset");
|
||||
}, "Range " + i + " " + testRanges[i] + " forwards");
|
||||
|
||||
// Copy-pasted from above
|
||||
test(function() {
|
||||
setSelectionBackwards(eval(testRanges[i]));
|
||||
selection.removeAllRanges();
|
||||
assert_equals(selection.rangeCount, 0,
|
||||
"After removeAllRanges(), rangeCount must be 0");
|
||||
// Test that it's forwards
|
||||
selection.addRange(range);
|
||||
assert_equals(selection.anchorOffset, selection.getRangeAt(0).startOffset,
|
||||
"After removeAllRanges(), addRange() must be forwards, so anchorOffset must equal startOffset rather than endOffset");
|
||||
assert_equals(selection.focusOffset, selection.getRangeAt(0).endOffset,
|
||||
"After removeAllRanges(), addRange() must be forwards, so focusOffset must equal endOffset rather than startOffset");
|
||||
}, "Range " + i + " " + testRanges[i] + " backwards");
|
||||
}
|
||||
|
||||
testDiv.style.display = "none";
|
||||
</script>
|
53
dom/imptests/editing/selecttest/test_selectAllChildren.html
Normal file
53
dom/imptests/editing/selecttest/test_selectAllChildren.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!doctype html>
|
||||
<title>Selection.selectAllChildren tests</title>
|
||||
<div id=log></div>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=common.js></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
testRanges.unshift("[]");
|
||||
|
||||
for (var i = 0; i < testRanges.length; i++) {
|
||||
var endpoints = eval(testRanges[i]);
|
||||
|
||||
for (var j = 0; j < testNodes.length; j++) {
|
||||
var node = eval(testNodes[j]);
|
||||
|
||||
test(function() {
|
||||
setSelectionForwards(endpoints);
|
||||
var originalRange = getSelection().rangeCount
|
||||
? getSelection().getRangeAt(0)
|
||||
: null;
|
||||
|
||||
if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
|
||||
assert_throws("INVALID_NODE_TYPE_ERR", function() {
|
||||
selection.selectAllChildren(node);
|
||||
}, "selectAllChildren() on a DocumentType must throw InvalidNodeTypeError");
|
||||
return;
|
||||
}
|
||||
|
||||
selection.selectAllChildren(node);
|
||||
// This implicitly tests that the selection is forwards, by using
|
||||
// anchorOffset/focusOffset instead of getRangeAt.
|
||||
assert_equals(selection.rangeCount, 1,
|
||||
"After selectAllChildren, rangeCount must be 1");
|
||||
assert_equals(selection.anchorNode, node,
|
||||
"After selectAllChildren, anchorNode must be the given node");
|
||||
assert_equals(selection.anchorOffset, 0,
|
||||
"After selectAllChildren, anchorOffset must be 0");
|
||||
assert_equals(selection.focusNode, node,
|
||||
"After selectAllChildren, focusNode must be the given node");
|
||||
assert_equals(selection.focusOffset, node.childNodes.length,
|
||||
"After selectAllChildren, focusOffset must be the given node's number of children");
|
||||
if (originalRange) {
|
||||
assert_not_equals(getSelection().getRangeAt(0), originalRange,
|
||||
"selectAllChildren must replace any existing range, not mutate it");
|
||||
}
|
||||
}, "Range " + i + " " + testRanges[i] + ", node " + j + " " + testNodes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
testDiv.style.display = "none";
|
||||
</script>
|
5716
dom/imptests/editing/tests.js
Normal file
5716
dom/imptests/editing/tests.js
Normal file
File diff suppressed because it is too large
Load Diff
20
dom/imptests/failures/editing/conformancetest/Makefile.in
Normal file
20
dom/imptests/failures/editing/conformancetest/Makefile.in
Normal file
@ -0,0 +1,20 @@
|
||||
DEPTH = ../../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/failures/editing/conformancetest
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
test_event.html.json \
|
||||
test_runtest.html.json \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
@ -0,0 +1,310 @@
|
||||
{
|
||||
"Simple editable div: beforeinput event, canceled":true,
|
||||
"Simple editable div: input event, canceled":true,
|
||||
"Simple editable div: beforeinput event, uncanceled":true,
|
||||
"Simple editable div: input event, uncanceled":true,
|
||||
"Editable b: execCommand() must not throw, canceled":true,
|
||||
"Editable b: beforeinput event, canceled":true,
|
||||
"Editable b: input event, canceled":true,
|
||||
"Editable b: execCommand() must not throw, uncanceled":true,
|
||||
"Editable b: beforeinput event, uncanceled":true,
|
||||
"Editable b: input event, uncanceled":true,
|
||||
"No editable content: execCommand() must not throw, canceled":true,
|
||||
"No editable content: execCommand() must not throw, uncanceled":true,
|
||||
"Changing selection from handler: beforeinput event, canceled":true,
|
||||
"Changing selection from handler: input event, canceled":true,
|
||||
"Changing selection from handler: beforeinput event, uncanceled":true,
|
||||
"Changing selection from handler: input event, uncanceled":true,
|
||||
"Command backColor, value \"\": beforeinput event, canceled":true,
|
||||
"Command backColor, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command backColor, value \"\": input event, uncanceled":true,
|
||||
"Command backColor, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command backColor, value \"quasit\": input event, canceled":true,
|
||||
"Command backColor, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command backColor, value \"quasit\": input event, uncanceled":true,
|
||||
"Command backColor, value \"green\": beforeinput event, canceled":true,
|
||||
"Command backColor, value \"green\": input event, canceled":true,
|
||||
"Command backColor, value \"green\": beforeinput event, uncanceled":true,
|
||||
"Command backColor, value \"green\": input event, uncanceled":true,
|
||||
"Command createLink, value \"\": execCommand() must not throw, canceled":true,
|
||||
"Command createLink, value \"\": beforeinput event, canceled":true,
|
||||
"Command createLink, value \"\": execCommand() must not throw, uncanceled":true,
|
||||
"Command createLink, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command createLink, value \"\": input event, uncanceled":true,
|
||||
"Command createLink, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command createLink, value \"quasit\": input event, canceled":true,
|
||||
"Command createLink, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command createLink, value \"quasit\": input event, uncanceled":true,
|
||||
"Command createLink, value \"http://www.w3.org/community/editing/\": beforeinput event, canceled":true,
|
||||
"Command createLink, value \"http://www.w3.org/community/editing/\": input event, canceled":true,
|
||||
"Command createLink, value \"http://www.w3.org/community/editing/\": beforeinput event, uncanceled":true,
|
||||
"Command createLink, value \"http://www.w3.org/community/editing/\": input event, uncanceled":true,
|
||||
"Command fontName, value \"\": beforeinput event, canceled":true,
|
||||
"Command fontName, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command fontName, value \"\": input event, uncanceled":true,
|
||||
"Command fontName, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command fontName, value \"quasit\": input event, canceled":true,
|
||||
"Command fontName, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command fontName, value \"quasit\": input event, uncanceled":true,
|
||||
"Command fontName, value \"serif\": beforeinput event, canceled":true,
|
||||
"Command fontName, value \"serif\": input event, canceled":true,
|
||||
"Command fontName, value \"serif\": beforeinput event, uncanceled":true,
|
||||
"Command fontName, value \"serif\": input event, uncanceled":true,
|
||||
"Command fontName, value \"Helvetica\": beforeinput event, canceled":true,
|
||||
"Command fontName, value \"Helvetica\": input event, canceled":true,
|
||||
"Command fontName, value \"Helvetica\": beforeinput event, uncanceled":true,
|
||||
"Command fontName, value \"Helvetica\": input event, uncanceled":true,
|
||||
"Command fontSize, value \"\": beforeinput event, canceled":true,
|
||||
"Command fontSize, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command fontSize, value \"\": input event, uncanceled":true,
|
||||
"Command fontSize, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command fontSize, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command fontSize, value \"quasit\": input event, uncanceled":true,
|
||||
"Command fontSize, value \"6\": beforeinput event, canceled":true,
|
||||
"Command fontSize, value \"6\": input event, canceled":true,
|
||||
"Command fontSize, value \"6\": beforeinput event, uncanceled":true,
|
||||
"Command fontSize, value \"6\": input event, uncanceled":true,
|
||||
"Command fontSize, value \"15px\": beforeinput event, canceled":true,
|
||||
"Command fontSize, value \"15px\": input event, canceled":true,
|
||||
"Command fontSize, value \"15px\": beforeinput event, uncanceled":true,
|
||||
"Command fontSize, value \"15px\": input event, uncanceled":true,
|
||||
"Command foreColor, value \"\": beforeinput event, canceled":true,
|
||||
"Command foreColor, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command foreColor, value \"\": input event, uncanceled":true,
|
||||
"Command foreColor, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command foreColor, value \"quasit\": input event, canceled":true,
|
||||
"Command foreColor, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command foreColor, value \"quasit\": input event, uncanceled":true,
|
||||
"Command foreColor, value \"green\": beforeinput event, canceled":true,
|
||||
"Command foreColor, value \"green\": input event, canceled":true,
|
||||
"Command foreColor, value \"green\": beforeinput event, uncanceled":true,
|
||||
"Command foreColor, value \"green\": input event, uncanceled":true,
|
||||
"Command hiliteColor, value \"\": beforeinput event, canceled":true,
|
||||
"Command hiliteColor, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command hiliteColor, value \"\": input event, uncanceled":true,
|
||||
"Command hiliteColor, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command hiliteColor, value \"quasit\": input event, canceled":true,
|
||||
"Command hiliteColor, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command hiliteColor, value \"quasit\": input event, uncanceled":true,
|
||||
"Command hiliteColor, value \"green\": beforeinput event, canceled":true,
|
||||
"Command hiliteColor, value \"green\": input event, canceled":true,
|
||||
"Command hiliteColor, value \"green\": beforeinput event, uncanceled":true,
|
||||
"Command hiliteColor, value \"green\": input event, uncanceled":true,
|
||||
"Command italic, value \"\": beforeinput event, canceled":true,
|
||||
"Command italic, value \"\": input event, canceled":true,
|
||||
"Command italic, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command italic, value \"\": input event, uncanceled":true,
|
||||
"Command italic, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command italic, value \"quasit\": input event, canceled":true,
|
||||
"Command italic, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command italic, value \"quasit\": input event, uncanceled":true,
|
||||
"Command removeFormat, value \"\": beforeinput event, canceled":true,
|
||||
"Command removeFormat, value \"\": input event, canceled":true,
|
||||
"Command removeFormat, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command removeFormat, value \"\": input event, uncanceled":true,
|
||||
"Command removeFormat, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command removeFormat, value \"quasit\": input event, canceled":true,
|
||||
"Command removeFormat, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command removeFormat, value \"quasit\": input event, uncanceled":true,
|
||||
"Command strikeThrough, value \"\": beforeinput event, canceled":true,
|
||||
"Command strikeThrough, value \"\": input event, canceled":true,
|
||||
"Command strikeThrough, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command strikeThrough, value \"\": input event, uncanceled":true,
|
||||
"Command strikeThrough, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command strikeThrough, value \"quasit\": input event, canceled":true,
|
||||
"Command strikeThrough, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command strikeThrough, value \"quasit\": input event, uncanceled":true,
|
||||
"Command subscript, value \"\": beforeinput event, canceled":true,
|
||||
"Command subscript, value \"\": input event, canceled":true,
|
||||
"Command subscript, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command subscript, value \"\": input event, uncanceled":true,
|
||||
"Command subscript, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command subscript, value \"quasit\": input event, canceled":true,
|
||||
"Command subscript, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command subscript, value \"quasit\": input event, uncanceled":true,
|
||||
"Command superscript, value \"\": beforeinput event, canceled":true,
|
||||
"Command superscript, value \"\": input event, canceled":true,
|
||||
"Command superscript, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command superscript, value \"\": input event, uncanceled":true,
|
||||
"Command superscript, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command superscript, value \"quasit\": input event, canceled":true,
|
||||
"Command superscript, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command superscript, value \"quasit\": input event, uncanceled":true,
|
||||
"Command underline, value \"\": beforeinput event, canceled":true,
|
||||
"Command underline, value \"\": input event, canceled":true,
|
||||
"Command underline, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command underline, value \"\": input event, uncanceled":true,
|
||||
"Command underline, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command underline, value \"quasit\": input event, canceled":true,
|
||||
"Command underline, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command underline, value \"quasit\": input event, uncanceled":true,
|
||||
"Command unlink, value \"\": beforeinput event, canceled":true,
|
||||
"Command unlink, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command unlink, value \"\": input event, uncanceled":true,
|
||||
"Command unlink, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command unlink, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command unlink, value \"quasit\": input event, uncanceled":true,
|
||||
"Command delete, value \"\": beforeinput event, canceled":true,
|
||||
"Command delete, value \"\": input event, canceled":true,
|
||||
"Command delete, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command delete, value \"\": input event, uncanceled":true,
|
||||
"Command delete, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command delete, value \"quasit\": input event, canceled":true,
|
||||
"Command delete, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command delete, value \"quasit\": input event, uncanceled":true,
|
||||
"Command formatBlock, value \"\": beforeinput event, canceled":true,
|
||||
"Command formatBlock, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command formatBlock, value \"\": input event, uncanceled":true,
|
||||
"Command formatBlock, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command formatBlock, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command formatBlock, value \"quasit\": input event, uncanceled":true,
|
||||
"Command formatBlock, value \"p\": beforeinput event, canceled":true,
|
||||
"Command formatBlock, value \"p\": input event, canceled":true,
|
||||
"Command formatBlock, value \"p\": beforeinput event, uncanceled":true,
|
||||
"Command formatBlock, value \"p\": input event, uncanceled":true,
|
||||
"Command forwardDelete, value \"\": beforeinput event, canceled":true,
|
||||
"Command forwardDelete, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command forwardDelete, value \"\": input event, uncanceled":true,
|
||||
"Command forwardDelete, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command forwardDelete, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command forwardDelete, value \"quasit\": input event, uncanceled":true,
|
||||
"Command indent, value \"\": beforeinput event, canceled":true,
|
||||
"Command indent, value \"\": input event, canceled":true,
|
||||
"Command indent, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command indent, value \"\": input event, uncanceled":true,
|
||||
"Command indent, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command indent, value \"quasit\": input event, canceled":true,
|
||||
"Command indent, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command indent, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"\": input event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"\": input event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"quasit\": input event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"id\": beforeinput event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"id\": input event, canceled":true,
|
||||
"Command insertHorizontalRule, value \"id\": beforeinput event, uncanceled":true,
|
||||
"Command insertHorizontalRule, value \"id\": input event, uncanceled":true,
|
||||
"Command insertHTML, value \"\": execCommand() must not throw, canceled":true,
|
||||
"Command insertHTML, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertHTML, value \"\": execCommand() must not throw, uncanceled":true,
|
||||
"Command insertHTML, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertHTML, value \"\": input event, uncanceled":true,
|
||||
"Command insertHTML, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertHTML, value \"quasit\": input event, canceled":true,
|
||||
"Command insertHTML, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertHTML, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertHTML, value \"<b>hi</b>\": beforeinput event, canceled":true,
|
||||
"Command insertHTML, value \"<b>hi</b>\": input event, canceled":true,
|
||||
"Command insertHTML, value \"<b>hi</b>\": beforeinput event, uncanceled":true,
|
||||
"Command insertHTML, value \"<b>hi</b>\": input event, uncanceled":true,
|
||||
"Command insertImage, value \"\": execCommand() must not throw, canceled":true,
|
||||
"Command insertImage, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertImage, value \"\": execCommand() must not throw, uncanceled":true,
|
||||
"Command insertImage, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertImage, value \"\": input event, uncanceled":true,
|
||||
"Command insertImage, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertImage, value \"quasit\": input event, canceled":true,
|
||||
"Command insertImage, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertImage, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertImage, value \"http://example.com/some-image\": beforeinput event, canceled":true,
|
||||
"Command insertImage, value \"http://example.com/some-image\": input event, canceled":true,
|
||||
"Command insertImage, value \"http://example.com/some-image\": beforeinput event, uncanceled":true,
|
||||
"Command insertImage, value \"http://example.com/some-image\": input event, uncanceled":true,
|
||||
"Command insertLineBreak, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertLineBreak, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertLineBreak, value \"\": input event, uncanceled":true,
|
||||
"Command insertLineBreak, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertLineBreak, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertLineBreak, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertOrderedList, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertOrderedList, value \"\": input event, canceled":true,
|
||||
"Command insertOrderedList, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertOrderedList, value \"\": input event, uncanceled":true,
|
||||
"Command insertOrderedList, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertOrderedList, value \"quasit\": input event, canceled":true,
|
||||
"Command insertOrderedList, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertOrderedList, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertParagraph, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertParagraph, value \"\": input event, canceled":true,
|
||||
"Command insertParagraph, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertParagraph, value \"\": input event, uncanceled":true,
|
||||
"Command insertParagraph, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertParagraph, value \"quasit\": input event, canceled":true,
|
||||
"Command insertParagraph, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertParagraph, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertText, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertText, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertText, value \"\": input event, uncanceled":true,
|
||||
"Command insertText, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertText, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertText, value \"quasit\": input event, uncanceled":true,
|
||||
"Command insertText, value \"abc\": beforeinput event, canceled":true,
|
||||
"Command insertText, value \"abc\": beforeinput event, uncanceled":true,
|
||||
"Command insertText, value \"abc\": input event, uncanceled":true,
|
||||
"Command insertUnorderedList, value \"\": beforeinput event, canceled":true,
|
||||
"Command insertUnorderedList, value \"\": input event, canceled":true,
|
||||
"Command insertUnorderedList, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command insertUnorderedList, value \"\": input event, uncanceled":true,
|
||||
"Command insertUnorderedList, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command insertUnorderedList, value \"quasit\": input event, canceled":true,
|
||||
"Command insertUnorderedList, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command insertUnorderedList, value \"quasit\": input event, uncanceled":true,
|
||||
"Command justifyCenter, value \"\": beforeinput event, canceled":true,
|
||||
"Command justifyCenter, value \"\": input event, canceled":true,
|
||||
"Command justifyCenter, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command justifyCenter, value \"\": input event, uncanceled":true,
|
||||
"Command justifyCenter, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command justifyCenter, value \"quasit\": input event, canceled":true,
|
||||
"Command justifyCenter, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command justifyCenter, value \"quasit\": input event, uncanceled":true,
|
||||
"Command justifyFull, value \"\": beforeinput event, canceled":true,
|
||||
"Command justifyFull, value \"\": input event, canceled":true,
|
||||
"Command justifyFull, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command justifyFull, value \"\": input event, uncanceled":true,
|
||||
"Command justifyFull, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command justifyFull, value \"quasit\": input event, canceled":true,
|
||||
"Command justifyFull, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command justifyFull, value \"quasit\": input event, uncanceled":true,
|
||||
"Command justifyLeft, value \"\": beforeinput event, canceled":true,
|
||||
"Command justifyLeft, value \"\": input event, canceled":true,
|
||||
"Command justifyLeft, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command justifyLeft, value \"\": input event, uncanceled":true,
|
||||
"Command justifyLeft, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command justifyLeft, value \"quasit\": input event, canceled":true,
|
||||
"Command justifyLeft, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command justifyLeft, value \"quasit\": input event, uncanceled":true,
|
||||
"Command justifyRight, value \"\": beforeinput event, canceled":true,
|
||||
"Command justifyRight, value \"\": input event, canceled":true,
|
||||
"Command justifyRight, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command justifyRight, value \"\": input event, uncanceled":true,
|
||||
"Command justifyRight, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command justifyRight, value \"quasit\": input event, canceled":true,
|
||||
"Command justifyRight, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command justifyRight, value \"quasit\": input event, uncanceled":true,
|
||||
"Command outdent, value \"\": beforeinput event, canceled":true,
|
||||
"Command outdent, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command outdent, value \"\": input event, uncanceled":true,
|
||||
"Command outdent, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command outdent, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command outdent, value \"quasit\": input event, uncanceled":true,
|
||||
"Command redo, value \"\": beforeinput event, canceled":true,
|
||||
"Command redo, value \"\": input event, canceled":true,
|
||||
"Command redo, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command redo, value \"\": input event, uncanceled":true,
|
||||
"Command redo, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command redo, value \"quasit\": input event, canceled":true,
|
||||
"Command redo, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command redo, value \"quasit\": input event, uncanceled":true,
|
||||
"Command undo, value \"\": beforeinput event, canceled":true,
|
||||
"Command undo, value \"\": input event, canceled":true,
|
||||
"Command undo, value \"\": beforeinput event, uncanceled":true,
|
||||
"Command undo, value \"\": input event, uncanceled":true,
|
||||
"Command undo, value \"quasit\": beforeinput event, canceled":true,
|
||||
"Command undo, value \"quasit\": input event, canceled":true,
|
||||
"Command undo, value \"quasit\": beforeinput event, uncanceled":true,
|
||||
"Command undo, value \"quasit\": input event, uncanceled":true
|
||||
}
|
29172
dom/imptests/failures/editing/conformancetest/test_runtest.html.json
Normal file
29172
dom/imptests/failures/editing/conformancetest/test_runtest.html.json
Normal file
File diff suppressed because it is too large
Load Diff
22
dom/imptests/failures/editing/selecttest/Makefile.in
Normal file
22
dom/imptests/failures/editing/selecttest/Makefile.in
Normal file
@ -0,0 +1,22 @@
|
||||
DEPTH = ../../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = dom/imptests/failures/editing/selecttest
|
||||
|
||||
DIRS = \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TESTS = \
|
||||
test_addRange.html.json \
|
||||
test_Document-open.html.json \
|
||||
test_getSelection.html.json \
|
||||
test_interfaces.html.json \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TESTS)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"Selection must be replaced with a new object after document.open()":true
|
||||
}
|
4236
dom/imptests/failures/editing/selecttest/test_addRange.html.json
Normal file
4236
dom/imptests/failures/editing/selecttest/test_addRange.html.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
{
|
||||
"getSelection() on HTML document with null defaultView must be null":true,
|
||||
"getSelection() on XML document with null defaultView must be null":true,
|
||||
"window.getSelection() instanceof Selection in an iframe immediately after appendChild":true,
|
||||
"document.getSelection() instanceof Selection in an iframe immediately after appendChild":true,
|
||||
"getSelection() on HTML document with null defaultView must be null inside an iframe onload":true
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"Selection interface: existence and properties of interface object":true,
|
||||
"Selection interface: existence and properties of interface prototype object":true,
|
||||
"Selection interface: existence and properties of interface prototype object's \"constructor\" property":true,
|
||||
"Selection interface: calling collapse() on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling extend() on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling selectAllChildren() on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling getRangeAt() on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling addRange() on getSelection() with too few arguments must throw TypeError":true,
|
||||
"Selection interface: calling removeRange() on getSelection() with too few arguments must throw TypeError":true
|
||||
}
|
Loading…
Reference in New Issue
Block a user