Bug 1676295 - Add WPT to test deleting in/around/across list items r=smaug

There are not enough tests comparing delete operation result and result of
`getTargetRanges()` when selection is in/around/across list item elements.
This patch creates a utility method to make the test body not need to use
Selection API for making simpler tests.

The expected behavior is based on Blink and WebKit unless their behavior is
buggy because their behavior is more reasonable than Gecko's in most cases.

Note that the removing tests are covered by the new tests.

Differential Revision: https://phabricator.services.mozilla.com/D96800
This commit is contained in:
Masayuki Nakano 2020-11-14 10:30:31 +00:00
parent 5f2e68c256
commit 1edcd70cdd
9 changed files with 7773 additions and 67 deletions

View File

@ -70,7 +70,6 @@ skip-if = headless
[test_bug483651.html]
[test_bug484181.html]
skip-if = toolkit == 'android'
[test_bug487524.html]
[test_bug490879.html]
skip-if = toolkit == 'android' || headless # bug 1299578
[test_bug502673.html]

View File

@ -1,64 +0,0 @@
<!DOCTYPE HTML>
<html><head>
<title>Test for bug 487524</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script class="testbody" type="application/javascript">
function runTest() {
function setupIframe(e, html, focus_id) {
var doc = e.contentDocument;
doc.body.innerHTML = html;
doc.designMode = "on";
e = doc.getElementById(focus_id);
doc.defaultView.focus();
if (e) e.focus();
return e;
}
var i1 = document.getElementById("i1");
var li1 = setupIframe(i1, '<ul><li id="li1">one</li><li>two</li><ul><li>a</li></ul></ul>', "li1");
var doc = li1.ownerDocument;
var selection = doc.defaultView.getSelection();
selection.removeAllRanges();
var range = doc.createRange();
range.setStart(li1, 0);
range.setEnd(li1.nextSibling, 0);
selection.addRange(range);
sendKey("delete");
is(doc.body.innerHTML, "<ul><li>two</li><ul><li>a</li></ul></ul>", "delete 1st LI");
var li2 = setupIframe(i1, '<ul><li id="li2">two</li><ul><li>a</li></ul></ul>', "li2");
selection = doc.defaultView.getSelection();
selection.removeAllRanges();
range = doc.createRange();
range.setStart(li2, 0);
range.setEnd(li2.nextSibling.firstChild, 0);
selection.addRange(range);
sendKey("delete");
is(doc.body.innerHTML, "<ul><ul><li>a</li></ul></ul>", "delete 2nd LI");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(runTest);
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=487524">Mozilla Bug 487524</a>
<p id="display"></p>
<pre id="test">
</pre>
<iframe id="i1" width="200" height="100" src="about:blank"></iframe><br>
</body>
</html>

View File

@ -0,0 +1,737 @@
[input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Delete]
max-asserts: 17
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dd>list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dt>list-item2</dt><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>list-item2[\]</dt></dl><ol><li>list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dt>list-item2</dt><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dd>list-item2</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dd>list-item2</dd><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dt>list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>list-item2[\]</dt></dl><ul><li>list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dd>list-item2</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dt>list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dt>list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dd>list-item2</dd><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dt>list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dd>list-item2</dd><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>list-item2[\]</dt></dl><ul><li>list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dd>list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>list-item2[\]</dd></dl><ul><li>list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dd>list-item2</dd><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dt>list-item2</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dt>list-item2</dt><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>list-item2[\]</dd></dl><ul><li>list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ol><li>list-item1[</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[</li></ul><dl><dt>list-item2</dt><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dd>list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>list-item2[\]</dd></dl><ol><li>list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ol><li>list-item1[\]</li></ol><dl><dt>list-item2</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>list-item2[\]</dt></dl><ol><li>list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Delete at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dd>list-item2[\]</dd></dl><ol><li>list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Delete at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<ul><li>list-item1[\]</li></ul><dl><dd>list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Delete at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html?Backspace]
max-asserts: 17
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt}>list-item2</dt></dl><ul><li>[\]list-item3</li></ul>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dt>list-item2</dt><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt}>list-item2</dt></dl><ol><li>[\]list-item3</li></ol>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt}>list-item2</dt></dl><ol><li>[\]list-item3</li></ol>"]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dd>list-item2</dd><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>"]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dt>list-item2</dt><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd}>list-item2</dd></dl><ul><li>[\]list-item3</li></ul>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dd>[\]list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dt>list-item2</dt><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd}>list-item2</dd></dl><ol><li>[\]list-item3</li></ol>"]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dt>[\]list-item2</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd}>list-item2</dd></dl><ol><li>[\]list-item3</li></ol>"]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dt>list-item2</dt></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt>[list-item2</dt></dl><ul><li>}list-item3</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ul><li>list-item3\]</li></ul>"]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dd>list-item2</dd><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dd>[list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dd>}list-item2</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dt>[list-item2</dt></dl><ol><li>}list-item3</li></ol>"]
expected: FAIL
[Backspace at "<ol><li>list-item1</li></ol><dl><dd>[\]list-item2</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ul><li>list-item3\]</li></ul>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dt>}list-item2</dt><dd>list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>list-item2\]</dt><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dd>}list-item2</dd><dt>list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dd>list-item1</dd><dd}>list-item2</dd></dl><ul><li>[\]list-item3</li></ul>"]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dd>list-item2</dd><dd>}list-item3</dd></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>[list-item1</li></ul><dl><dd>list-item2\]</dd><dd>list-item3</dd></dl>"]
expected: FAIL
[Backspace at "<dl><dd>[list-item1</dd><dt>list-item2</dt></dl><ol><li>list-item3\]</li></ol>"]
expected: FAIL
[Backspace at "<dl><dt>[list-item1</dt><dd>list-item2</dd></dl><ol><li>list-item3\]</li></ol>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ol><li>[list-item1</li></ol><dl><dt>}list-item2</dt><dt>list-item3</dt></dl>"]
expected: FAIL
[Backspace at "<ol><li>list-item1[</li></ol><dl><dt>list-item2</dt><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1[</li></ul><dl><dd>list-item2</dd><dt>}list-item3</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<ul><li>list-item1</li></ul><dl><dt>[\]list-item2</dt></dl>" - comparing innerHTML]
expected: FAIL
[Backspace at "<dl><dt>list-item1</dt><dt}>list-item2</dt></dl><ul><li>[\]list-item3</li></ul>"]
expected: FAIL

