test_find.html (8838B)
1 <!doctype html> 2 <meta charset="utf-8"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <body> 6 <script> 7 const t = async_test("Test window.find / nsFind"); 8 9 function testFindable(findCount, textToFind, buildDoc, description) { 10 if (typeof findCount == "boolean") 11 findCount = findCount ? 1 : 0; 12 try { 13 const iframe = document.querySelector("iframe") 14 iframe.contentDocument.documentElement.innerHTML = 15 (typeof buildDoc == "string") ? buildDoc : ""; 16 17 if (typeof buildDoc == "function") 18 buildDoc(iframe.contentDocument); 19 20 iframe.contentWindow.getSelection().removeAllRanges(); 21 for (let i = findCount; i >= 0; --i) { 22 const expectFindable = i != 0; 23 assert_equals( 24 iframe.contentWindow.find(textToFind), 25 expectFindable, 26 "Should be " + (expectFindable ? "" : "not ") + "findable: " + description + ", text: " + textToFind + ", iter: " + (findCount - i + 1) 27 ); 28 } 29 30 } catch (ex) { 31 assert_unreached(ex); 32 } 33 } 34 35 const INLINE_LIKE_DISPLAY_VALUES = [ 36 "inline", 37 "inline-grid", 38 "inline-block", 39 "inline-flex", 40 ]; 41 42 const BLOCK_LIKE_DISPLAY_VALUES = [ 43 "block", 44 "flex", 45 "grid", 46 "list-item", 47 "table-column-group", 48 "table-column", 49 "table-footer-group", 50 "table-header-group", 51 "table-row-group", 52 "table-row", 53 "table", 54 ]; 55 56 let runTests = t.step_func_done(function() { 57 testFindable(true, "me and me", ` 58 me <div style="display: contents">and</div> me 59 `, "display: contents"); 60 61 testFindable(true, "me me", ` 62 me <div style="display: none">and</div> me 63 `, "display: none"); 64 65 testFindable(false, "me and me", ` 66 me <div style="display: none">and</div> me 67 `, "display: none"); 68 69 for (const display of INLINE_LIKE_DISPLAY_VALUES) { 70 testFindable(true, "me and me", ` 71 me <div style="display: ${display}">and</div> me 72 `, "div display: " + display); 73 testFindable(true, "me and me", ` 74 me <span style="display: ${display}">and</span> me 75 `, "span display: " + display); 76 } 77 78 for (const display of BLOCK_LIKE_DISPLAY_VALUES) { 79 testFindable(false, "me and me", ` 80 me <div style="display: ${display}">and</div> me 81 `, "div display: " + display); 82 testFindable(false, "me and me", ` 83 me <span style="display: ${display}">and</span> me 84 `, "span display: " + display); 85 } 86 87 testFindable(false, "me and me", ` 88 me <fieldset>and</fieldset> me 89 `); 90 91 testFindable(true, "This text should be visible", ` 92 <div style="visibility: hidden"> 93 <div style="visibility: visible"> 94 This text should be visible 95 </div> 96 </div> 97 `); 98 99 testFindable(true, "This text should be visible", ` 100 <style>:root { overflow: hidden }</style> 101 <div style="overflow: auto;"> 102 <div style="height: 300vh"></div> 103 This text should be visible 104 </div> 105 `); 106 107 testFindable(true, "foobar", ` 108 <body><script style="display: block;">foobar</` + `script></body> 109 `); 110 111 112 testFindable(true, "Shadow text", function(document) { 113 let div = document.createElement("div"); 114 div.attachShadow({ mode: "open" }).innerHTML = ` 115 Wohoo, this is Shadow text, yay! 116 `; 117 document.documentElement.appendChild(div); 118 }, "In Shadow DOM"); 119 120 testFindable(true, "Shadow text", function(document) { 121 let div = document.createElement("div"); 122 div.appendChild(document.createTextNode( 123 "Wohoo, this is Shadow text, yay!" 124 )); 125 div.attachShadow({ mode: "open" }).innerHTML = `<slot></slot>`; 126 document.documentElement.appendChild(div); 127 }, "Slotted content in Shadow DOM"); 128 129 // TODO(emilio): This should work in an ideal world. 130 testFindable(false, "Shadow text", function(document) { 131 let div = document.createElement("div"); 132 div.appendChild(document.createTextNode("text, yay!")); 133 div.attachShadow({ mode: "open" }).innerHTML = `This is Shadow <slot></slot>`; 134 document.documentElement.appendChild(div); 135 }, "Mixed shadow and non-shadow text"); 136 137 testFindable(true, "Shadow", function(document) { 138 document.documentElement.innerHTML = ` 139 Sources<span id="host"></span> 140 <div>whatever</div> 141 `; 142 document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "Shadow text"; 143 }, "Test inside a shadow-root mid-match"); 144 145 testFindable(false, "Outside shadow", function(document) { 146 document.documentElement.innerHTML = ` 147 Outside <div id="host"></div> shadow 148 `; 149 document.getElementById("host").attachShadow({ mode: "open" }).innerHTML = "inside shadow"; 150 }, "Block in different subtree"); 151 152 // NOTE(emilio): It is probably doable / worth changing this to return true, 153 // maybe, by relaxing the security checks in the ranges nsFind returns or 154 // such. 155 // 156 // See bug 1442466 / bug 1510485 / bug 1505887. 157 testFindable(false, "foo", function(document) { 158 let input = document.createElement("input"); 159 input.value = "foo"; 160 document.documentElement.appendChild(input); 161 }, "Native anonymous content isn't exposed in window.find"); 162 163 // Same as above, but in this case the check is warranted, we shouldn't 164 // expose this range. 165 testFindable(false, "find me", ` 166 <style>div::before { content: "Do find me" }</style> 167 <div></div> 168 `, "Pseudo-element"); 169 170 // Same as above. 171 testFindable(false, "find me", ` 172 <img alt="Do find me"> 173 `, "Image alt content"); 174 175 // Same as above. 176 testFindable(false, "find me", ` 177 <input type="submit" value="Do find me"> 178 `, "Submit input value"); 179 180 testFindable(false, "\0", ` 181 � 182 `); 183 184 testFindable(true, "\0", function(document) { 185 document.documentElement.appendChild(document.createTextNode("\0")); 186 }, "Inserted null characters are findable"); 187 188 testFindable(false, "ab", `a<br>b`, "<br> forces a break even if there's no whitespace in between"); 189 190 testFindable(true, "history.kafka", ` 191 <code>database.history​.kafka.bootstrap.servers</code> 192 `, "ZWSP should be ignored"); 193 194 testFindable(2, " ", "a b c", "Collapsed whitespace"); 195 196 // TODO(emilio): This might be worth discussing in the spec. For now 197 // hard-coding our implementation. 198 testFindable(false, "find me", ` 199 Do you find <span inert>not findable</span> me? 200 `, "boundary-crossing inert"); 201 202 testFindable(true, "hidden content", ` 203 <div hidden="until-found">This is hidden content</div> 204 `, "hidden=until-found should be findable"); 205 206 testFindable(true, "details content", ` 207 <details> 208 <summary>Click to expand</summary> 209 <div>This is details content</div> 210 </details> 211 `, "closed details should be findable"); 212 213 promise_test(async function() { 214 const iframe = document.querySelector("iframe"); 215 iframe.contentDocument.documentElement.innerHTML = ` 216 <div id="hidden" hidden="until-found">findable text</div> 217 `; 218 219 const beforematchPromise = new Promise(resolve => { 220 iframe.contentDocument.getElementById("hidden").addEventListener("beforematch", () => { 221 resolve(); 222 }, { once: true }); 223 }); 224 225 iframe.contentWindow.getSelection().removeAllRanges(); 226 const found = iframe.contentWindow.find("findable"); 227 228 assert_true(found, "Should find text in hidden=until-found"); 229 230 await beforematchPromise; 231 232 await new Promise(resolve => iframe.contentWindow.requestAnimationFrame(resolve)); 233 234 const hiddenElement = iframe.contentDocument.getElementById("hidden"); 235 assert_equals(hiddenElement.hidden, false, "hidden attribute should be removed"); 236 }, "beforematch event fires and element is revealed for hidden=until-found"); 237 238 testFindable(false, "should not be found", ` 239 <style>#outer { content-visibility: hidden; }</style> 240 <div id="outer"> 241 <div hidden="until-found">This should not be found</div> 242 </div> 243 `, "hidden=until-found inside content-visibility:hidden should not be findable"); 244 245 promise_test(async function() { 246 const iframe = document.querySelector("iframe"); 247 iframe.contentDocument.documentElement.innerHTML = ` 248 <details id="details"> 249 <summary>Summary</summary> 250 <div>Details text</div> 251 </details> 252 `; 253 254 iframe.contentWindow.getSelection().removeAllRanges(); 255 const found = iframe.contentWindow.find("Details text"); 256 257 assert_true(found, "Should find text in closed details"); 258 259 await new Promise(resolve => iframe.contentWindow.requestAnimationFrame(resolve)); 260 261 const detailsElement = iframe.contentDocument.getElementById("details"); 262 assert_true(detailsElement.open, "details element should be opened after find"); 263 }, "details element is opened after find"); 264 }); 265 266 window.onload = function() { 267 let iframe = document.createElement("iframe"); 268 iframe.onload = runTests; 269 iframe.srcdoc = "<!doctype html><html></html>"; 270 document.body.appendChild(iframe); 271 }; 272 </script> 273 </body>