Selection-getComposedRanges.html (9857B)
1 <!DOCTYPE html> 2 <html> 3 <body> 4 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> 5 <meta name="assert" content="Selection's getComposedRanges should return a sequence of static ranges"> 6 <link rel="help" href="https://w3c.github.io/selection-api/#dom-selection-getcomposedranges"> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <div id="container"></div> 10 <script> 11 12 test(() => { 13 getSelection().removeAllRanges(); 14 assert_array_equals(getSelection().getComposedRanges(), []); 15 }, 'getComposedRanges returns an empty sequence when there is no selection'); 16 17 test(() => { 18 container.innerHTML = 'hello, world'; 19 getSelection().setBaseAndExtent(container.firstChild, 0, container.firstChild, 5); 20 assert_throws_js(TypeError, function() { 21 getSelection().getComposedRanges({ shadowRoots: [container] }); 22 }, "Failed to execute 'getComposedRanges' on arguments which don't implment ShadowRoot interface"); 23 }, 'getComposedRanges should fail if argument is not a shadow root'); 24 25 test(() => { 26 container.innerHTML = 'hello, world'; 27 getSelection().setBaseAndExtent(container.firstChild, 0, container.firstChild, 5); 28 const ranges = getSelection().getComposedRanges(); 29 assert_equals(ranges.length, 1); 30 assert_equals(ranges[0].startContainer, container.firstChild); 31 assert_equals(ranges[0].startOffset, 0); 32 assert_equals(ranges[0].endContainer, container.firstChild); 33 assert_equals(ranges[0].endOffset, 5); 34 }, 'getComposedRanges returns a sequence with a static range when there is a forward-direction selection in the document tree'); 35 36 test(() => { 37 container.innerHTML = 'hello, world'; 38 getSelection().setBaseAndExtent(container.firstChild, 4, container.firstChild, 3); 39 const ranges = getSelection().getComposedRanges(); 40 assert_equals(ranges.length, 1); 41 assert_equals(ranges[0].startContainer, container.firstChild); 42 assert_equals(ranges[0].startOffset, 3); 43 assert_equals(ranges[0].endContainer, container.firstChild); 44 assert_equals(ranges[0].endOffset, 4); 45 }, 'getComposedRanges returns a sequence with a static range when there is a backward-direction selection in the document tree'); 46 47 test(() => { 48 container.innerHTML = 'a<div id="host"></div>b'; 49 const host = container.querySelector('#host'); 50 const shadowRoot = host.attachShadow({mode: 'closed'}); 51 shadowRoot.innerHTML = 'hello, world'; 52 getSelection().setBaseAndExtent(shadowRoot.firstChild, 0, shadowRoot.firstChild, 5); 53 const ranges = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] }); 54 assert_equals(ranges.length, 1); 55 assert_equals(ranges[0].startContainer, shadowRoot.firstChild); 56 assert_equals(ranges[0].startOffset, 0); 57 assert_equals(ranges[0].endContainer, shadowRoot.firstChild); 58 assert_equals(ranges[0].endOffset, 5); 59 }, 'getComposedRanges returns a sequence with a static range pointing to a shadow tree when there is a selection in the shadow tree and the shadow tree is specified as an argument'); 60 61 test(() => { 62 container.innerHTML = 'a<div id="host"></div>b'; 63 const host = container.querySelector('#host'); 64 const shadowRoot = host.attachShadow({mode: 'closed'}); 65 shadowRoot.innerHTML = 'hello, world'; 66 getSelection().setBaseAndExtent(shadowRoot.firstChild, 0, shadowRoot.firstChild, 5); 67 const ranges = getSelection().getComposedRanges(); 68 assert_equals(ranges.length, 1); 69 assert_equals(ranges[0].startContainer, container); 70 assert_equals(ranges[0].startOffset, 1); 71 assert_equals(ranges[0].endContainer, container); 72 assert_equals(ranges[0].endOffset, 2); 73 }, 'getComposedRanges returns a sequence with a static range pointing to the shadow host when there is a selection in a shadow tree and the shadow tree is not specified as an argument'); 74 75 test(() => { 76 container.innerHTML = 'a<div id="host"></div>b'; 77 const host = container.querySelector('#host'); 78 const shadowRoot = host.attachShadow({mode: 'closed'}); 79 shadowRoot.innerHTML = 'hello, world'; 80 getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 2); 81 const ranges = getSelection().getComposedRanges(); 82 assert_equals(ranges.length, 1); 83 assert_equals(ranges[0].startContainer, container); 84 assert_equals(ranges[0].startOffset, 1); 85 assert_equals(ranges[0].endContainer, container); 86 assert_equals(ranges[0].endOffset, 2); 87 }, 'getComposedRanges a sequence with a static range pointing to the shadow host when there is a forward selection that crosses shadow boundaries and the shadow tree is not specified as an argument'); 88 89 test(() => { 90 container.innerHTML = 'a<div id="host"></div>b'; 91 const host = container.querySelector('#host'); 92 const shadowRoot = host.attachShadow({mode: 'closed'}); 93 shadowRoot.innerHTML = 'hello, world'; 94 getSelection().setBaseAndExtent(shadowRoot.firstChild, 7, container, 2); 95 const ranges = getSelection().getComposedRanges({ shadowRoots: [shadowRoot] }); 96 assert_equals(ranges.length, 1); 97 assert_equals(ranges[0].startContainer, shadowRoot.firstChild); 98 assert_equals(ranges[0].startOffset, 7); 99 assert_equals(ranges[0].endContainer, container); 100 assert_equals(ranges[0].endOffset, 2); 101 }, 'getComposedRanges a sequence with a static range that crosses shadow boundaries when there is a forward selection that crosses shadow boundaries and the shadow tree is specified as an argument'); 102 103 test(() => { 104 container.innerHTML = 'a<div id="outerHost"></div>b'; 105 const outerHost = container.querySelector('#outerHost'); 106 const outerShadowRoot = outerHost.attachShadow({mode: 'closed'}); 107 outerShadowRoot.innerHTML = '<div id="innerHost">hello</div><div>world</div>'; 108 const innerHost = outerShadowRoot.getElementById('innerHost'); 109 const innerShadowRoot = innerHost.attachShadow({mode: 'closed'}); 110 innerShadowRoot.innerHTML = 'some text'; 111 getSelection().setBaseAndExtent(innerShadowRoot.firstChild, 5, innerShadowRoot.firstChild, 9); 112 const ranges = getSelection().getComposedRanges(); 113 assert_equals(ranges.length, 1); 114 assert_equals(ranges[0].startContainer, container); 115 assert_equals(ranges[0].startOffset, 1); 116 assert_equals(ranges[0].endContainer, container); 117 assert_equals(ranges[0].endOffset, 2); 118 }, 'getComposedRanges returns a sequence with a static range pointing to the outer shadow host when there is a selection in an inner shadow tree and no shadow tree is specified as an argument'); 119 120 test(() => { 121 container.innerHTML = 'a<div id="outerHost"></div>b'; 122 const outerHost = container.querySelector('#outerHost'); 123 const outerShadowRoot = outerHost.attachShadow({mode: 'closed'}); 124 outerShadowRoot.innerHTML = '<div id="innerHost">hello</div><div>world</div>'; 125 const innerHost = outerShadowRoot.getElementById('innerHost'); 126 const innerShadowRoot = innerHost.attachShadow({mode: 'closed'}); 127 innerShadowRoot.innerHTML = 'some text'; 128 getSelection().setBaseAndExtent(innerShadowRoot.firstChild, 5, innerShadowRoot.firstChild, 9); 129 const ranges = getSelection().getComposedRanges({ shadowRoots: [innerShadowRoot] }); 130 assert_equals(ranges.length, 1); 131 assert_equals(ranges[0].startContainer, innerShadowRoot.firstChild); 132 assert_equals(ranges[0].startOffset, 5); 133 assert_equals(ranges[0].endContainer, innerShadowRoot.firstChild); 134 assert_equals(ranges[0].endOffset, 9); 135 }, 'getComposedRanges returns a sequence with a static range pointing to the inner shadow tree when there is a selection in an inner shadow tree and the inner shadow tree is specified as an argument'); 136 137 test(() => { 138 container.innerHTML = 'a<div id="outerHost"></div>b'; 139 const outerHost = container.querySelector('#outerHost'); 140 const outerShadowRoot = outerHost.attachShadow({mode: 'closed'}); 141 outerShadowRoot.innerHTML = '<div id="innerHost">hello</div><div>world</div>'; 142 const innerHost = outerShadowRoot.getElementById('innerHost'); 143 const innerShadowRoot = innerHost.attachShadow({mode: 'closed'}); 144 innerShadowRoot.innerHTML = 'some text'; 145 getSelection().setBaseAndExtent(innerShadowRoot.firstChild, 5, innerShadowRoot.firstChild, 9); 146 const ranges = getSelection().getComposedRanges({ shadowRoots: [outerShadowRoot] }); 147 assert_equals(ranges.length, 1); 148 assert_equals(ranges[0].startContainer, outerShadowRoot); 149 assert_equals(ranges[0].startOffset, 0); 150 assert_equals(ranges[0].endContainer, outerShadowRoot); 151 assert_equals(ranges[0].endOffset, 1); 152 }, 'getComposedRanges returns a sequence with a static range pointing to the outer shadow tree when there is a selection in an inner shadow tree and the outer shadow tree is specified as an argument'); 153 154 test(() => { 155 container.innerHTML = 'a<div id="outerHost"></div>b'; 156 const outerHost = container.querySelector('#outerHost'); 157 const outerShadowRoot = outerHost.attachShadow({mode: 'closed'}); 158 outerShadowRoot.innerHTML = '<div id="innerHost">hello</div><div>world</div>'; 159 const innerHost = outerShadowRoot.getElementById('innerHost'); 160 const innerShadowRoot = innerHost.attachShadow({mode: 'closed'}); 161 innerShadowRoot.innerHTML = 'some text'; 162 getSelection().setBaseAndExtent(container.firstChild, 0, outerShadowRoot, 0); 163 const ranges = getSelection().getComposedRanges({ shadowRoots: [innerShadowRoot] }); 164 assert_equals(ranges.length, 1); 165 assert_equals(ranges[0].startContainer, container.firstChild); 166 assert_equals(ranges[0].startOffset, 0); 167 assert_equals(ranges[0].endContainer, outerShadowRoot); 168 assert_equals(ranges[0].endOffset, 0); 169 }, 'getComposedRanges returns a sequence with a static range without rescoping when there is a selection in an outer shadow tree and the inner shadow tree is specified as an argument'); 170 171 </script> 172 </body> 173 </html>