summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html')
-rw-r--r--testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html1744
1 files changed, 1744 insertions, 0 deletions
diff --git a/testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html b/testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html
new file mode 100644
index 0000000000..7c225cd051
--- /dev/null
+++ b/testing/web-platform/tests/input-events/input-events-get-target-ranges-deleting-in-list-items.tentative.html
@@ -0,0 +1,1744 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<meta name="variant" content="?Backspace,ul">
+<meta name="variant" content="?Backspace,ol">
+<meta name="variant" content="?Delete,ul">
+<meta name="variant" content="?Delete,ol">
+<title>InputEvent.getTargetRanges() at deleting in/around/across list item elements</title>
+<div contenteditable></div>
+<script src="input-events-get-target-ranges.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script>
+"use strict";
+
+const [action, list] = location.search.substring(1).split(",");
+function run() {
+ switch (action) {
+ case "Backspace":
+ return sendBackspaceKey();
+ case "Delete":
+ return sendDeleteKey();
+ default:
+ throw "Unhandled variant";
+ }
+}
+
+/**
+ * @param innerHTML Initial `innerHTML` value of the editor.
+ * @param data
+ * expectedInnerHTML
+ * Expected `innerHTML` of the editor after calling
+ * `run()`. This can be array of string if there are
+ * some acceptable differences like whether there is
+ * an invisible `<br>` element at end of list item.
+ * expectedTargetRanges
+ * `null` or `unspecified` if `beforeinput` event shouldn't
+ * be fired.
+ * Otherwise, function returning an array of objects
+ * which have `startContainer`, `startOffset`,
+ * `endContainer`, `endOffset`. This will be called
+ * before calling `run()` and compared with
+ * `getTargetRanges()` after that.
+ * expectInputEvent:
+ * `true` if it should cause an `input` event.
+ */
+function addPromiseTest(innerHTML, data) {
+ promise_test(async (t) => {
+ initializeTest(innerHTML);
+ let expectedTargetRanges =
+ typeof data.expectedTargetRanges === "function"
+ ? data.expectedTargetRanges()
+ : null;
+ await run();
+ checkEditorContentResultAsSubTest(data.expectedInnerHTML, t.name);
+ if (expectedTargetRanges !== null) {
+ checkGetTargetRangesOfBeforeinputOnDeleteSomething(expectedTargetRanges);
+ if (data.expectInputEvent) {
+ checkGetTargetRangesOfInputOnDeleteSomething();
+ } else {
+ checkGetTargetRangesOfInputOnDoNothing();
+ }
+ } else {
+ checkBeforeinputAndInputEventsOnNOOP();
+ }
+ }, `${action} at "${innerHTML}"`);
+}
+
+addPromiseTest(
+ `<${list}><li>list[-item1</li><li>list]-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: "list".length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: "list".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-[item1</li><li>]list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: "list-".length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-[item1</li><li>}list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: "list-".length,
+ endContainer: gEditor.querySelector("li + li"),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1[</li><li>list]-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: "list".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1{</li><li>list]-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li"),
+ startOffset: 1,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: "list".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1[</li><li>]list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li>list-item1</li><li>[]list-item2</li></${list}>`
+ : `<${list}><li>list-item1[]</li><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li>list-item1<br></li><li>[]list-item2</li></${list}>`
+ : `<${list}><li>list-item1[]<br></li><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return action === "Backspace"
+ ? [
+ {
+ startContainer: gEditor.querySelector("li"),
+ startOffset: 1,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ]
+ : [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li>list-item1<br><br></li><li>[]list-item2</li></${list}>`
+ : `<${list}><li>list-item1[]<br><br></li><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><li>list-item1<br>list-item2</li></${list}>`,
+ `<${list}><li>list-item1<br>list-item2<br></li></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return action === "Backspace"
+ ? [
+ {
+ startContainer: gEditor.querySelector("li"),
+ startOffset: 1,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ]
+ : [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li>list-item1</li><li>[]list-item2<br>second line of list-item2</li></${list}>`
+ : `<${list}><li>list-item1[]</li><li>list-item2<br>second line of list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li><li>second line of list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return action === "Backspace"
+ ? [
+ {
+ startContainer: gEditor.querySelector("li"),
+ startOffset: 1,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ]
+ : [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li><p>list-item1</p></li><li>[]list-item2</li></${list}>`
+ : `<${list}><li><p>list-item1[]</p></li><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><p>list-item1list-item2</p></li></${list}>`,
+ expectedTargetRanges: () => {
+ return action === "Backspace"
+ ? [
+ {
+ startContainer: gEditor.querySelector("p").firstChild,
+ startOffset: gEditor.querySelector("p").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ]
+ : [
+ {
+ startContainer: gEditor.querySelector("p").firstChild,
+ startOffset: gEditor.querySelector("p").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ action === "Backspace"
+ ? `<${list}><li>list-item1</li><li><p>[]list-item2</p></li></${list}>`
+ : `<${list}><li>list-item1[]</li><li><p>list-item2</p></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return action === "Backspace"
+ ? [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("p").firstChild,
+ endOffset: 0,
+ },
+ ]
+ : [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("p").firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>[list-item1]</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li").firstChild,
+ endOffset: gEditor.querySelector("li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>{list-item1}</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li").firstChild,
+ endOffset: gEditor.querySelector("li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// Even if the last list item is selected, don't delete the list and
+// the last list item element. This is a triple click case on Gecko.
+addPromiseTest(
+ `<${list}>{<li>list-item1</li>}</${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li").firstChild,
+ endOffset: gEditor.querySelector("li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// A list item is selected and it's not the last one, can delete it.
+addPromiseTest(
+ `<${list}>{<li>list-item1</li>}<li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// Delete list element when deleting from empty last list item.
+addPromiseTest(
+ `<${list}><li>{}<br></li></${list}>`,
+ {
+ expectedInnerHTML: ["", "<br>", "<div><br></div>"],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor,
+ startOffset: 0,
+ endContainer: gEditor,
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `{<${list}><li><br></li></${list}>}`,
+ {
+ expectedInnerHTML: ["", "<br>", "<div><br></div>"],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor,
+ startOffset: 0,
+ endContainer: gEditor,
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li><br></li></${list}>}</div>`,
+ {
+ expectedInnerHTML: ["<div><br></div>", "<div><div><br></div></div>"],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("div"),
+ startOffset: 0,
+ endContainer: gEditor.querySelector("div"),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// It may be better to ignore the invisible white-space and take same action
+// as above, but it requires more expensive check before deleting. So perhaps,
+// this behavior is reasonable.
+addPromiseTest(
+ `<div>{ <${list}><li><br></li></${list}> }</div>`,
+ {
+ expectedInnerHTML: ["<div><br></div>", "<div><div><br></div></div>"],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("div"),
+ startOffset: 0,
+ endContainer: gEditor.querySelector("div"),
+ endOffset: 3,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div><${list}><li>{}<br></li></${list}></div>`,
+ {
+ expectedInnerHTML: ["<div><br></div>", "<div><div><br></div></div>"],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("div"),
+ startOffset: 0,
+ endContainer: gEditor.querySelector("div"),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// XXX Blink does not delete the list element if its first or last <li> element
+// is not editable. However, it means that user cannot delete the list
+// element, and it's not consistent behavior when only middle list item(s)
+// are not editable. Perhaps, once it makes the list element has only
+// one empty list item element, then, another deleting operation allows to
+// delete the list element.
+addPromiseTest(
+ `<div>{<${list}><li contenteditable="false"><br></li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(list),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(list),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li contenteditable="false">list-item1</li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(list),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(list),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li contenteditable="false">list-item1</li><li><br></li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(list),
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li"),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li contenteditable="false">list-item1</li><li>list-item2</li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(list),
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li><br></li><li contenteditable="false">list-item2</li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(list),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li>list-item1</li><li contenteditable="false">list-item2</li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(list),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li><br></li><li contenteditable="false">list-item2</li><li><br></li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li + li"),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<div>{<${list}><li>list-item1</li><li contenteditable="false">list-item2</li><li>list-item3</li></${list}>}</div>`,
+ {
+ expectedInnerHTML: `<div><${list}><li><br></li></${list}></div>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1</li>{<li>list-item2</li>}<li>list-item3</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li>list-item3</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 1,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// Selecting last list item element shouldn't delete the list item.
+addPromiseTest(
+ `<${list}><li>list-item1</li>{<li>list-item2</li>}</${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li + li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li + li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > li + li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1</li><li>list-item2</li>{<li>list-item3</li>}</${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li>list-item2</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li + li + li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li + li + li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > li + li + li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+for (let childList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li>list-item1</li>{<li>list-item2</li>}<li><${childList}><li><br></li></${childList}></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 1,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ // Invalid nested list elements cases. Treat the nested list element as a list item element.
+ addPromiseTest(
+ `<${list}><li>list-item1</li>{<li>list-item2</li>}<${childList}><li><br></li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 1,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1</li><li>list-item2</li>{<${childList}><li><br></li></${childList}>}</${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li>list-item2</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 2,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 3,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+}
+
+// Don't delete list and joined list items when only there content are selected.
+addPromiseTest(
+ `<${list}><li>[list-item1</li><li>list-item2]</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>[list-item1</li><li>list-item2]</li><li>list-item3</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li><li>list-item3</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1</li><li>[list-item2]</li><li>list-item3</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><br></li><li>list-item3</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li + li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+addPromiseTest(
+ `<${list}><li>list-item1</li><li>[list-item2</li><li>list-item3]</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li + li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector("li + li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+);
+
+// Ported tests from editing/delete.js and editing/forwarddelete.js
+for (let otherList of ["ul", "ol"]) {
+ if (action === "Backspace") {
+ addPromiseTest(
+ `<${otherList}><li>list-item1</li></${otherList}><${list}><li>l[]ist-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${otherList}><li>list-item1</li></${otherList}><${list}><li>ist-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${otherList} + ${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${otherList} + ${list} > li`).firstChild,
+ endOffset: "l".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[]</li></${list}><${otherList}><li>list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item</li></${list}><${otherList}><li>list-item2</li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: "list-item".length,
+ endContainer: gEditor.querySelector("li").firstChild,
+ endOffset: "list-item1".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+ } else {
+ addPromiseTest(
+ `<${list}><li>list-item[]1</li></${list}><${otherList}><li>list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item</li></${list}><${otherList}><li>list-item2</li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: "list-item".length,
+ endContainer: gEditor.querySelector("li").firstChild,
+ endOffset: "list-item1".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${otherList}><li>list-item1</li></${otherList}><${list}><li>[]list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${otherList}><li>list-item1</li></${otherList}><${list}><li>ist-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${otherList} + ${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${otherList} + ${list} > li`).firstChild,
+ endOffset: "l".length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+ }
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li><li>list-item2]</li></${list}><${otherList}><li>list-item3</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li></${list}><${otherList}><li>ist-item3</li><li>ist-item4</li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: gEditor.querySelector("li").firstChild.length,
+ endContainer: gEditor.querySelector("li + li").firstChild,
+ endOffset: gEditor.querySelector("li + li").firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+}
+
+
+// Invalid nested list element cases. Traditionally, all browser engines
+// insert child list element without wrapping it with a list item element.
+// So, keeping the behavior in these cases are important for backward
+// compatibility.
+// https://bugzilla.mozilla.org/show_bug.cgi?id=487524
+for (let childList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li>[list-item1</li><${childList}><li>}list-item2</li></ul></${list}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><${childList}><li>list-item2</li></${childList}></${list}>`,
+ `<${list}><${childList}><li>list-item2<br></li></${childList}></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li><${childList}><li>list-item2]</li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector("li").firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > ${childList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>[list-item1</li></${childList}><li>}list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><${childList}><li>list-item2</li></${childList}></${list}>`,
+ `<${list}><${childList}><li>list-item2<br></li></${childList}></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>[list-item1</li></${childList}><li>list-item2]</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>list-item1</li><li>[list-item2</li></${childList}><li>}list-item3</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li>list-item1</li><li>list-item3</li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li + li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li><${childList}><li>list-item2</li><li>}list-item3</li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><${childList}><li>list-item3</li></${childList}></${list}>`,
+ `<${list}><${childList}><li>list-item3<br></li></${childList}></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > ${childList} > li + li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1</li><li>[list-item2</li><${childList}><li>list-item3</li><li>}list-item4</li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><${childList}><li>list-item4</li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li + li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > ${childList} > li + li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ // Valid sub list element cases.
+ addPromiseTest(
+ `<${list}><li>[list-item1</li><li><${childList}><li>list-item2]</li></${childList}></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>[list-item1</li></${childList}><li>}list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><li><${childList}><li>list-item2</li></${childList}></li></${list}>`,
+ `<${list}><li><${childList}><li>list-item2<br></li></${childList}></li></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li + li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>[list-item1</li></${childList}><li>list-item2]</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} > li + li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} > li + li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+}
+
+// When deleting the last list item in a sub list, only the list should
+// be removed. This makes users feel like doing outdent.
+for (let childList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li><${childList}><li>{}<br></li></${childList}></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>[list-item1]</li></${childList}></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li li`).firstChild,
+ endOffset: gEditor.querySelector(`li li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>{<${childList}><li>list-item1</li></${childList}>}</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li li`).firstChild,
+ endOffset: gEditor.querySelector(`li li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>{}<br></li></${childList}></li><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li><li>list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1</li><li><${childList}><li>{}<br></li></${childList}></li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li + li`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li + li`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ // Invalid cases.
+ addPromiseTest(
+ `<${list}><${childList}><li>{}<br></li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>[list-item1]</li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li`).firstChild,
+ endOffset: gEditor.querySelector(`li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}>{<${childList}><li>list-item1</li></${childList}>}</${list}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`li`).firstChild,
+ endOffset: gEditor.querySelector(`li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>{}<br></li></${childList}><li>list-item2</li></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li><li>list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 1,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1</li><${childList}><li>{}<br></li></${childList}></${list}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list}`),
+ startOffset: 1,
+ endContainer: gEditor.querySelector(`${list}`),
+ endOffset: 2,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+}
+
+// Joining same level list elements.
+for (let otherList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><li>}list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><li>list-item2</li></${list}>`,
+ `<${list}><li>list-item2<br></li></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><li>list-item2]</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><li>}list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>first line in list-item1<br>list-item1[</li></${list}><${otherList}><li>}list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>first line in list-item1<br>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > br`).nextSibling,
+ startOffset: gEditor.querySelector(`${list} > li > br`).nextSibling.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><li>}list-item2<br>second line in list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}><${otherList}><li>second line in list-item2</li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1</li><li>list-item2[</li></${list}><${otherList}><li>}list-item3</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1</li><li>list-item2list-item3</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li + li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li + li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><li>}list-item2</li><li>list-item3</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}><${otherList}><li>list-item3</li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+}
+
+// Joining nested left list and right list element. Move the content in first line from selection end in the right
+// list item element into end of the left list item element.
+for (let childList of ["ul", "ol"]) {
+ for (let otherList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li><${childList}><li>[list-item1</li></${childList}></li></${list}><${otherList}><li>}list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><li><${childList}><li>list-item2</li></${childList}></li></${list}>`,
+ `<${list}><li><${childList}><li>list-item2<br></li></${childList}></li></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>[list-item1</li></${childList}></li></${list}><${otherList}><li>list-item2]</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li><br></li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li><${childList}><li>list-item1[</li></${childList}></li></${list}><${otherList}><li>list-item2]</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li><${childList}><li>list-item1</li></${childList}></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li > ${childList} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ // Invalid cases.
+ addPromiseTest(
+ `<${list}><${childList}><li>[list-item1</li></${childList}></${list}><${otherList}><li>}list-item2</li></${otherList}>`,
+ {
+ expectedInnerHTML: [
+ `<${list}><${childList}><li>list-item2</li></${childList}></${list}>`,
+ `<${list}><${childList}><li>list-item2<br></li></${childList}></${list}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>[list-item1</li></${childList}></${list}><${otherList}><li>list-item2]</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li><br></li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><${childList}><li>list-item1[</li></${childList}></${list}><${otherList}><li>list-item2]</li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><${childList}><li>list-item1</li></${childList}></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > ${childList} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > ${childList} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+ }
+}
+
+// Joining left list and nested right list element. Basically, the first line from the selection end should
+// be moved into the end of the left list item element, but if all content in the left list is being deleted,
+// keep the right list elements.
+for (let childList of ["ul", "ol"]) {
+ for (let otherList of ["ul", "ol"]) {
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><li><${childList}><li>}list-item2</li></${childList}></li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><li><${childList}><li>}list-item2</li></${childList}></li></${otherList}>`,
+ {
+ expectedInnerHTML: [
+ `<${otherList}><li><${childList}><li>list-item2</li></${childList}></li></${otherList}>`,
+ `<${otherList}><li><${childList}><li>list-item2<br></li></${childList}></li></${otherList}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><li><${childList}><li>list-item2]</li></${childList}></li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li > ${childList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > li > ${childList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><li><${childList}><li>}list-item2<br>second line of list-item2</li></${childList}></li></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}><${otherList}><li><${childList}><li>second line of list-item2</li></${childList}></li></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > li > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ // Invalid cases.
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><${childList}><li>}list-item2</li></${childList}></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><${childList}><li>}list-item2</li></${childList}></${otherList}>`,
+ {
+ expectedInnerHTML: [
+ `<${otherList}><${childList}><li>list-item2</li></${childList}></${otherList}>`,
+ `<${otherList}><${childList}><li>list-item2<br></li></${childList}></${otherList}>`,
+ ],
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>[list-item1</li></${list}><${otherList}><${childList}><li>list-item2]</li></${childList}></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li><br></li></${list}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: 0,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > ${childList} > li`).firstChild,
+ endOffset: gEditor.querySelector(`${list} + ${otherList} > ${childList} > li`).firstChild.length,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+
+ addPromiseTest(
+ `<${list}><li>list-item1[</li></${list}><${otherList}><${childList}><li>}list-item2<br>second line of list-item2</li></${childList}></${otherList}>`,
+ {
+ expectedInnerHTML: `<${list}><li>list-item1list-item2</li></${list}><${otherList}><${childList}><li>second line of list-item2</li></${childList}></${otherList}>`,
+ expectedTargetRanges: () => {
+ return [
+ {
+ startContainer: gEditor.querySelector(`${list} > li`).firstChild,
+ startOffset: gEditor.querySelector(`${list} > li`).firstChild.length,
+ endContainer: gEditor.querySelector(`${list} + ${otherList} > ${childList} > li`),
+ endOffset: 0,
+ },
+ ];
+ },
+ expectInputEvent: true,
+ }
+ );
+ }
+}
+
+</script>