| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <meta name="timeout" content="long"> | |
| <meta name="variant" content="?Backspace"> | |
| <meta name="variant" content="?Delete"> | |
| <title>InputEvent.getTargetRanges() at joining dl element and ol or ul element</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 = location.search.substring(1); | |
| 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}"`); | |
| } | |
| // TODO: This file does not have tests for the cases joining dl elements and | |
| // parent or child ul/ol elements. They should be added, but perhaps, | |
| // they are edge cases. | |
| // Joining dl with ul/ol list element | |
| for (let otherList of ["ul", "ol"]) { | |
| for (let firstItem of ["dt", "dd"]) { | |
| addPromiseTest( | |
| action === "Backspace" | |
| ? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}></dl>` | |
| : `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}></dl>`, | |
| { | |
| expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: gEditor.querySelector("li").firstChild.length, | |
| endContainer: gEditor.querySelector(firstItem).firstChild, | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| for (let secondItem of ["dt", "dd"]) { | |
| addPromiseTest( | |
| action === "Backspace" | |
| ? `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}}>list-item2</${secondItem}></dl><${otherList}><li>[]list-item3</li></${otherList}>` | |
| : `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2[]</${secondItem}></dl><${otherList}><li>list-item3</li></${otherList}>`, | |
| { | |
| expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2list-item3</${secondItem}></dl>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild, | |
| startOffset: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild.length, | |
| endContainer: gEditor.querySelector("li").firstChild, | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>}list-item3</li></${otherList}>`, | |
| { | |
| expectedInnerHTML: | |
| secondItem === "dt" | |
| ? [ | |
| `<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3</li></${otherList}>`, | |
| `<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3<br></li></${otherList}>`, | |
| ] | |
| : [ | |
| `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, | |
| `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3<br></${secondItem}></dl>`, | |
| ], | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild, | |
| startOffset: 0, | |
| endContainer: gEditor.querySelector("li"), | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`, | |
| { | |
| expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}><br></${secondItem}></dl>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector(secondItem).firstChild, | |
| startOffset: 0, | |
| endContainer: gEditor.querySelector("li").firstChild, | |
| endOffset: gEditor.querySelector("li").firstChild.length, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<dl><${firstItem}>[list-item1</${firstItem}><${secondItem}>list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`, | |
| { | |
| expectedInnerHTML: `<dl><${firstItem}><br></${firstItem}></dl>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector(firstItem).firstChild, | |
| startOffset: 0, | |
| endContainer: gEditor.querySelector("li").firstChild, | |
| endOffset: gEditor.querySelector("li").firstChild.length, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| action === "Backspace" | |
| ? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>` | |
| : `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, | |
| { | |
| expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: gEditor.querySelector("li").firstChild.length, | |
| endContainer: gEditor.querySelector(firstItem).firstChild, | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, | |
| { | |
| expectedInnerHTML: [ | |
| `<${otherList}><li>list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| `<${otherList}><li>list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| ], | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: 0, | |
| endContainer: gEditor.querySelector(firstItem), | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>list-item2]</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, | |
| { | |
| expectedInnerHTML: `<${otherList}><li><br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: 0, | |
| endContainer: gEditor.querySelector(firstItem).firstChild, | |
| endOffset: gEditor.querySelector(firstItem).firstChild.length, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, | |
| { | |
| expectedInnerHTML: [ | |
| `<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| `<${otherList}><li>list-item1list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, | |
| ], | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: gEditor.querySelector("li").firstChild.length, | |
| endContainer: gEditor.querySelector(firstItem), | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| addPromiseTest( | |
| `<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>}list-item3</${secondItem}></dl>`, | |
| { | |
| expectedInnerHTML: [ | |
| `<${otherList}><li>list-item1list-item3</li></${otherList}>`, | |
| `<${otherList}><li>list-item1list-item3<br></li></${otherList}>`, | |
| ], | |
| expectedTargetRanges: () => { | |
| return [ | |
| { | |
| startContainer: gEditor.querySelector("li").firstChild, | |
| startOffset: gEditor.querySelector("li").firstChild.length, | |
| endContainer: gEditor.querySelector(secondItem), | |
| endOffset: 0, | |
| }, | |
| ]; | |
| }, | |
| expectInputEvent: true, | |
| } | |
| ); | |
| } | |
| } | |
| } | |
| </script> |