1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
<!doctype html>
<meta charset="utf-8">
<title>Selection indices after content change</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<input id="i1" type="text" value="hello">
<textarea id="t1">hello</textarea>
<script>
"use strict";
// This helper ensures that when the selection direction is reset, it always is reset to the same value consistently
// (which must be one of either "none" or "forward"). This helps catch bugs like one observed in Chrome, where textareas
// reset to "none" but inputs reset to "forward".
let observedResetSelectionDirection;
function assertSelectionDirectionIsReset(element) {
if (!observedResetSelectionDirection) {
assert_in_array(element.selectionDirection, ["none", "forward"],
"selectionDirection must be set to either none or forward");
observedResetSelectionDirection = element.selectionDirection;
} else {
assert_equals(element.selectionDirection, observedResetSelectionDirection,
`selectionDirection must be reset to ${observedResetSelectionDirection} (which was previously observed to be ` +
`the value after resetting the selection direction)`);
}
}
runInputTest("input out of document", () => {
const input = document.createElement("input");
input.value = "hello";
return input;
});
runInputTest("input in document", () => {
const input = document.querySelector("#i1");
input.value = "hello";
return input;
});
runInputTest("input in document, with focus", () => {
const input = document.querySelector("#i1");
input.value = "hello";
input.focus();
return input;
});
runTextareaTest("textarea out of document", () => {
const textarea = document.createElement("textarea");
textarea.value = "hello";
return textarea;
});
runTextareaTest("textarea in document", () => {
const textarea = document.querySelector("#t1");
textarea.value = "hello";
return textarea;
});
runTextareaTest("textarea in document, with focus", () => {
const textarea = document.querySelector("#t1");
textarea.value = "hello";
textarea.focus();
return textarea;
});
function runTest(descriptor, elementFactory) {
test(() => {
const element = elementFactory();
element.setSelectionRange(1, 3, "backward");
assert_equals(element.selectionStart, 1, "Sanity check: selectionStart was set correctly");
assert_equals(element.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
assert_equals(element.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
element.value = "hello";
assert_equals(element.selectionStart, 1, "selectionStart must not change");
assert_equals(element.selectionEnd, 3, "selectionEnd must not change");
assert_equals(element.selectionDirection, "backward", "selectionDirection must not change");
}, `${descriptor}: selection must not change when setting the same value`);
test(() => {
const element = elementFactory();
element.setSelectionRange(1, 3, "backward");
assert_equals(element.selectionStart, 1, "Sanity check: selectionStart was set correctly");
assert_equals(element.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
assert_equals(element.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
element.value = "hello2";
assert_equals(element.selectionStart, element.value.length, "selectionStart must be reset to the end");
assert_equals(element.selectionEnd, element.value.length, "selectionEnd must be reset to the end");
assertSelectionDirectionIsReset(element);
}, `${descriptor}: selection must change when setting a different value`);
}
function runInputTest(descriptor, elementFactory) {
runTest(descriptor, elementFactory);
test(() => {
const input = elementFactory();
input.setSelectionRange(1, 3, "backward");
assert_equals(input.selectionStart, 1, "Sanity check: selectionStart was set correctly");
assert_equals(input.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
assert_equals(input.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
input.value = "he\nllo";
assert_equals(input.selectionStart, 1, "selectionStart must not change");
assert_equals(input.selectionEnd, 3, "selectionEnd must not change");
assert_equals(input.selectionDirection, "backward", "selectionDirection must not change");
}, `${descriptor}: selection must not change when setting a value that becomes the same after the value ` +
`sanitization algorithm`);
}
function runTextareaTest(descriptor, elementFactory) {
runTest(descriptor, elementFactory);
test(() => {
const textarea = elementFactory();
textarea.value = "hell\no";
textarea.setSelectionRange(1, 3, "backward");
assert_equals(textarea.selectionStart, 1, "Sanity check: selectionStart was set correctly");
assert_equals(textarea.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
assert_equals(textarea.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
textarea.value = "hell\r\no";
assert_equals(textarea.selectionStart, 1, "selectionStart must not change when setting to CRLF");
assert_equals(textarea.selectionEnd, 3, "selectionEnd must not change when setting to CRLF");
assert_equals(textarea.selectionDirection, "backward", "selectionDirection must not change when setting to CRLF");
textarea.value = "hell\ro";
assert_equals(textarea.selectionStart, 1, "selectionStart must not change when setting to CR");
assert_equals(textarea.selectionEnd, 3, "selectionEnd must not change when setting to CR");
assert_equals(textarea.selectionDirection, "backward", "selectionDirection must not change when setting to CR");
}, `${descriptor}: selection must not change when setting the same normalized value`);
}
</script>
|