310 lines
No EOL
12 KiB
HTML
310 lines
No EOL
12 KiB
HTML
<!doctype html>
|
|
<meta charset=utf-8>
|
|
<title>Test execCommand with selection around select element</title>
|
|
<meta name="timeout" content="long">
|
|
<meta name="variant" content="?delete">
|
|
<meta name="variant" content="?forwardDelete">
|
|
<meta name="variant" content="?insertText">
|
|
<script src=/resources/testharness.js></script>
|
|
<script src=/resources/testharnessreport.js></script>
|
|
<script>
|
|
"use strict";
|
|
|
|
const command = document.location.search.substring(1);
|
|
const insertText = command === "insertText" ? "XYZ" : "";
|
|
|
|
/**
|
|
* Typically, browsers do not allow to move caret or select part of <select>,
|
|
* <option> and <optgroup>, but Selection API can do it (but browsers don't
|
|
* show the result). In this case, any elements under `<select>` element
|
|
* shouldn't be modified (deleted) for avoiding unexpected data loss for the
|
|
* users.
|
|
*/
|
|
|
|
promise_test(async () => {
|
|
await new Promise(resolve => {
|
|
addEventListener("load", resolve, {once: true});
|
|
});
|
|
});
|
|
|
|
function addPromiseTest(desc, initFunc, expectedResults) {
|
|
promise_test(async () => {
|
|
initFunc();
|
|
document.execCommand(command, false, insertText);
|
|
if (Array.isArray(expectedResults)) {
|
|
assert_in_array(document.body.innerHTML.replace(/(=""|<br>)/g, ""), expectedResults);
|
|
} else {
|
|
assert_equals(document.body.innerHTML.replace(/(=""|<br>)/g, ""), expectedResults);
|
|
}
|
|
}, `execCommand(${command}, false, "${insertText}") in ${desc}`);
|
|
}
|
|
|
|
for (const multiple of ["", " multiple"]) {
|
|
addPromiseTest(
|
|
`<div contenteditable><p>ab[c</p><select${multiple}><option>d]ef</option></select></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("p").firstChild,
|
|
2,
|
|
document.querySelector("option").firstChild,
|
|
1
|
|
);
|
|
},
|
|
[
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select></div>`,
|
|
`<div contenteditable><p>ab${insertText}</p><select${multiple}><option>def</option></select></div>`,
|
|
]
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>d[]ef</option></select></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select></div>`;
|
|
getSelection().collapse(
|
|
document.querySelector("option").firstChild,
|
|
1
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select></div>`,
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><select${multiple}><option>ab[c</option></select><p>d]ef</p></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><select${multiple}><option>abc</option></select><p>def</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("option").firstChild,
|
|
2,
|
|
document.querySelector("p").firstChild,
|
|
1
|
|
);
|
|
},
|
|
[
|
|
`<div contenteditable><select${multiple}><option>abc</option></select><p>def</p></div>`,
|
|
`<div contenteditable><select${multiple}><option>abc</option></select><p>${insertText}ef</p></div>`,
|
|
]
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>{}def</option></select><p>ghi</p></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`;
|
|
getSelection().collapse(
|
|
document.querySelector("option"),
|
|
0
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def{}</option></select><p>ghi</p></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`;
|
|
getSelection().collapse(
|
|
document.querySelector("option"),
|
|
1
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>{def}</option></select><p>ghi</p></div>: shouldn't modify in <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("option")
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option></select><p>ghi</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>{def</option><option>ghi}</option></select><p>jkl</p></div>: shouldn't join <option>s`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("option"),
|
|
0,
|
|
document.querySelector("option + option"),
|
|
1,
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}>{<option>def</option>}<option>ghi</option></select><p>jkl</p></div>: shouldn't delete <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("select"),
|
|
0,
|
|
document.querySelector("select"),
|
|
1,
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option>{<option>ghi</option>}</select><p>jkl</p></div>: shouldn't delete <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("select"),
|
|
1,
|
|
document.querySelector("select"),
|
|
2,
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}>{<option>def</option><option>ghi</option>}</select><p>jkl</p></div>: shouldn't delete <option>s nor <select${multiple}>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("select")
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p><select${multiple}><optgroup>{<option>def</option><option>ghi</option>}</optgroup></select><p>jkl</p></div>: shouldn't delete <option>, <optgroup> nor <select${multiple}>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><optgroup><option>def</option><option>ghi</option></optgroup></select><p>jkl</p></div>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("optgroup")
|
|
);
|
|
},
|
|
`<div contenteditable><p>abc</p><select${multiple}><optgroup><option>def</option><option>ghi</option></optgroup></select><p>jkl</p></div>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p>{<select${multiple}><option>def</option><option>ghi</option></select>}<p>jkl</p></div>: <select${multiple}> element itself should be removable`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("div"),
|
|
1,
|
|
document.querySelector("div"),
|
|
2,
|
|
);
|
|
},
|
|
[
|
|
`<div contenteditable><p>abc</p>${insertText}<p>jkl</p></div>`,
|
|
`<div contenteditable><p>abc${insertText}</p><p>jkl</p></div>`,
|
|
`<div contenteditable><p>abc</p><p>${insertText}jkl</p></div>`,
|
|
]
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<div contenteditable><p>abc</p>{<select${multiple}><optgroup><option>def</option><option>ghi</option></optgroup></select>}<p>jkl</p></div>: <select${multiple}> element itself should be removable`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<div contenteditable><p>abc</p><select${multiple}><option>def</option><option>ghi</option></select><p>jkl</p></div>`;
|
|
getSelection().setBaseAndExtent(
|
|
document.querySelector("div"),
|
|
1,
|
|
document.querySelector("div"),
|
|
2,
|
|
);
|
|
},
|
|
[
|
|
`<div contenteditable><p>abc</p>${insertText}<p>jkl</p></div>`,
|
|
`<div contenteditable><p>abc${insertText}</p><p>jkl</p></div>`,
|
|
`<div contenteditable><p>abc</p><p>${insertText}jkl</p></div>`,
|
|
]
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<select${multiple} contenteditable>{<option>abc</option><option>def</option>}</select>: shouldn't delete <option>s`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<select${multiple} contenteditable><option>abc</option><option>def</option></select>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("select")
|
|
);
|
|
},
|
|
`<select${multiple} contenteditable><option>abc</option><option>def</option></select>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<select${multiple}><option contenteditable>{abc}</option><option>def</option></select>: shouldn't modify <option>`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<select${multiple}><option contenteditable>abc</option><option>def</option></select>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("option")
|
|
);
|
|
},
|
|
`<select${multiple}><option contenteditable>abc</option><option>def</option></select>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<select${multiple}><optgroup contenteditable>{<option>abc</option><option>def</option>}</optgroup></select>: shouldn't delete <option>s`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<select${multiple}><optgroup contenteditable><option>abc</option><option>def</option></optgroup></select>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("optgroup")
|
|
);
|
|
},
|
|
`<select${multiple}><optgroup contenteditable><option>abc</option><option>def</option></optgroup></select>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
`<select${multiple}><optgroup contenteditable><option>{abc}</option><option>def</option></optgroup></select>: shouldn't delete <option>s nor optgroup`,
|
|
() => {
|
|
document.body.innerHTML =
|
|
`<select${multiple}><optgroup contenteditable><option>abc</option><option>def</option></optgroup></select>`;
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("option")
|
|
);
|
|
},
|
|
`<select${multiple}><optgroup contenteditable><option>abc</option><option>def</option></optgroup></select>`
|
|
);
|
|
}
|
|
|
|
addPromiseTest(
|
|
"<optgroup contenteditable><option>{abc}</option><option>def</option></optgroup>: shouldn't delete <option>s nor optgroup",
|
|
() => {
|
|
document.body.innerHTML =
|
|
"<optgroup contenteditable><option>abc</option><option>def</option></optgroup>";
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("option")
|
|
);
|
|
},
|
|
`<optgroup contenteditable><option>abc</option><option>def</option></optgroup>`
|
|
);
|
|
|
|
addPromiseTest(
|
|
"<option contenteditable>{abc}</option>: shouldn't modify <option>",
|
|
() => {
|
|
document.body.innerHTML =
|
|
"<option contenteditable>abc</option>";
|
|
getSelection().selectAllChildren(
|
|
document.querySelector("option")
|
|
);
|
|
},
|
|
`<option contenteditable>abc</option>`
|
|
);
|
|
</script>
|
|
<body></body> |