Skip to content

Commit

Permalink
[Selection API] Add DOM Mutations removal test
Browse files Browse the repository at this point in the history
Add a tentative WPT test where we remove various DOM nodes and see its
effect on the getComposedRanges' returned StaticRanges.

Change-Id: I3d9c22b499a5a3fc4905dce2a46fa9ddaef85f45
Bug: 40286116
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5938337
Reviewed-by: Siye Liu <siliu@microsoft.com>
Commit-Queue: Di Zhang <dizhangg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370101}
  • Loading branch information
dizhang168 authored and chromium-wpt-export-bot committed Oct 17, 2024
1 parent 1e30fcf commit dcf26fe
Showing 1 changed file with 110 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html>
<body>
<meta name="author" href="mailto:dizhangg@chromium.org">
<link rel="help" href="https://w3c.github.io/selection-api/#dom-selection-getcomposedranges">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<meta name="variant" content="?mode=closed">
<meta name="variant" content="?mode=open">

<div id="container"></div>

<script>

const mode = (new URLSearchParams(document.location.search)).get("mode");

test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const host = container.querySelector('#host');
const shadowRoot = host.attachShadow({ mode });
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 2);
const rangeBefore = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] })[0];
host.remove();
const rangeAfter = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] })[0];

assert_equals(rangeBefore.startContainer, shadowRoot.firstChild, 'StaticRange does not update on new mutation.');
assert_equals(rangeBefore.startOffset, 7);
assert_equals(rangeBefore.endContainer, container);
assert_equals(rangeBefore.endOffset, 2);

assert_equals(rangeAfter.startContainer, container, 'collapsed to the host parent: container');
assert_equals(rangeAfter.startOffset, 1);
assert_equals(rangeAfter.endContainer, container);
assert_equals(rangeAfter.endOffset, 1);
}, 'Range is fully in shadow tree. Removing shadow host collapses composed StaticRange. Note it does not update previously returned composed StaticRange.');

test(() => {
container.innerHTML = '<div id="wrapper">a<div id="host"></div>b</div>';
const wrapper = container.querySelector('#wrapper');
const host = container.querySelector('#host');
const shadowRoot = host.attachShadow({ mode });
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 4, shadowRoot.firstChild, 7);
wrapper.remove();

const rangeAfter = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] })[0];
assert_equals(rangeAfter.startContainer, container, 'collapsed to parent of removed node');
assert_equals(rangeAfter.startOffset, 0);
assert_equals(rangeAfter.endContainer, container);
assert_equals(rangeAfter.endOffset, 0);
}, 'Range is fully in shadow tree. Removing parent of shadow host collapses composed StaticRange.');

test(() => {
container.innerHTML = '<div id="hello">Hello,</div><div id="world"> World</div>';
getSelection().setBaseAndExtent(hello.firstChild, 1, world.firstChild, 3);
hello.firstChild.remove();
const rangeAfter = getSelection().getComposedRanges()[0];

assert_equals(rangeAfter.startContainer, hello);
assert_equals(rangeAfter.startOffset, 0);
assert_equals(rangeAfter.endContainer, world.firstChild);
assert_equals(rangeAfter.endOffset, 3);
}, 'Range is in light DOM. Removing startContainer rescopes new composed range to its parent.');

test(() => {
container.innerHTML = 'a<div id="host"></div>b';
const host = container.querySelector('#host');
const shadowRoot = host.attachShadow({ mode });
shadowRoot.innerHTML = 'hello, world';
getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 2);
shadowRoot.innerHTML = '';
const rangeAfter = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] })[0];

assert_equals(rangeAfter.startContainer, shadowRoot, 'collapsed to be at the parent shadow root');
assert_equals(rangeAfter.startOffset, 0);
assert_equals(rangeAfter.endContainer, container);
assert_equals(rangeAfter.endOffset, 2);
}, 'Range is across shadow trees. Replacing shadowRoot content rescopes new composed range to the shadowRoot.');

test(() => {
container.innerHTML = [
'<div id=host>',
'<div id=div1 slot=slot2>slotted content 1</div>',
'<div id=div2 slot=slot1>slotted content 2</div>',
'</div>'
].join('');
const shadowRoot = host.attachShadow({mode: 'open'});
shadowRoot.innerHTML = [
'<span>before</span>',
'<slot name=slot1></slot>',
'<span>between</span>',
'<slot name=slot2></slot>',
'<span>after</span>',
].join('');

const sel = getSelection();
sel.setBaseAndExtent(div1.firstChild, 2, div2.firstChild, 2);
div1.remove();

const rangeAfter = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] })[0];
assert_equals(rangeAfter.startContainer, host);
assert_equals(rangeAfter.startOffset, 0);
assert_equals(rangeAfter.endContainer, div2.firstChild);
assert_equals(rangeAfter.endOffset, 2);
}, 'Range is between two light slotted contents. Removing start container rescopes to its parent in light tree.');

</script>
</body>
</html>

0 comments on commit dcf26fe

Please sign in to comment.