View File

@ -0,0 +1,285 @@
<!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>

View File

@ -0,0 +1,605 @@
<!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 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 = 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}"`);
}
// Join left list element and right list element, both have one item.
function test_join_1_1(leftItem, rightItem) {
addPromiseTest(
action === "Backspace"
? `<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItem}>[]list-item2</${rightItem}></dl>`
: `<dl><${leftItem}>list-item1[]</${leftItem}></dl><dl><${rightItem}>list-item2</${rightItem}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl>`,
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItem}>}list-item2</${rightItem}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl>`,
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItem}>}list-item2</${rightItem}></dl>`,
{
expectedInnerHTML:
leftItem === "dt" && rightItem === "dd"
? [
`<dl><${rightItem}>list-item2</${rightItem}></dl>`,
`<dl><${rightItem}>list-item2<br></${rightItem}></dl>`,
]
: [
`<dl><${leftItem}>list-item2</${leftItem}></dl>`,
`<dl><${leftItem}>list-item2<br></${leftItem}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItem}>list-item2]</${rightItem}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1</${leftItem}></dl>`,
`<dl><${leftItem}>list-item1<br></${leftItem}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItem}>list-item2]</${rightItem}></dl>`,
{
expectedInnerHTML: `<dl><${leftItem}><br></${leftItem}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
}
// Join left list element which has 2 items and right list element which has one item.
function test_join_2_1(leftItems, rightItem) {
addPromiseTest(
action === "Backspace"
? `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItem}>[]list-item3</${rightItem}></dl>`
: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[]</${leftItems[1]}></dl><dl><${rightItem}>list-item3</${rightItem}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
{
expectedInnerHTML:
leftItems[1] === "dt" && rightItem === "dd"
? [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItem}>list-item3</${rightItem}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItem}>list-item3<br></${rightItem}></dl>`,
]
: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3</${leftItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3<br></${leftItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItem}>}list-item3</${rightItem}></dl>`,
{
expectedInnerHTML:
leftItems[0] === "dt" && rightItem === "dd"
? [
`<dl><${rightItem}>list-item3</${rightItem}></dl>`,
`<dl><${rightItem}>list-item3<br></${rightItem}></dl>`,
]
: [
`<dl><${leftItems[0]}>list-item3</${leftItems[0]}></dl>`,
`<dl><${leftItems[0]}>list-item3<br></${leftItems[0]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItem}>list-item3]</${rightItem}></dl>`,
{
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItem}>list-item3]</${rightItem}></dl>`,
{
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}><br></${leftItems[1]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItem}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
}
// Join left list element which has one item and right list element which has 2 items.
function test_join_1_2(leftItem, rightItems) {
addPromiseTest(
action === "Backspace"
? `<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItems[0]}>[]list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`
: `<dl><${leftItem}>list-item1[]</${leftItem}></dl><dl><${rightItems[0]}>list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItems[0]}>}list-item2</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1list-item2</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
`<dl><${leftItem}>list-item1list-item2<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>list-item1[</${leftItem}></dl><dl><${rightItems[0]}>list-item2]</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItem}>list-item1</${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
`<dl><${leftItem}>list-item1<br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}</dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: gEditor.querySelector(`${leftItem}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItems[0]}>list-item2]</${rightItems[0]}><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
{
expectedInnerHTML: `<dl><${leftItem}><br></${leftItem}></dl><dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItem}>[list-item1</${leftItem}></dl><dl><${rightItems[0]}>list-item2</${rightItems[0]}><${rightItems[1]}>}list-item3</${rightItems[1]}></dl>`,
{
expectedInnerHTML:
leftItem === "dt" && rightItems[1] === "dd"
? [
`<dl><${rightItems[1]}>list-item3</${rightItems[1]}></dl>`,
`<dl><${rightItems[1]}>list-item3<br></${rightItems[1]}></dl>`,
]
: [
`<dl><${leftItem}>list-item3</${leftItem}></dl>`,
`<dl><${leftItem}>list-item3<br></${leftItem}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItem}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
}
// Join left list element and right list element, both have 2 items.
function test_join_2_2(leftItems, rightItems) {
addPromiseTest(
action === "Backspace"
? `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>[]list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`
: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[]</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
// XXX This and next one's expectation come from Blink's behavior.
// I'm not sure whether this is intentional complicated handling
// or not.
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML:
leftItems[1] === "dt" && rightItems[0] === "dd"
? [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}></dl><dl><${rightItems[0]}>list-item3<br></${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
]
: [
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item3<br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>}list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML:
leftItems[0] === "dt" && rightItems[0] === "dd"
? [
`<dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${rightItems[0]}>list-item3<br></${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
]
: [
`<dl><${leftItems[0]}>list-item3</${leftItems[0]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
`<dl><${leftItems[0]}>list-item3<br></${leftItems[0]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
],
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`),
endOffset: 0,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2[</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3]</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild.length,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}>[list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3]</${rightItems[0]}><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
{
expectedInnerHTML: `<dl><${leftItems[0]}>list-item1</${leftItems[0]}><${leftItems[1]}><br></${leftItems[1]}></dl><dl><${rightItems[1]}>list-item4</${rightItems[1]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]} + ${leftItems[1]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
addPromiseTest(
`<dl><${leftItems[0]}>[list-item1</${leftItems[0]}><${leftItems[1]}>list-item2</${leftItems[1]}></dl><dl><${rightItems[0]}>list-item3</${rightItems[0]}><${rightItems[1]}>list-item4]</${rightItems[1]}></dl>`,
{
expectedInnerHTML: `<dl><${leftItems[0]}><br></${leftItems[0]}></dl>`,
expectedTargetRanges: () => {
return [
{
startContainer: gEditor.querySelector(`${leftItems[0]}`).firstChild,
startOffset: 0,
endContainer: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`).firstChild,
endOffset: gEditor.querySelector(`dl + dl > ${rightItems[0]} + ${rightItems[1]}`).firstChild.length,
},
];
},
expectInputEvent: true,
}
);
}
// Joining dl elements
for (let listItem1 of ["dt", "dd"]) {
for (let listItem2 of ["dt", "dd"]) {
test_join_1_1(listItem1, listItem2);
for (let listItem3 of ["dt", "dd"]) {
test_join_2_1([listItem1, listItem2], listItem3);
test_join_1_2(listItem1, [listItem2, listItem3]);
for (let listItem4 of ["dt", "dd"]) {
test_join_2_2([listItem1, listItem2], [listItem3, listItem4]);
}
}
}
}
</script>

View File

@ -46,8 +46,7 @@ function initializeTest(aInnerHTML) {
gEditor.addEventListener("input", onInput);
}
gEditor.innerHTML = aInnerHTML;
gEditor.focus();
setupEditor(aInnerHTML);
gBeforeinput = [];
gInput = [];
}
@ -251,3 +250,267 @@ function checkEditorContentResultAsSubTest(
}
}, `${description} - comparing innerHTML`);
}
// Similar to `setupDiv` in editing/include/tests.js, this method sets
// innerHTML value of gEditor, and sets multiple selection ranges specified
// with the markers.
// - `[` specifies start boundary in a text node
// - `{` specifies start boundary before a node
// - `]` specifies end boundary in a text node
// - `}` specifies end boundary after a node
function setupEditor(innerHTMLWithRangeMarkers) {
const startBoundaries = innerHTMLWithRangeMarkers.match(/\{|\[/g) || [];
const endBoundaries = innerHTMLWithRangeMarkers.match(/\}|\]/g) || [];
if (startBoundaries.length !== endBoundaries.length) {
throw "Should match number of open/close markers";
}
gEditor.innerHTML = innerHTMLWithRangeMarkers;
gEditor.focus();
if (startBoundaries.length === 0) {
// Don't remove the range for now since some tests may assume that
// setting innerHTML does not remove all selection ranges.
return;
}
function getNextRangeAndDeleteMarker(startNode) {
function getNextLeafNode(node) {
function inclusiveDeepestFirstChildNode(container) {
while (container.firstChild) {
container = container.firstChild;
}
return container;
}
if (node.hasChildNodes()) {
return inclusiveDeepestFirstChildNode(node);
}
if (node.nextSibling) {
return inclusiveDeepestFirstChildNode(node.nextSibling);
}
let nextSibling = (function nextSiblingOfAncestorElement(child) {
for (
let parent = child.parentElement;
parent && parent != gEditor;
parent = parent.parentElement
) {
if (parent.nextSibling) {
return parent.nextSibling;
}
}
return null;
})(node);
if (!nextSibling) {
return null;
}
return inclusiveDeepestFirstChildNode(nextSibling);
}
function scanMarkerInTextNode(textNode, offset) {
return /[\{\[\]\}]/.exec(textNode.data.substr(offset));
}
let startMarker = (function scanNextStartMaker(
startContainer,
startOffset
) {
function scanStartMakerInTextNode(textNode, offset) {
let scanResult = scanMarkerInTextNode(textNode, offset);
if (scanResult === null) {
return null;
}
if (scanResult[0] === "}" || scanResult[0] === "]") {
throw "An end marker is found before a start marker";
}
return {
marker: scanResult[0],
container: textNode,
offset: scanResult.index + offset,
};
}
if (startContainer.nodeType === Node.TEXT_NODE) {
let scanResult = scanStartMakerInTextNode(startContainer, startOffset);
if (scanResult !== null) {
return scanResult;
}
}
let nextNode = startContainer;
while ((nextNode = getNextLeafNode(nextNode))) {
if (nextNode.nodeType === Node.TEXT_NODE) {
let scanResult = scanStartMakerInTextNode(nextNode, 0);
if (scanResult !== null) {
return scanResult;
}
continue;
}
}
return null;
})(startNode, 0);
if (startMarker === null) {
return null;
}
let endMarker = (function scanNextEndMarker(startContainer, startOffset) {
function scanEndMarkerInTextNode(textNode, offset) {
let scanResult = scanMarkerInTextNode(textNode, offset);
if (scanResult === null) {
return null;
}
if (scanResult[0] === "{" || scanResult[0] === "[") {
throw "A start marker is found before an end marker";
}
return {
marker: scanResult[0],
container: textNode,
offset: scanResult.index + offset,
};
}
if (startContainer.nodeType === Node.TEXT_NODE) {
let scanResult = scanEndMarkerInTextNode(startContainer, startOffset);
if (scanResult !== null) {
return scanResult;
}
}
let nextNode = startContainer;
while ((nextNode = getNextLeafNode(nextNode))) {
if (nextNode.nodeType === Node.TEXT_NODE) {
let scanResult = scanEndMarkerInTextNode(nextNode, 0);
if (scanResult !== null) {
return scanResult;
}
continue;
}
}
return null;
})(startMarker.container, startMarker.offset + 1);
if (endMarker === null) {
throw "Found an open marker, but not found corresponding close marker";
}
function indexOfContainer(container, child) {
let offset = 0;
for (let node = container.firstChild; node; node = node.nextSibling) {
if (node == child) {
return offset;
}
offset++;
}
throw "child must be a child node of container";
}
(function deleteFoundMarkers() {
function removeNode(node) {
let container = node.parentElement;
let offset = indexOfContainer(container, node);
node.remove();
return { container, offset };
}
if (startMarker.container == endMarker.container) {
// If the text node becomes empty, remove it and set collapsed range
// to the position where there is the text node.
if (startMarker.container.length === 2) {
if (!/[\[\{][\]\}]/.test(startMarker.container.data)) {
throw `Unexpected text node (data: "${startMarker.container.data}")`;
}
let { container, offset } = removeNode(startMarker.container);
startMarker.container = endMarker.container = container;
startMarker.offset = endMarker.offset = offset;
startMarker.marker = endMarker.marker = "";
return;
}
startMarker.container.data = `${startMarker.container.data.substring(
0,
startMarker.offset
)}${startMarker.container.data.substring(
startMarker.offset + 1,
endMarker.offset
)}${startMarker.container.data.substring(endMarker.offset + 1)}`;
if (startMarker.offset >= startMarker.container.length) {
startMarker.offset = endMarker.offset = startMarker.container.length;
return;
}
endMarker.offset--; // remove the start marker's length
if (endMarker.offset > endMarker.container.length) {
endMarker.offset = endMarker.container.length;
}
return;
}
if (startMarker.container.length === 1) {
let { container, offset } = removeNode(startMarker.container);
startMarker.container = container;
startMarker.offset = offset;
startMarker.marker = "";
} else {
startMarker.container.data = `${startMarker.container.data.substring(
0,
startMarker.offset
)}${startMarker.container.data.substring(startMarker.offset + 1)}`;
}
if (endMarker.container.length === 1) {
let { container, offset } = removeNode(endMarker.container);
endMarker.container = container;
endMarker.offset = offset;
endMarker.marker = "";
} else {
endMarker.container.data = `${endMarker.container.data.substring(
0,
endMarker.offset
)}${endMarker.container.data.substring(endMarker.offset + 1)}`;
}
})();
(function handleNodeSelectMarker() {
if (startMarker.marker === "{") {
if (startMarker.offset === 0) {
// The range start with the text node.
let container = startMarker.container.parentElement;
startMarker.offset = indexOfContainer(
container,
startMarker.container
);
startMarker.container = container;
} else if (startMarker.offset === startMarker.container.data.length) {
// The range start after the text node.
let container = startMarker.container.parentElement;
startMarker.offset =
indexOfContainer(container, startMarker.container) + 1;
startMarker.container = container;
} else {
throw 'Start marker "{" is allowed start or end of a text node';
}
}
if (endMarker.marker === "}") {
if (endMarker.offset === 0) {
// The range ends before the text node.
let container = endMarker.container.parentElement;
endMarker.offset = indexOfContainer(container, endMarker.container);
endMarker.container = container;
} else if (endMarker.offset === endMarker.container.data.length) {
// The range ends with the text node.
let container = endMarker.container.parentElement;
endMarker.offset =
indexOfContainer(container, endMarker.container) + 1;
endMarker.container = container;
} else {
throw 'End marker "}" is allowed start or end of a text node';
}
}
})();
let range = document.createRange();
range.setStart(startMarker.container, startMarker.offset);
range.setEnd(endMarker.container, endMarker.offset);
return range;
}
let ranges = [];
for (
let range = getNextRangeAndDeleteMarker(gEditor.firstChild);
range;
range = getNextRangeAndDeleteMarker(range.endContainer)
) {
ranges.push(range);
}
gSelection.removeAllRanges();
for (let range of ranges) {
gSelection.addRange(range);
}
if (gSelection.rangeCount != ranges.length) {
throw `Failed to set selection to the given ranges whose length is ${ranges.length}, but only ${gSelection.rangeCount} ranges are added`;
}
}