| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
| 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ | 16 */ |
| 17 | 17 |
| 18 /* global assert */ |
| 19 |
| 18 "use strict"; | 20 "use strict"; |
| 19 | 21 |
| 20 const {ElemHideEmulation, setTestMode, | 22 const {ElemHideEmulation, setTestMode, |
| 21 getTestInfo} = require("../../lib/content/elemHideEmulation"); | 23 getTestInfo} = require("../../lib/content/elemHideEmulation"); |
| 22 | 24 |
| 23 const REFRESH_INTERVAL = 200; | 25 describe("Element Hiding Emulation", () => |
| 24 | |
| 25 let testDocument = null; | |
| 26 | |
| 27 exports.setUp = function(callback) | |
| 28 { | 26 { |
| 29 setTestMode(); | 27 const REFRESH_INTERVAL = 200; |
| 30 | 28 |
| 31 let iframe = document.createElement("iframe"); | 29 let testDocument = null; |
| 32 document.body.appendChild(iframe); | 30 |
| 33 testDocument = iframe.contentDocument; | 31 beforeEach(() => |
| 34 | 32 { |
| 35 callback(); | 33 setTestMode(); |
| 36 }; | 34 |
| 37 | 35 let iframe = document.createElement("iframe"); |
| 38 exports.tearDown = function(callback) | 36 document.body.appendChild(iframe); |
| 39 { | 37 testDocument = iframe.contentDocument; |
| 40 let iframe = testDocument.defaultView.frameElement; | |
| 41 iframe.parentNode.removeChild(iframe); | |
| 42 testDocument = null; | |
| 43 | |
| 44 callback(); | |
| 45 }; | |
| 46 | |
| 47 function timeout(delay) | |
| 48 { | |
| 49 return new Promise((resolve, reject) => | |
| 50 { | |
| 51 window.setTimeout(resolve, delay); | |
| 52 }); | 38 }); |
| 53 } | 39 |
| 54 | 40 afterEach(() => |
| 55 function unexpectedError(test, error) | 41 { |
| 56 { | 42 let iframe = testDocument.defaultView.frameElement; |
| 57 console.error(error); | 43 iframe.parentNode.removeChild(iframe); |
| 58 test.ok(false, "Unexpected error: " + error); | 44 testDocument = null; |
| 59 } | 45 }); |
| 60 | 46 |
| 61 function expectHidden(test, element, id) | 47 function timeout(delay) |
| 62 { | 48 { |
| 63 let withId = ""; | 49 return new Promise((resolve, reject) => |
| 64 if (typeof id != "undefined") | 50 { |
| 65 withId = ` with ID '${id}'`; | 51 window.setTimeout(resolve, delay); |
| 66 | 52 }); |
| 67 test.equal( | |
| 68 window.getComputedStyle(element).display, "none", | |
| 69 `The element${withId}'s display property should be set to 'none'`); | |
| 70 } | |
| 71 | |
| 72 function expectVisible(test, element, id) | |
| 73 { | |
| 74 let withId = ""; | |
| 75 if (typeof id != "undefined") | |
| 76 withId = ` with ID '${id}'`; | |
| 77 | |
| 78 test.notEqual( | |
| 79 window.getComputedStyle(element).display, "none", | |
| 80 `The element${withId}'s display property should not be set to 'none'`); | |
| 81 } | |
| 82 | |
| 83 function expectProcessed(test, element, id = null) | |
| 84 { | |
| 85 let withId = ""; | |
| 86 if (id) | |
| 87 withId = ` with ID '${id}'`; | |
| 88 | |
| 89 test.ok( | |
| 90 getTestInfo().lastProcessedElements.has(element), | |
| 91 `The element${withId} should have been processed`); | |
| 92 } | |
| 93 | |
| 94 function expectNotProcessed(test, element, id = null) | |
| 95 { | |
| 96 let withId = ""; | |
| 97 if (id) | |
| 98 withId = ` with ID '${id}'`; | |
| 99 | |
| 100 test.ok( | |
| 101 !getTestInfo().lastProcessedElements.has(element), | |
| 102 `The element${withId} should not have been processed`); | |
| 103 } | |
| 104 | |
| 105 function findUniqueId() | |
| 106 { | |
| 107 let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); | |
| 108 if (!testDocument.getElementById(id)) | |
| 109 return id; | |
| 110 return findUniqueId(); | |
| 111 } | |
| 112 | |
| 113 function insertStyleRule(rule) | |
| 114 { | |
| 115 let styleElement; | |
| 116 let styleElements = testDocument.head.getElementsByTagName("style"); | |
| 117 if (styleElements.length) | |
| 118 styleElement = styleElements[0]; | |
| 119 else | |
| 120 { | |
| 121 styleElement = testDocument.createElement("style"); | |
| 122 testDocument.head.appendChild(styleElement); | |
| 123 } | 53 } |
| 124 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); | 54 |
| 125 } | 55 function unexpectedError(error) |
| 126 | 56 { |
| 127 function createElement(parent, type = "div", id = findUniqueId(), | 57 console.error(error); |
| 128 innerText = null) | 58 assert.ok(false, "Unexpected error: " + error); |
| 129 { | |
| 130 let element = testDocument.createElement(type); | |
| 131 element.id = id; | |
| 132 if (!parent) | |
| 133 testDocument.body.appendChild(element); | |
| 134 else | |
| 135 parent.appendChild(element); | |
| 136 if (innerText) | |
| 137 element.innerText = innerText; | |
| 138 return element; | |
| 139 } | |
| 140 | |
| 141 // Insert a <div> with a unique id and a CSS rule | |
| 142 // for the the selector matching the id. | |
| 143 function createElementWithStyle(styleBlock, parent) | |
| 144 { | |
| 145 let element = createElement(parent); | |
| 146 insertStyleRule("#" + element.id + " " + styleBlock); | |
| 147 return element; | |
| 148 } | |
| 149 | |
| 150 // Create a new ElemHideEmulation instance with @selectors. | |
| 151 async function applyElemHideEmulation(test, selectors) | |
| 152 { | |
| 153 await Promise.resolve(); | |
| 154 | |
| 155 try | |
| 156 { | |
| 157 let elemHideEmulation = new ElemHideEmulation( | |
| 158 elems => | |
| 159 { | |
| 160 for (let elem of elems) | |
| 161 elem.style.display = "none"; | |
| 162 } | |
| 163 ); | |
| 164 | |
| 165 elemHideEmulation.document = testDocument; | |
| 166 elemHideEmulation.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2; | |
| 167 elemHideEmulation.apply(selectors.map( | |
| 168 selector => ({selector, text: selector}) | |
| 169 )); | |
| 170 | |
| 171 return elemHideEmulation; | |
| 172 } | 59 } |
| 173 catch (error) | 60 |
| 174 { | 61 function expectHidden(element, id) |
| 175 unexpectedError(test, error); | 62 { |
| 63 let withId = ""; |
| 64 if (typeof id != "undefined") |
| 65 withId = ` with ID '${id}'`; |
| 66 |
| 67 assert.equal( |
| 68 window.getComputedStyle(element).display, "none", |
| 69 `The element${withId}'s display property should be set to 'none'`); |
| 176 } | 70 } |
| 177 } | 71 |
| 178 | 72 function expectVisible(element, id) |
| 179 exports.testVerbatimPropertySelector = async function(test) | 73 { |
| 180 { | 74 let withId = ""; |
| 181 let toHide = createElementWithStyle("{background-color: #000}"); | 75 if (typeof id != "undefined") |
| 182 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; | 76 withId = ` with ID '${id}'`; |
| 183 | 77 |
| 184 if (await applyElemHideEmulation(test, selectors)) | 78 assert.notEqual( |
| 185 expectHidden(test, toHide); | 79 window.getComputedStyle(element).display, "none", |
| 186 | 80 `The element${withId}'s display property should not be set to 'none'`); |
| 187 test.done(); | |
| 188 }; | |
| 189 | |
| 190 exports.testVerbatimPropertySelectorWithPrefix = async function(test) | |
| 191 { | |
| 192 let parent = createElementWithStyle("{background-color: #000}"); | |
| 193 let toHide = createElementWithStyle("{background-color: #000}", parent); | |
| 194 | |
| 195 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; | |
| 196 | |
| 197 if (await applyElemHideEmulation(test, selectors)) | |
| 198 { | |
| 199 expectVisible(test, parent); | |
| 200 expectHidden(test, toHide); | |
| 201 } | 81 } |
| 202 | 82 |
| 203 test.done(); | 83 function expectProcessed(element, id = null) |
| 204 }; | 84 { |
| 205 | 85 let withId = ""; |
| 206 exports.testVerbatimPropertySelectorWithPrefixNoMatch = async function(test) | 86 if (id) |
| 207 { | 87 withId = ` with ID '${id}'`; |
| 208 let parent = createElementWithStyle("{background-color: #000}"); | 88 |
| 209 let toHide = createElementWithStyle("{background-color: #fff}", parent); | 89 assert.ok( |
| 210 | 90 getTestInfo().lastProcessedElements.has(element), |
| 211 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; | 91 `The element${withId} should have been processed`); |
| 212 | |
| 213 if (await applyElemHideEmulation(test, selectors)) | |
| 214 { | |
| 215 expectVisible(test, parent); | |
| 216 expectVisible(test, toHide); | |
| 217 } | 92 } |
| 218 | 93 |
| 219 test.done(); | 94 function expectNotProcessed(element, id = null) |
| 220 }; | 95 { |
| 221 | 96 let withId = ""; |
| 222 exports.testVerbatimPropertySelectorWithSuffix = async function(test) | 97 if (id) |
| 223 { | 98 withId = ` with ID '${id}'`; |
| 224 let parent = createElementWithStyle("{background-color: #000}"); | 99 |
| 225 let toHide = createElementWithStyle("{background-color: #000}", parent); | 100 assert.ok( |
| 226 | 101 !getTestInfo().lastProcessedElements.has(element), |
| 227 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0)) > div"]; | 102 `The element${withId} should not have been processed`); |
| 228 | |
| 229 if (await applyElemHideEmulation(test, selectors)) | |
| 230 { | |
| 231 expectVisible(test, parent); | |
| 232 expectHidden(test, toHide); | |
| 233 } | 103 } |
| 234 | 104 |
| 235 test.done(); | 105 function findUniqueId() |
| 236 }; | 106 { |
| 237 | 107 let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); |
| 238 exports.testVerbatimPropertyPseudoSelectorWithPrefixAndSuffix = async function(t
est) | 108 if (!testDocument.getElementById(id)) |
| 239 { | 109 return id; |
| 240 let parent = createElementWithStyle("{background-color: #000}"); | 110 return findUniqueId(); |
| 241 let middle = createElementWithStyle("{background-color: #000}", parent); | |
| 242 let toHide = createElementWithStyle("{background-color: #000}", middle); | |
| 243 | |
| 244 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0)) > div
"]; | |
| 245 | |
| 246 if (await applyElemHideEmulation(test, selectors)) | |
| 247 { | |
| 248 expectVisible(test, parent); | |
| 249 expectVisible(test, middle); | |
| 250 expectHidden(test, toHide); | |
| 251 } | 111 } |
| 252 | 112 |
| 253 test.done(); | 113 function insertStyleRule(rule) |
| 254 }; | 114 { |
| 255 | 115 let styleElement; |
| 256 // Add the style. Then add the element for that style. | 116 let styleElements = testDocument.head.getElementsByTagName("style"); |
| 257 // This should retrigger the filtering and hide it. | 117 if (styleElements.length) |
| 258 exports.testPropertyPseudoSelectorAddStyleAndElement = async function(test) | 118 styleElement = styleElements[0]; |
| 259 { | 119 else |
| 260 let styleElement; | 120 { |
| 261 let toHide; | 121 styleElement = testDocument.createElement("style"); |
| 262 | 122 testDocument.head.appendChild(styleElement); |
| 263 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; | 123 } |
| 264 | 124 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
| 265 if (await applyElemHideEmulation(test, selectors)) | |
| 266 { | |
| 267 styleElement = testDocument.createElement("style"); | |
| 268 testDocument.head.appendChild(styleElement); | |
| 269 styleElement.sheet.insertRule("#toHide {background-color: #000}"); | |
| 270 await timeout(REFRESH_INTERVAL); | |
| 271 | |
| 272 toHide = createElement(); | |
| 273 toHide.id = "toHide"; | |
| 274 expectVisible(test, toHide); | |
| 275 await timeout(REFRESH_INTERVAL); | |
| 276 | |
| 277 expectHidden(test, toHide); | |
| 278 } | 125 } |
| 279 | 126 |
| 280 test.done(); | 127 function createElement(parent, type = "div", id = findUniqueId(), |
| 281 }; | 128 innerText = null) |
| 282 | 129 { |
| 283 exports.testPropertySelectorWithWildcard = async function(test) | 130 let element = testDocument.createElement(type); |
| 284 { | 131 element.id = id; |
| 285 let toHide = createElementWithStyle("{background-color: #000}"); | 132 if (!parent) |
| 286 let selectors = [":-abp-properties(*color: rgb(0, 0, 0))"]; | 133 testDocument.body.appendChild(element); |
| 287 | 134 else |
| 288 if (await applyElemHideEmulation(test, selectors)) | 135 parent.appendChild(element); |
| 289 expectHidden(test, toHide); | 136 if (innerText) |
| 290 | 137 element.innerText = innerText; |
| 291 test.done(); | 138 return element; |
| 292 }; | |
| 293 | |
| 294 exports.testPropertySelectorWithRegularExpression = async function(test) | |
| 295 { | |
| 296 let toHide = createElementWithStyle("{background-color: #000}"); | |
| 297 let selectors = [":-abp-properties(/.*color: rgb\\(0, 0, 0\\)/)"]; | |
| 298 | |
| 299 if (await applyElemHideEmulation(test, selectors)) | |
| 300 expectHidden(test, toHide); | |
| 301 | |
| 302 test.done(); | |
| 303 }; | |
| 304 | |
| 305 exports.testDynamicallyChangedProperty = async function(test) | |
| 306 { | |
| 307 let toHide = createElementWithStyle("{}"); | |
| 308 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; | |
| 309 | |
| 310 if (await applyElemHideEmulation(test, selectors)) | |
| 311 { | |
| 312 expectVisible(test, toHide); | |
| 313 insertStyleRule("#" + toHide.id + " {background-color: #000}"); | |
| 314 | |
| 315 await timeout(0); | |
| 316 | |
| 317 // Re-evaluation will only happen after a delay | |
| 318 expectVisible(test, toHide); | |
| 319 await timeout(REFRESH_INTERVAL); | |
| 320 | |
| 321 expectHidden(test, toHide); | |
| 322 } | 139 } |
| 323 | 140 |
| 324 test.done(); | 141 // Insert a <div> with a unique id and a CSS rule |
| 325 }; | 142 // for the the selector matching the id. |
| 326 | 143 function createElementWithStyle(styleBlock, parent) |
| 327 exports.testPseudoClassWithPropBeforeSelector = async function(test) | 144 { |
| 328 { | 145 let element = createElement(parent); |
| 329 let parent = createElementWithStyle("{}"); | 146 insertStyleRule("#" + element.id + " " + styleBlock); |
| 330 let child = createElementWithStyle("{background-color: #000}", parent); | 147 return element; |
| 331 | |
| 332 let selectors = ["div:-abp-properties(content: \"publicite\")"]; | |
| 333 | |
| 334 insertStyleRule(`#${child.id}::before {content: "publicite"}`); | |
| 335 | |
| 336 if (await applyElemHideEmulation(test, selectors)) | |
| 337 { | |
| 338 expectHidden(test, child); | |
| 339 expectVisible(test, parent); | |
| 340 } | 148 } |
| 341 | 149 |
| 342 test.done(); | 150 // Create a new ElemHideEmulation instance with @selectors. |
| 343 }; | 151 async function applyElemHideEmulation(selectors) |
| 344 | 152 { |
| 345 exports.testPseudoClassHasSelector = async function(test) | 153 await Promise.resolve(); |
| 346 { | 154 |
| 347 let toHide = createElementWithStyle("{}"); | 155 try |
| 348 | 156 { |
| 349 if (await applyElemHideEmulation(test, ["div:-abp-has(div)"])) | 157 let elemHideEmulation = new ElemHideEmulation( |
| 350 expectVisible(test, toHide); | 158 elems => |
| 351 | 159 { |
| 352 test.done(); | 160 for (let elem of elems) |
| 353 }; | 161 elem.style.display = "none"; |
| 354 | 162 } |
| 355 exports.testPseudoClassHasSelectorWithPrefix = async function(test) | 163 ); |
| 356 { | 164 |
| 357 let parent = createElementWithStyle("{}"); | 165 elemHideEmulation.document = testDocument; |
| 358 let child = createElementWithStyle("{}", parent); | 166 elemHideEmulation.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2; |
| 359 | 167 elemHideEmulation.apply(selectors.map( |
| 360 if (await applyElemHideEmulation(test, ["div:-abp-has(div)"])) | 168 selector => ({selector, text: selector}) |
| 361 { | 169 )); |
| 362 expectHidden(test, parent); | 170 |
| 363 expectVisible(test, child); | 171 return elemHideEmulation; |
| 364 } | 172 } |
| 365 | 173 catch (error) |
| 366 test.done(); | 174 { |
| 367 }; | 175 unexpectedError(error); |
| 368 | |
| 369 exports.testPseudoClassHasSelectorWithSuffix = async function(test) | |
| 370 { | |
| 371 let parent = createElementWithStyle("{}"); | |
| 372 let middle = createElementWithStyle("{}", parent); | |
| 373 let child = createElementWithStyle("{}", middle); | |
| 374 | |
| 375 if (await applyElemHideEmulation(test, ["div:-abp-has(div) > div"])) | |
| 376 { | |
| 377 expectVisible(test, parent); | |
| 378 expectHidden(test, middle); | |
| 379 expectHidden(test, child); | |
| 380 } | |
| 381 | |
| 382 test.done(); | |
| 383 }; | |
| 384 | |
| 385 exports.testPseudoClassHasSelectorWithSuffixSibling = async function(test) | |
| 386 { | |
| 387 let parent = createElementWithStyle("{}"); | |
| 388 let middle = createElementWithStyle("{}", parent); | |
| 389 let toHide = createElementWithStyle("{}"); | |
| 390 | |
| 391 if (await applyElemHideEmulation(test, ["div:-abp-has(div) + div"])) | |
| 392 { | |
| 393 expectVisible(test, parent); | |
| 394 expectVisible(test, middle); | |
| 395 expectHidden(test, toHide); | |
| 396 } | |
| 397 | |
| 398 test.done(); | |
| 399 }; | |
| 400 | |
| 401 exports.testPseudoClassHasSelectorWithSuffixSiblingChild = async function(test) | |
| 402 { | |
| 403 // <div> | |
| 404 // <div></div> | |
| 405 // <div> | |
| 406 // <div>to hide</div> | |
| 407 // </div> | |
| 408 // </div> | |
| 409 let parent = createElementWithStyle("{}"); | |
| 410 let middle = createElementWithStyle("{}", parent); | |
| 411 let sibling = createElementWithStyle("{}"); | |
| 412 let toHide = createElementWithStyle("{}", sibling); | |
| 413 | |
| 414 if (await applyElemHideEmulation(test, ["div:-abp-has(div) + div > div"])) | |
| 415 { | |
| 416 expectVisible(test, parent); | |
| 417 expectVisible(test, middle); | |
| 418 expectVisible(test, sibling); | |
| 419 expectHidden(test, toHide); | |
| 420 } | |
| 421 | |
| 422 test.done(); | |
| 423 }; | |
| 424 | |
| 425 function compareExpectations(test, elems, expectations) | |
| 426 { | |
| 427 for (let elem in expectations) | |
| 428 { | |
| 429 if (elems[elem]) | |
| 430 { | |
| 431 if (expectations[elem]) | |
| 432 expectVisible(test, elems[elem], elem); | |
| 433 else | |
| 434 expectHidden(test, elems[elem], elem); | |
| 435 } | 176 } |
| 436 } | 177 } |
| 437 } | 178 |
| 438 | 179 describe("Verbatim Property Selector", () => |
| 439 async function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, se
lector, expectations) | 180 { |
| 440 { | 181 it("Regular", async() => |
| 441 testDocument.body.innerHTML = `<div id="parent"> | 182 { |
| 442 <div id="middle"> | 183 let toHide = createElementWithStyle("{background-color: #000}"); |
| 443 <div id="middle1"><div id="inside" class="inside"></div></div> | 184 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
| 444 </div> | 185 |
| 445 <div id="sibling"> | 186 if (await applyElemHideEmulation(selectors)) |
| 446 <div id="tohide"><span>to hide</span></div> | 187 expectHidden(toHide); |
| 447 </div> | 188 }); |
| 448 <div id="sibling2"> | 189 |
| 449 <div id="sibling21"><div id="sibling211" class="inside"></div></div> | 190 it("With Prefix", async() => |
| 450 </div> | 191 { |
| 451 </div>`; | 192 let parent = createElementWithStyle("{background-color: #000}"); |
| 452 let elems = { | 193 let toHide = createElementWithStyle("{background-color: #000}", parent); |
| 453 parent: testDocument.getElementById("parent"), | 194 |
| 454 middle: testDocument.getElementById("middle"), | 195 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]
; |
| 455 inside: testDocument.getElementById("inside"), | 196 |
| 456 sibling: testDocument.getElementById("sibling"), | 197 if (await applyElemHideEmulation(selectors)) |
| 457 sibling2: testDocument.getElementById("sibling2"), | 198 { |
| 458 toHide: testDocument.getElementById("tohide") | 199 expectVisible(parent); |
| 459 }; | 200 expectHidden(toHide); |
| 460 | 201 } |
| 461 insertStyleRule(".inside {}"); | 202 }); |
| 462 | 203 |
| 463 if (await applyElemHideEmulation(test, [selector])) | 204 it("With Prefix No Match", async() => |
| 464 compareExpectations(test, elems, expectations); | 205 { |
| 465 | 206 let parent = createElementWithStyle("{background-color: #000}"); |
| 466 test.done(); | 207 let toHide = createElementWithStyle("{background-color: #fff}", parent); |
| 467 } | 208 |
| 468 | 209 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]
; |
| 469 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) | 210 |
| 470 { | 211 if (await applyElemHideEmulation(selectors)) |
| 471 let expectations = { | 212 { |
| 472 parent: true, | 213 expectVisible(parent); |
| 473 middile: true, | 214 expectVisible(toHide); |
| 474 inside: true, | 215 } |
| 475 sibling: true, | 216 }); |
| 476 sibling2: true, | 217 |
| 477 toHide: false | 218 it("With Suffix", async() => |
| 478 }; | 219 { |
| 479 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 220 let parent = createElementWithStyle("{background-color: #000}"); |
| 480 test, "div:-abp-has(:-abp-has(div.inside)) + div > div", expectations); | 221 let toHide = createElementWithStyle("{background-color: #000}", parent); |
| 481 }; | 222 |
| 482 | 223 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0)) > div"]
; |
| 483 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test) | 224 |
| 484 { | 225 if (await applyElemHideEmulation(selectors)) |
| 485 let expectations = { | 226 { |
| 486 parent: true, | 227 expectVisible(parent); |
| 487 middile: true, | 228 expectHidden(toHide); |
| 488 inside: true, | 229 } |
| 489 sibling: true, | 230 }); |
| 490 sibling2: true, | 231 |
| 491 toHide: false | 232 |
| 492 }; | 233 it("With prefix and suffix", async() => |
| 493 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 234 { |
| 494 test, "div:-abp-has(:-abp-has(> div.inside)) + div > div", expectations); | 235 let parent = createElementWithStyle("{background-color: #000}"); |
| 495 }; | 236 let middle = createElementWithStyle("{background-color: #000}", parent); |
| 496 | 237 let toHide = createElementWithStyle("{background-color: #000}", middle); |
| 497 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling3 = function(test) | 238 |
| 498 { | 239 let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0)) >
div"]; |
| 499 let expectations = { | 240 |
| 500 parent: true, | 241 if (await applyElemHideEmulation(selectors)) |
| 501 middile: true, | 242 { |
| 502 inside: true, | 243 expectVisible(parent); |
| 503 sibling: true, | 244 expectVisible(middle); |
| 504 sibling2: true, | 245 expectHidden(toHide); |
| 505 toHide: false | 246 } |
| 506 }; | 247 }); |
| 507 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 248 }); |
| 508 test, "div:-abp-has(> div:-abp-has(div.inside)) + div > div", expectations); | 249 |
| 509 }; | 250 // Add the style. Then add the element for that style. |
| 510 | 251 // This should retrigger the filtering and hide it. |
| 511 exports.testPseudoClassHasSelectorWithSuffixSiblingNoop = function(test) | 252 it("Property Pseudo Selector Add Style and elemment", async() => |
| 512 { | 253 { |
| 513 let expectations = { | 254 let styleElement; |
| 514 parent: true, | 255 let toHide; |
| 515 middile: true, | 256 |
| 516 inside: true, | 257 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
| 517 sibling: true, | 258 |
| 518 sibling2: true, | 259 if (await applyElemHideEmulation(selectors)) |
| 519 toHide: true | 260 { |
| 520 }; | 261 styleElement = testDocument.createElement("style"); |
| 521 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 262 testDocument.head.appendChild(styleElement); |
| 522 test, "div:-abp-has(> body div.inside) + div > div", expectations); | 263 styleElement.sheet.insertRule("#toHide {background-color: #000}"); |
| 523 }; | 264 await timeout(REFRESH_INTERVAL); |
| 524 | 265 |
| 525 exports.testPseudoClassHasSelectorWithSuffixSiblingContains = function(test) | 266 toHide = createElement(); |
| 526 { | 267 toHide.id = "toHide"; |
| 527 let expectations = { | 268 expectVisible(toHide); |
| 528 parent: true, | 269 await timeout(REFRESH_INTERVAL); |
| 529 middile: true, | 270 |
| 530 inside: true, | 271 expectHidden(toHide); |
| 531 sibling: true, | 272 } |
| 532 sibling2: true, | 273 }); |
| 533 toHide: true | 274 |
| 534 }; | 275 describe("Property Selector", () => |
| 535 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 276 { |
| 536 test, "div:-abp-has(> span:-abp-contains(Advertisment))", expectations); | 277 it("With Wildcard", async() => |
| 537 }; | 278 { |
| 538 | 279 let toHide = createElementWithStyle("{background-color: #000}"); |
| 539 async function runTestPseudoClassContains(test, selector, expectations) | 280 let selectors = [":-abp-properties(*color: rgb(0, 0, 0))"]; |
| 540 { | 281 |
| 541 testDocument.body.innerHTML = `<div id="parent"> | 282 if (await applyElemHideEmulation(selectors)) |
| 542 <div id="middle"> | 283 expectHidden(toHide); |
| 543 <div id="middle1"><div id="inside" class="inside"></div></div> | 284 }); |
| 544 </div> | 285 |
| 545 <div id="sibling"> | 286 it("With regular expression", async() => |
| 546 <div id="tohide">to hide \ud83d\ude42!</div> | 287 { |
| 547 </div> | 288 let toHide = createElementWithStyle("{background-color: #000}"); |
| 548 <div id="sibling2"> | 289 let selectors = [":-abp-properties(/.*color: rgb\\(0, 0, 0\\)/)"]; |
| 549 <div id="sibling21"><div id="sibling211" class="inside">Ad*</div></div> | 290 |
| 550 </div> | 291 if (await applyElemHideEmulation(selectors)) |
| 551 </div>`; | 292 expectHidden(toHide); |
| 552 let elems = { | 293 }); |
| 553 parent: testDocument.getElementById("parent"), | 294 }); |
| 554 middle: testDocument.getElementById("middle"), | 295 |
| 555 inside: testDocument.getElementById("inside"), | 296 it("Dynamically Changed Property", async() => |
| 556 sibling: testDocument.getElementById("sibling"), | 297 { |
| 557 sibling2: testDocument.getElementById("sibling2"), | 298 let toHide = createElementWithStyle("{}"); |
| 558 toHide: testDocument.getElementById("tohide") | 299 let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
| 559 }; | 300 |
| 560 | 301 if (await applyElemHideEmulation(selectors)) |
| 561 if (await applyElemHideEmulation(test, [selector])) | 302 { |
| 562 compareExpectations(test, elems, expectations); | 303 expectVisible(toHide); |
| 563 | 304 insertStyleRule("#" + toHide.id + " {background-color: #000}"); |
| 564 test.done(); | 305 |
| 565 } | 306 await timeout(0); |
| 566 | 307 |
| 567 exports.testPseudoClassContainsText = function(test) | 308 // Re-evaluation will only happen after a delay |
| 568 { | 309 expectVisible(toHide); |
| 569 let expectations = { | 310 await timeout(REFRESH_INTERVAL); |
| 570 parent: true, | 311 |
| 571 middle: true, | 312 expectHidden(toHide); |
| 572 inside: true, | 313 } |
| 573 sibling: false, | 314 }); |
| 574 sibling2: true, | 315 |
| 575 toHide: true | 316 describe("Pseudo Class", () => |
| 576 }; | 317 { |
| 577 runTestPseudoClassContains( | 318 it("With prop before selector", async() => |
| 578 test, "#parent div:-abp-contains(to hide)", expectations); | 319 { |
| 579 }; | 320 let parent = createElementWithStyle("{}"); |
| 580 | 321 let child = createElementWithStyle("{background-color: #000}", parent); |
| 581 exports.testPseudoClassContainsRegexp = function(test) | 322 |
| 582 { | 323 let selectors = ["div:-abp-properties(content: \"publicite\")"]; |
| 583 let expectations = { | 324 |
| 584 parent: true, | 325 insertStyleRule(`#${child.id}::before {content: "publicite"}`); |
| 585 middle: true, | 326 |
| 586 inside: true, | 327 if (await applyElemHideEmulation(selectors)) |
| 587 sibling: false, | 328 { |
| 588 sibling2: true, | 329 expectHidden(child); |
| 589 toHide: true | 330 expectVisible(parent); |
| 590 }; | 331 } |
| 591 runTestPseudoClassContains( | 332 }); |
| 592 test, "#parent div:-abp-contains(/to\\shide/)", expectations); | 333 |
| 593 }; | 334 function compareExpectations(elems, expectations) |
| 594 | 335 { |
| 595 exports.testPseudoClassContainsRegexpIFlag = function(test) | 336 for (let elem in expectations) |
| 596 { | 337 { |
| 597 let expectations = { | 338 if (elems[elem]) |
| 598 parent: true, | 339 { |
| 599 middle: true, | 340 if (expectations[elem]) |
| 600 inside: true, | 341 expectVisible(elems[elem], elem); |
| 601 sibling: false, | 342 else |
| 602 sibling2: true, | 343 expectHidden(elems[elem], elem); |
| 603 toHide: true | 344 } |
| 604 }; | 345 } |
| 605 runTestPseudoClassContains( | 346 } |
| 606 test, "#parent div:-abp-contains(/to\\sHide/i)", expectations); | 347 |
| 607 }; | 348 describe("Has Selector", () => |
| 608 | 349 { |
| 609 exports.testPseudoClassContainsRegexpUFlag = function(test) | 350 it("Simple", async() => |
| 610 { | 351 { |
| 611 let expectations = { | 352 let toHide = createElementWithStyle("{}"); |
| 612 parent: true, | 353 |
| 613 middle: true, | 354 if (await applyElemHideEmulation(["div:-abp-has(div)"])) |
| 614 inside: true, | 355 expectVisible(toHide); |
| 615 sibling: false, | 356 }); |
| 616 sibling2: true, | 357 |
| 617 toHide: true | 358 it("With prefix", async() => |
| 618 }; | 359 { |
| 619 runTestPseudoClassContains( | 360 let parent = createElementWithStyle("{}"); |
| 620 test, "#parent div:-abp-contains(/to\\shide\\s.!/u)", expectations); | 361 let child = createElementWithStyle("{}", parent); |
| 621 }; | 362 |
| 622 | 363 if (await applyElemHideEmulation(["div:-abp-has(div)"])) |
| 623 exports.testPseudoClassContainsWildcardNoMatch = function(test) | 364 { |
| 624 { | 365 expectHidden(parent); |
| 625 let expectations = { | 366 expectVisible(child); |
| 626 parent: true, | 367 } |
| 627 middle: true, | 368 }); |
| 628 inside: true, | 369 |
| 629 sibling: true, | 370 it("With suffix", async() => |
| 630 sibling2: true, | 371 { |
| 631 toHide: true | 372 let parent = createElementWithStyle("{}"); |
| 632 }; | 373 let middle = createElementWithStyle("{}", parent); |
| 633 // this filter shouldn't match anything as "*" has no meaning. | 374 let child = createElementWithStyle("{}", middle); |
| 634 runTestPseudoClassContains( | 375 |
| 635 test, "#parent div:-abp-contains(to *hide)", expectations); | 376 if (await applyElemHideEmulation(["div:-abp-has(div) > div"])) |
| 636 }; | 377 { |
| 637 | 378 expectVisible(parent); |
| 638 exports.testPseudoClassContainsWildcardMatch = function(test) | 379 expectHidden(middle); |
| 639 { | 380 expectHidden(child); |
| 640 let expectations = { | 381 } |
| 641 parent: true, | 382 }); |
| 642 middle: true, | 383 |
| 643 inside: true, | 384 it("With suffix sibling", async() => |
| 644 sibling: true, | 385 { |
| 645 sibling2: false, | 386 let parent = createElementWithStyle("{}"); |
| 646 toHide: true | 387 let middle = createElementWithStyle("{}", parent); |
| 647 }; | 388 let toHide = createElementWithStyle("{}"); |
| 648 runTestPseudoClassContains( | 389 |
| 649 test, "#parent div:-abp-contains(Ad*)", expectations); | 390 if (await applyElemHideEmulation(["div:-abp-has(div) + div"])) |
| 650 }; | 391 { |
| 651 | 392 expectVisible(parent); |
| 652 exports.testPseudoClassHasSelectorWithPropSelector = async function(test) | 393 expectVisible(middle); |
| 653 { | 394 expectHidden(toHide); |
| 654 let parent = createElementWithStyle("{}"); | 395 } |
| 655 let child = createElementWithStyle("{background-color: #000}", parent); | 396 }); |
| 656 | 397 |
| 657 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)
))"]; | 398 it("With suffix sibling child", async() => |
| 658 | 399 { |
| 659 if (await applyElemHideEmulation(test, selectors)) | 400 // <div> |
| 660 { | 401 // <div></div> |
| 661 expectVisible(test, child); | 402 // <div> |
| 662 expectHidden(test, parent); | 403 // <div>to hide</div> |
| 663 } | 404 // </div> |
| 664 | 405 // </div> |
| 665 test.done(); | 406 let parent = createElementWithStyle("{}"); |
| 666 }; | 407 let middle = createElementWithStyle("{}", parent); |
| 667 | 408 let sibling = createElementWithStyle("{}"); |
| 668 exports.testPseudoClassHasSelectorWithPropSelector2 = async function(test) | 409 let toHide = createElementWithStyle("{}", sibling); |
| 669 { | 410 |
| 670 let parent = createElementWithStyle("{}"); | 411 if (await applyElemHideEmulation(["div:-abp-has(div) + div > div"])) |
| 671 let child = createElementWithStyle("{}", parent); | 412 { |
| 672 | 413 expectVisible(parent); |
| 673 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)
))"]; | 414 expectVisible(middle); |
| 674 | 415 expectVisible(sibling); |
| 675 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); | 416 expectHidden(toHide); |
| 676 | 417 } |
| 677 if (await applyElemHideEmulation(test, selectors)) | 418 }); |
| 678 { | 419 |
| 679 expectVisible(test, child); | 420 async function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(se
lector, expectations) |
| 680 expectHidden(test, parent); | 421 { |
| 681 } | 422 testDocument.body.innerHTML = `<div id="parent"> |
| 682 | 423 <div id="middle"> |
| 683 test.done(); | 424 <div id="middle1"><div id="inside" class="inside"></div></div> |
| 684 }; | 425 </div> |
| 685 | 426 <div id="sibling"> |
| 686 exports.testDomUpdatesStyle = async function(test) | 427 <div id="tohide"><span>to hide</span></div> |
| 687 { | 428 </div> |
| 688 let parent = createElementWithStyle("{}"); | 429 <div id="sibling2"> |
| 689 let child = createElementWithStyle("{}", parent); | 430 <div id="sibling21"><div id="sibling211" class="inside"></div></div> |
| 690 | 431 </div> |
| 691 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)
))"]; | 432 </div>`; |
| 692 | 433 let elems = { |
| 693 if (await applyElemHideEmulation(test, selectors)) | 434 parent: testDocument.getElementById("parent"), |
| 694 { | 435 middle: testDocument.getElementById("middle"), |
| 695 expectVisible(test, child); | 436 inside: testDocument.getElementById("inside"), |
| 696 expectVisible(test, parent); | 437 sibling: testDocument.getElementById("sibling"), |
| 697 | 438 sibling2: testDocument.getElementById("sibling2"), |
| 698 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); | 439 toHide: testDocument.getElementById("tohide") |
| 699 await timeout(0); | 440 }; |
| 700 | 441 |
| 701 expectVisible(test, child); | 442 insertStyleRule(".inside {}"); |
| 702 expectVisible(test, parent); | 443 if (await applyElemHideEmulation([selector])) |
| 703 await timeout(REFRESH_INTERVAL); | 444 compareExpectations(elems, expectations); |
| 704 | 445 } |
| 705 expectVisible(test, child); | 446 |
| 706 expectHidden(test, parent); | 447 it("With has and with suffix sibling", () => |
| 707 } | 448 { |
| 708 | 449 let expectations = { |
| 709 test.done(); | 450 parent: true, |
| 710 }; | 451 middile: true, |
| 711 | 452 inside: true, |
| 712 exports.testDomUpdatesContent = async function(test) | 453 sibling: true, |
| 713 { | 454 sibling2: true, |
| 714 let parent = createElementWithStyle("{}"); | 455 toHide: false |
| 715 let child = createElementWithStyle("{}", parent); | 456 }; |
| 716 | 457 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
| 717 if (await applyElemHideEmulation(test, ["div > div:-abp-contains(hide me)"])) | 458 "div:-abp-has(:-abp-has(div.inside)) + div > div", expectations); |
| 718 { | 459 }); |
| 719 expectVisible(test, parent); | 460 |
| 720 expectVisible(test, child); | 461 it("With has an with suffix sibling (2)", () => |
| 721 | 462 { |
| 722 child.textContent = "hide me"; | 463 let expectations = { |
| 723 await timeout(0); | 464 parent: true, |
| 724 | 465 middile: true, |
| 725 expectVisible(test, parent); | 466 inside: true, |
| 726 expectVisible(test, child); | 467 sibling: true, |
| 727 await timeout(REFRESH_INTERVAL); | 468 sibling2: true, |
| 728 | 469 toHide: false |
| 729 expectVisible(test, parent); | 470 }; |
| 730 expectHidden(test, child); | 471 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
| 731 } | 472 "div:-abp-has(:-abp-has(> div.inside)) + div > div", expectations); |
| 732 | 473 }); |
| 733 test.done(); | 474 |
| 734 }; | 475 it("With has an with suffix sibling (3)", () => |
| 735 | 476 { |
| 736 exports.testDomUpdatesNewElement = async function(test) | 477 let expectations = { |
| 737 { | 478 parent: true, |
| 738 let parent = createElementWithStyle("{}"); | 479 middile: true, |
| 739 let child = createElementWithStyle("{ background-color: #000}", parent); | 480 inside: true, |
| 740 let sibling; | 481 sibling: true, |
| 741 let child2; | 482 sibling2: true, |
| 742 | 483 toHide: false |
| 743 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)
))"]; | 484 }; |
| 744 | 485 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
| 745 if (await applyElemHideEmulation(test, selectors)) | 486 "div:-abp-has(> div:-abp-has(div.inside)) + div > div", expectations); |
| 746 { | 487 }); |
| 747 expectHidden(test, parent); | 488 |
| 748 expectVisible(test, child); | 489 it("With suffix sibling no-op", () => |
| 749 | 490 { |
| 750 sibling = createElementWithStyle("{}"); | 491 let expectations = { |
| 751 await timeout(0); | 492 parent: true, |
| 752 | 493 middile: true, |
| 753 expectHidden(test, parent); | 494 inside: true, |
| 754 expectVisible(test, child); | 495 sibling: true, |
| 755 expectVisible(test, sibling); | 496 sibling2: true, |
| 756 | 497 toHide: true |
| 757 await timeout(REFRESH_INTERVAL); | 498 }; |
| 758 | 499 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
| 759 expectHidden(test, parent); | 500 "div:-abp-has(> body div.inside) + div > div", expectations); |
| 760 expectVisible(test, child); | 501 }); |
| 761 expectVisible(test, sibling); | 502 |
| 762 | 503 it("With suffix sibling contains", () => |
| 763 child2 = createElementWithStyle("{ background-color: #000}", | 504 { |
| 764 sibling); | 505 let expectations = { |
| 765 await timeout(0); | 506 parent: true, |
| 766 | 507 middile: true, |
| 767 expectVisible(test, child2); | 508 inside: true, |
| 768 await timeout(REFRESH_INTERVAL); | 509 sibling: true, |
| 769 | 510 sibling2: true, |
| 770 expectHidden(test, parent); | 511 toHide: true |
| 771 expectVisible(test, child); | 512 }; |
| 772 expectHidden(test, sibling); | 513 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
| 773 expectVisible(test, child2); | 514 "div:-abp-has(> span:-abp-contains(Advertisment))", expectations); |
| 774 } | 515 }); |
| 775 | 516 }); |
| 776 test.done(); | 517 |
| 777 }; | 518 describe("Contains selector", () => |
| 778 | 519 { |
| 779 exports.testPseudoClassPropertiesOnStyleSheetLoad = async function(test) | 520 async function runTestPseudoClassContains(selector, expectations) |
| 780 { | 521 { |
| 781 let parent = createElement(); | 522 testDocument.body.innerHTML = `<div id="parent"> |
| 782 let child = createElement(parent); | 523 <div id="middle"> |
| 783 | 524 <div id="middle1"><div id="inside" class="inside"></div></div> |
| 784 let selectors = [ | 525 </div> |
| 785 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 526 <div id="sibling"> |
| 786 "div:-abp-contains(hide me)", | 527 <div id="tohide">to hide \ud83d\ude42!</div> |
| 787 "div:-abp-has(> div.hideMe)" | 528 </div> |
| 788 ]; | 529 <div id="sibling2"> |
| 789 | 530 <div id="sibling21"> |
| 790 if (await applyElemHideEmulation(test, selectors)) | 531 <div id="sibling211" class="inside">Ad*</div> |
| 791 { | 532 </div> |
| 792 await timeout(REFRESH_INTERVAL); | 533 </div> |
| 793 | 534 </div>`; |
| 794 expectVisible(test, parent); | 535 let elems = { |
| 795 expectVisible(test, child); | 536 parent: testDocument.getElementById("parent"), |
| 796 | 537 middle: testDocument.getElementById("middle"), |
| 797 // Load a style sheet that targets the parent element. This should run only | 538 inside: testDocument.getElementById("inside"), |
| 798 // the "div:-abp-properties(background-color: rgb(0, 0, 0))" pattern. | 539 sibling: testDocument.getElementById("sibling"), |
| 799 insertStyleRule("#" + parent.id + " {background-color: #000}"); | 540 sibling2: testDocument.getElementById("sibling2"), |
| 800 | 541 toHide: testDocument.getElementById("tohide") |
| 801 await timeout(REFRESH_INTERVAL); | 542 }; |
| 802 | 543 |
| 803 expectHidden(test, parent); | 544 if (await applyElemHideEmulation([selector])) |
| 804 expectVisible(test, child); | 545 compareExpectations(elems, expectations); |
| 805 } | 546 } |
| 806 | 547 |
| 807 test.done(); | 548 it("Text", () => |
| 808 }; | 549 { |
| 809 | 550 let expectations = { |
| 810 exports.testPlainAttributeOnDomMutation = async function(test) | 551 parent: true, |
| 811 { | 552 middle: true, |
| 812 let parent = createElement(); | 553 inside: true, |
| 813 let child = createElement(parent); | 554 sibling: false, |
| 814 | 555 sibling2: true, |
| 815 let selectors = [ | 556 toHide: true |
| 816 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 557 }; |
| 817 "div[data-hide-me]", | 558 runTestPseudoClassContains( |
| 818 "div:-abp-contains(hide me)", | 559 "#parent div:-abp-contains(to hide)", expectations); |
| 819 "div:-abp-has(> div.hideMe)" | 560 }); |
| 820 ]; | 561 |
| 821 | 562 it("Regexp", () => |
| 822 if (await applyElemHideEmulation(test, selectors)) | 563 { |
| 823 { | 564 let expectations = { |
| 824 await timeout(REFRESH_INTERVAL); | 565 parent: true, |
| 825 | 566 middle: true, |
| 826 expectVisible(test, parent); | 567 inside: true, |
| 827 expectVisible(test, child); | 568 sibling: false, |
| 828 | 569 sibling2: true, |
| 829 // Set the "data-hide-me" attribute on the child element. | 570 toHide: true |
| 830 // | 571 }; |
| 831 // Note: Since the "div[data-hide-me]" pattern has already been processed | 572 runTestPseudoClassContains( |
| 832 // and the selector added to the document's style sheet, this will in fact | 573 "#parent div:-abp-contains(/to\\shide/)", expectations); |
| 833 // not do anything at our end, but the browser will just match the selector | 574 }); |
| 834 // and hide the element. | 575 |
| 835 child.setAttribute("data-hide-me", ""); | 576 it("Regexp i flag", () => |
| 836 | 577 { |
| 837 await timeout(REFRESH_INTERVAL); | 578 let expectations = { |
| 838 | 579 parent: true, |
| 839 expectVisible(test, parent); | 580 middle: true, |
| 840 expectHidden(test, child); | 581 inside: true, |
| 841 } | 582 sibling: false, |
| 842 | 583 sibling2: true, |
| 843 test.done(); | 584 toHide: true |
| 844 }; | 585 }; |
| 845 | 586 runTestPseudoClassContains( |
| 846 exports.testPseudoClassContainsOnDomMutation = async function(test) | 587 "#parent div:-abp-contains(/to\\sHide/i)", expectations); |
| 847 { | 588 }); |
| 848 let parent = createElement(); | 589 |
| 849 let child = createElement(parent); | 590 it("Regexp u flag", () => |
| 850 | 591 { |
| 851 let selectors = [ | 592 let expectations = { |
| 852 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 593 parent: true, |
| 853 "div[data-hide-me]", | 594 middle: true, |
| 854 "div:-abp-contains(hide me)", | 595 inside: true, |
| 855 "div:-abp-has(> div.hideMe)" | 596 sibling: false, |
| 856 ]; | 597 sibling2: true, |
| 857 | 598 toHide: true |
| 858 child.innerText = "do nothing"; | 599 }; |
| 859 | 600 runTestPseudoClassContains( |
| 860 if (await applyElemHideEmulation(test, selectors)) | 601 "#parent div:-abp-contains(/to\\shide\\s.!/u)", expectations); |
| 861 { | 602 }); |
| 862 await timeout(REFRESH_INTERVAL); | 603 |
| 863 | 604 it("Wildcard no match", () => |
| 864 expectVisible(test, parent); | 605 { |
| 865 expectVisible(test, child); | 606 let expectations = { |
| 866 | 607 parent: true, |
| 867 // Set the child element's text to "hide me". This should run only the | 608 middle: true, |
| 868 // "div:-abp-contains(hide me)" pattern. | 609 inside: true, |
| 869 // | 610 sibling: true, |
| 870 // Note: We need to set Node.innerText here in order to trigger the | 611 sibling2: true, |
| 871 // "characterData" DOM mutation on Chromium. If we set Node.textContent | 612 toHide: true |
| 872 // instead, it triggers the "childList" DOM mutation instead. | 613 }; |
| 873 child.innerText = "hide me"; | 614 // this filter shouldn't match anything as "*" has no meaning. |
| 874 | 615 runTestPseudoClassContains( |
| 875 await timeout(REFRESH_INTERVAL); | 616 "#parent div:-abp-contains(to *hide)", expectations); |
| 876 | 617 }); |
| 877 expectHidden(test, parent); | 618 |
| 878 expectVisible(test, child); | 619 it("Wildcard match", () => |
| 879 } | 620 { |
| 880 | 621 let expectations = { |
| 881 test.done(); | 622 parent: true, |
| 882 }; | 623 middle: true, |
| 883 | 624 inside: true, |
| 884 exports.testPseudoClassHasOnDomMutation = async function(test) | 625 sibling: true, |
| 885 { | 626 sibling2: false, |
| 886 let parent = createElement(); | 627 toHide: true |
| 887 let child = null; | 628 }; |
| 888 | 629 runTestPseudoClassContains( |
| 889 let selectors = [ | 630 "#parent div:-abp-contains(Ad*)", expectations); |
| 890 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 631 }); |
| 891 "div[data-hide-me]", | 632 }); |
| 892 "div:-abp-contains(hide me)", | 633 |
| 893 "div:-abp-has(> div)" | 634 describe("Has Selector with prop selector", () => |
| 894 ]; | 635 { |
| 895 | 636 it("Already present", async() => |
| 896 if (await applyElemHideEmulation(test, selectors)) | 637 { |
| 897 { | 638 let parent = createElementWithStyle("{}"); |
| 898 await timeout(REFRESH_INTERVAL); | 639 let child = createElementWithStyle("{background-color: #000}", parent); |
| 899 | 640 |
| 900 expectVisible(test, parent); | 641 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0,
0, 0)))"]; |
| 901 | 642 |
| 902 // Add the child element. This should run all the DOM-dependent patterns | 643 if (await applyElemHideEmulation(selectors)) |
| 903 // ("div:-abp-contains(hide me)" and "div:-abp-has(> div)"). | 644 { |
| 904 child = createElement(parent); | 645 expectVisible(child); |
| 905 | 646 expectHidden(parent); |
| 906 await timeout(REFRESH_INTERVAL); | 647 } |
| 907 | 648 }); |
| 908 expectHidden(test, parent); | 649 |
| 909 expectVisible(test, child); | 650 it("Dynamically added", async() => |
| 910 } | 651 { |
| 911 | 652 let parent = createElementWithStyle("{}"); |
| 912 test.done(); | 653 let child = createElementWithStyle("{}", parent); |
| 913 }; | 654 |
| 914 | 655 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0,
0, 0)))"]; |
| 915 exports.testPseudoClassHasWithClassOnDomMutation = async function(test) | 656 |
| 916 { | 657 insertStyleRule("body #" + parent.id + " > div { background-color: #000}
"); |
| 917 let parent = createElement(); | 658 |
| 918 let child = createElement(parent); | 659 if (await applyElemHideEmulation(selectors)) |
| 919 | 660 { |
| 920 let selectors = [ | 661 expectVisible(child); |
| 921 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 662 expectHidden(parent); |
| 922 "div[data-hide-me]", | 663 } |
| 923 "div:-abp-contains(hide me)", | 664 }); |
| 924 "div:-abp-has(> div.hideMe)" | 665 }); |
| 925 ]; | 666 }); |
| 926 | 667 |
| 927 if (await applyElemHideEmulation(test, selectors)) | 668 describe("DOM updates", () => |
| 928 { | 669 { |
| 929 await timeout(REFRESH_INTERVAL); | 670 it("Style", async() => |
| 930 | 671 { |
| 931 expectVisible(test, parent); | 672 let parent = createElementWithStyle("{}"); |
| 932 expectVisible(test, child); | 673 let child = createElementWithStyle("{}", parent); |
| 933 | 674 |
| 934 // Set the child element's class to "hideMe". This should run only the | 675 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0
, 0)))"]; |
| 935 // "div:-abp-has(> div.hideMe)" pattern. | 676 |
| 936 child.className = "hideMe"; | 677 if (await applyElemHideEmulation(selectors)) |
| 937 | 678 { |
| 938 await timeout(REFRESH_INTERVAL); | 679 expectVisible(child); |
| 939 | 680 expectVisible(parent); |
| 940 expectHidden(test, parent); | 681 |
| 941 expectVisible(test, child); | 682 insertStyleRule("body #" + parent.id + " > div { background-color: #000}
"); |
| 942 } | 683 await timeout(0); |
| 943 | 684 |
| 944 test.done(); | 685 expectVisible(child); |
| 945 }; | 686 expectVisible(parent); |
| 946 | 687 await timeout(REFRESH_INTERVAL); |
| 947 exports.testPseudoClassHasWithPseudoClassContainsOnDomMutation = async function(
test) | 688 |
| 948 { | 689 expectVisible(child); |
| 949 let parent = createElement(); | 690 expectHidden(parent); |
| 950 let child = createElement(parent); | 691 } |
| 951 | 692 }); |
| 952 let selectors = [ | 693 |
| 953 "div:-abp-properties(background-color: rgb(0, 0, 0))", | 694 it("Content", async() => |
| 954 "div[data-hide-me]", | 695 { |
| 955 "div:-abp-contains(hide me)", | 696 let parent = createElementWithStyle("{}"); |
| 956 "div:-abp-has(> div:-abp-contains(hide me))" | 697 let child = createElementWithStyle("{}", parent); |
| 957 ]; | 698 |
| 958 | 699 if (await applyElemHideEmulation(["div > div:-abp-contains(hide me)"])) |
| 959 child.innerText = "do nothing"; | 700 { |
| 960 | 701 expectVisible(parent); |
| 961 if (await applyElemHideEmulation(test, selectors)) | 702 expectVisible(child); |
| 962 { | 703 |
| 963 await timeout(REFRESH_INTERVAL); | 704 child.textContent = "hide me"; |
| 964 | 705 await timeout(0); |
| 965 expectVisible(test, parent); | 706 |
| 966 expectVisible(test, child); | 707 expectVisible(parent); |
| 967 | 708 expectVisible(child); |
| 968 // Set the child element's text to "hide me". This should run only the | 709 await timeout(REFRESH_INTERVAL); |
| 969 // "div:-abp-contains(hide me)" and | 710 |
| 970 // "div:-abp-has(> div:-abp-contains(hide me))" patterns. | 711 expectVisible(parent); |
| 971 child.innerText = "hide me"; | 712 expectHidden(child); |
| 972 | 713 } |
| 973 await timeout(REFRESH_INTERVAL); | 714 }); |
| 974 | 715 |
| 975 // Note: Even though it runs both the :-abp-contains() patterns, it only | 716 it("New element", async() => |
| 976 // hides the parent element because of revision d7d51d29aa34. | 717 { |
| 977 expectHidden(test, parent); | 718 let parent = createElementWithStyle("{}"); |
| 978 expectVisible(test, child); | 719 let child = createElementWithStyle("{ background-color: #000}", parent); |
| 979 } | 720 let sibling; |
| 980 | 721 let child2; |
| 981 test.done(); | 722 |
| 982 }; | 723 let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0
, 0)))"]; |
| 983 | 724 |
| 984 exports.testOnlyRelevantElementsProcessed = async function(test) | 725 if (await applyElemHideEmulation(selectors)) |
| 985 { | 726 { |
| 986 // <body> | 727 expectHidden(parent); |
| 987 // <div id="n1"> | 728 expectVisible(child); |
| 988 // <p id="n1_1"></p> | 729 |
| 989 // <p id="n1_2"></p> | 730 sibling = createElementWithStyle("{}"); |
| 990 // <p id="n1_4">Hello</p> | 731 await timeout(0); |
| 991 // </div> | 732 |
| 992 // <div id="n2"> | 733 expectHidden(parent); |
| 993 // <p id="n2_1"></p> | 734 expectVisible(child); |
| 994 // <p id="n2_2"></p> | 735 expectVisible(sibling); |
| 995 // <p id="n2_4">Hello</p> | 736 |
| 996 // </div> | 737 await timeout(REFRESH_INTERVAL); |
| 997 // <div id="n3"> | 738 |
| 998 // <p id="n3_1"></p> | 739 expectHidden(parent); |
| 999 // <p id="n3_2"></p> | 740 expectVisible(child); |
| 1000 // <p id="n3_4">Hello</p> | 741 expectVisible(sibling); |
| 1001 // </div> | 742 |
| 1002 // <div id="n4"> | 743 child2 = createElementWithStyle("{ background-color: #000}", |
| 1003 // <p id="n4_1"></p> | 744 sibling); |
| 1004 // <p id="n4_2"></p> | 745 await timeout(0); |
| 1005 // <p id="n4_4">Hello</p> | 746 |
| 1006 // </div> | 747 expectVisible(child2); |
| 1007 // </body> | 748 await timeout(REFRESH_INTERVAL); |
| 1008 for (let i of [1, 2, 3, 4]) | 749 |
| 1009 { | 750 expectHidden(parent); |
| 1010 let n = createElement(null, "div", `n${i}`); | 751 expectVisible(child); |
| 1011 for (let [j, text] of [[1], [2], [4, "Hello"]]) | 752 expectHidden(sibling); |
| 1012 createElement(n, "p", `n${i}_${j}`, text); | 753 expectVisible(child2); |
| 1013 } | 754 } |
| 1014 | 755 }); |
| 1015 let selectors = [ | 756 }); |
| 1016 "p:-abp-contains(Hello)", | 757 |
| 1017 "div:-abp-contains(Try me!)", | 758 it("Pseudo class properties on stylesheet load", async() => |
| 1018 "div:-abp-has(p:-abp-contains(This is good))" | 759 { |
| 1019 ]; | 760 let parent = createElement(); |
| 1020 | 761 let child = createElement(parent); |
| 1021 if (await applyElemHideEmulation(test, selectors)) | 762 |
| 1022 { | 763 let selectors = [ |
| 1023 await timeout(REFRESH_INTERVAL); | 764 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 1024 | 765 "div:-abp-contains(hide me)", |
| 1025 // This is only a sanity check to make sure everything else is working | 766 "div:-abp-has(> div.hideMe)" |
| 1026 // before we do the actual test. | 767 ]; |
| 768 |
| 769 if (await applyElemHideEmulation(selectors)) |
| 770 { |
| 771 await timeout(REFRESH_INTERVAL); |
| 772 |
| 773 expectVisible(parent); |
| 774 expectVisible(child); |
| 775 |
| 776 // Load a style sheet that targets the parent element. This should run onl
y |
| 777 // the "div:-abp-properties(background-color: rgb(0, 0, 0))" pattern. |
| 778 insertStyleRule("#" + parent.id + " {background-color: #000}"); |
| 779 |
| 780 await timeout(REFRESH_INTERVAL); |
| 781 |
| 782 expectHidden(parent); |
| 783 expectVisible(child); |
| 784 } |
| 785 }); |
| 786 |
| 787 describe("On DOM mutation", () => |
| 788 { |
| 789 it("Plain attributes", async() => |
| 790 { |
| 791 let parent = createElement(); |
| 792 let child = createElement(parent); |
| 793 |
| 794 let selectors = [ |
| 795 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 796 "div[data-hide-me]", |
| 797 "div:-abp-contains(hide me)", |
| 798 "div:-abp-has(> div.hideMe)" |
| 799 ]; |
| 800 |
| 801 if (await applyElemHideEmulation(selectors)) |
| 802 { |
| 803 await timeout(REFRESH_INTERVAL); |
| 804 |
| 805 expectVisible(parent); |
| 806 expectVisible(child); |
| 807 |
| 808 // Set the "data-hide-me" attribute on the child element. |
| 809 // |
| 810 // Note: Since the "div[data-hide-me]" pattern has already been processe
d |
| 811 // and the selector added to the document's style sheet, this will in fa
ct |
| 812 // not do anything at our end, but the browser will just match the selec
tor |
| 813 // and hide the element. |
| 814 child.setAttribute("data-hide-me", ""); |
| 815 |
| 816 await timeout(REFRESH_INTERVAL); |
| 817 |
| 818 expectVisible(parent); |
| 819 expectHidden(child); |
| 820 } |
| 821 }); |
| 822 |
| 823 it("Pseudo class contains", async() => |
| 824 { |
| 825 let parent = createElement(); |
| 826 let child = createElement(parent); |
| 827 |
| 828 let selectors = [ |
| 829 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 830 "div[data-hide-me]", |
| 831 "div:-abp-contains(hide me)", |
| 832 "div:-abp-has(> div.hideMe)" |
| 833 ]; |
| 834 |
| 835 child.innerText = "do nothing"; |
| 836 |
| 837 if (await applyElemHideEmulation(selectors)) |
| 838 { |
| 839 await timeout(REFRESH_INTERVAL); |
| 840 |
| 841 expectVisible(parent); |
| 842 expectVisible(child); |
| 843 |
| 844 // Set the child element's text to "hide me". This should run only the |
| 845 // "div:-abp-contains(hide me)" pattern. |
| 846 // |
| 847 // Note: We need to set Node.innerText here in order to trigger the |
| 848 // "characterData" DOM mutation on Chromium. If we set Node.textContent |
| 849 // instead, it triggers the "childList" DOM mutation instead. |
| 850 child.innerText = "hide me"; |
| 851 |
| 852 await timeout(REFRESH_INTERVAL); |
| 853 |
| 854 expectHidden(parent); |
| 855 expectVisible(child); |
| 856 } |
| 857 }); |
| 858 |
| 859 it("Pseudo class has", async() => |
| 860 { |
| 861 let parent = createElement(); |
| 862 let child = null; |
| 863 |
| 864 let selectors = [ |
| 865 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 866 "div[data-hide-me]", |
| 867 "div:-abp-contains(hide me)", |
| 868 "div:-abp-has(> div)" |
| 869 ]; |
| 870 |
| 871 if (await applyElemHideEmulation(selectors)) |
| 872 { |
| 873 await timeout(REFRESH_INTERVAL); |
| 874 |
| 875 expectVisible(parent); |
| 876 |
| 877 // Add the child element. This should run all the DOM-dependent patterns |
| 878 // ("div:-abp-contains(hide me)" and "div:-abp-has(> div)"). |
| 879 child = createElement(parent); |
| 880 |
| 881 await timeout(REFRESH_INTERVAL); |
| 882 |
| 883 expectHidden(parent); |
| 884 expectVisible(child); |
| 885 } |
| 886 }); |
| 887 |
| 888 it("Pseudo class has", async() => |
| 889 { |
| 890 let parent = createElement(); |
| 891 let child = createElement(parent); |
| 892 |
| 893 let selectors = [ |
| 894 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 895 "div[data-hide-me]", |
| 896 "div:-abp-contains(hide me)", |
| 897 "div:-abp-has(> div.hideMe)" |
| 898 ]; |
| 899 |
| 900 if (await applyElemHideEmulation(selectors)) |
| 901 { |
| 902 await timeout(REFRESH_INTERVAL); |
| 903 |
| 904 expectVisible(parent); |
| 905 expectVisible(child); |
| 906 |
| 907 // Set the child element's class to "hideMe". This should run only the |
| 908 // "div:-abp-has(> div.hideMe)" pattern. |
| 909 child.className = "hideMe"; |
| 910 |
| 911 await timeout(REFRESH_INTERVAL); |
| 912 |
| 913 expectHidden(parent); |
| 914 expectVisible(child); |
| 915 } |
| 916 }); |
| 917 |
| 918 it("Pseudo class has with pseudo class contains", async() => |
| 919 { |
| 920 let parent = createElement(); |
| 921 let child = createElement(parent); |
| 922 |
| 923 let selectors = [ |
| 924 "div:-abp-properties(background-color: rgb(0, 0, 0))", |
| 925 "div[data-hide-me]", |
| 926 "div:-abp-contains(hide me)", |
| 927 "div:-abp-has(> div:-abp-contains(hide me))" |
| 928 ]; |
| 929 |
| 930 child.innerText = "do nothing"; |
| 931 |
| 932 if (await applyElemHideEmulation(selectors)) |
| 933 { |
| 934 await timeout(REFRESH_INTERVAL); |
| 935 |
| 936 expectVisible(parent); |
| 937 expectVisible(child); |
| 938 |
| 939 // Set the child element's text to "hide me". This should run only the |
| 940 // "div:-abp-contains(hide me)" and |
| 941 // "div:-abp-has(> div:-abp-contains(hide me))" patterns. |
| 942 child.innerText = "hide me"; |
| 943 |
| 944 await timeout(REFRESH_INTERVAL); |
| 945 |
| 946 // Note: Even though it runs both the :-abp-contains() patterns, it only |
| 947 // hides the parent element because of revision d7d51d29aa34. |
| 948 expectHidden(parent); |
| 949 expectVisible(child); |
| 950 } |
| 951 }); |
| 952 }); |
| 953 |
| 954 it("Only relevant elements are processed", async() => |
| 955 { |
| 956 // <body> |
| 957 // <div id="n1"> |
| 958 // <p id="n1_1"></p> |
| 959 // <p id="n1_2"></p> |
| 960 // <p id="n1_4">Hello</p> |
| 961 // </div> |
| 962 // <div id="n2"> |
| 963 // <p id="n2_1"></p> |
| 964 // <p id="n2_2"></p> |
| 965 // <p id="n2_4">Hello</p> |
| 966 // </div> |
| 967 // <div id="n3"> |
| 968 // <p id="n3_1"></p> |
| 969 // <p id="n3_2"></p> |
| 970 // <p id="n3_4">Hello</p> |
| 971 // </div> |
| 972 // <div id="n4"> |
| 973 // <p id="n4_1"></p> |
| 974 // <p id="n4_2"></p> |
| 975 // <p id="n4_4">Hello</p> |
| 976 // </div> |
| 977 // </body> |
| 1027 for (let i of [1, 2, 3, 4]) | 978 for (let i of [1, 2, 3, 4]) |
| 1028 { | 979 { |
| 1029 for (let j of [1, 2, 4]) | 980 let n = createElement(null, "div", `n${i}`); |
| 1030 { | 981 for (let [j, text] of [[1], [2], [4, "Hello"]]) |
| 1031 let id = `n${i}_${j}`; | 982 createElement(n, "p", `n${i}_${j}`, text); |
| 1032 if (j == 4) | 983 } |
| 1033 expectHidden(test, testDocument.getElementById(id), id); | 984 |
| 985 let selectors = [ |
| 986 "p:-abp-contains(Hello)", |
| 987 "div:-abp-contains(Try me!)", |
| 988 "div:-abp-has(p:-abp-contains(This is good))" |
| 989 ]; |
| 990 |
| 991 if (await applyElemHideEmulation(selectors)) |
| 992 { |
| 993 await timeout(REFRESH_INTERVAL); |
| 994 |
| 995 // This is only a sanity check to make sure everything else is working |
| 996 // before we do the actual test. |
| 997 for (let i of [1, 2, 3, 4]) |
| 998 { |
| 999 for (let j of [1, 2, 4]) |
| 1000 { |
| 1001 let id = `n${i}_${j}`; |
| 1002 if (j == 4) |
| 1003 expectHidden(testDocument.getElementById(id), id); |
| 1004 else |
| 1005 expectVisible(testDocument.getElementById(id), id); |
| 1006 } |
| 1007 } |
| 1008 |
| 1009 // All <div> and <p> elements should be processed initially. |
| 1010 for (let element of [...testDocument.getElementsByTagName("div"), |
| 1011 ...testDocument.getElementsByTagName("p")]) |
| 1012 { |
| 1013 expectProcessed(element, element.id); |
| 1014 } |
| 1015 |
| 1016 // Modify the text in <p id="n4_1"> |
| 1017 testDocument.getElementById("n4_1").innerText = "Try me!"; |
| 1018 |
| 1019 await timeout(REFRESH_INTERVAL); |
| 1020 |
| 1021 // When an element's text is modified, only the element or one of its |
| 1022 // ancestors matching any selector is processed for :-abp-has() and |
| 1023 // :-abp-contains() |
| 1024 for (let element of [...testDocument.getElementsByTagName("div"), |
| 1025 ...testDocument.getElementsByTagName("p")]) |
| 1026 { |
| 1027 if (element.id == "n4" || element.id == "n4_1") |
| 1028 expectProcessed(element, element.id); |
| 1034 else | 1029 else |
| 1035 expectVisible(test, testDocument.getElementById(id), id); | 1030 expectNotProcessed(element, element.id); |
| 1031 } |
| 1032 |
| 1033 // Create a new <p id="n2_3"> element with no text. |
| 1034 createElement(testDocument.getElementById("n2"), "p", "n2_3"); |
| 1035 |
| 1036 await timeout(REFRESH_INTERVAL); |
| 1037 |
| 1038 // When a new element is added, only the element or one of its ancestors |
| 1039 // matching any selector is processed for :-abp-has() and :-abp-contains() |
| 1040 for (let element of [...testDocument.getElementsByTagName("div"), |
| 1041 ...testDocument.getElementsByTagName("p")]) |
| 1042 { |
| 1043 if (element.id == "n2" || element.id == "n2_3") |
| 1044 expectProcessed(element, element.id); |
| 1045 else |
| 1046 expectNotProcessed(element, element.id); |
| 1036 } | 1047 } |
| 1037 } | 1048 } |
| 1038 | 1049 }); |
| 1039 // All <div> and <p> elements should be processed initially. | 1050 }); |
| 1040 for (let element of [...testDocument.getElementsByTagName("div"), | |
| 1041 ...testDocument.getElementsByTagName("p")]) | |
| 1042 { | |
| 1043 expectProcessed(test, element, element.id); | |
| 1044 } | |
| 1045 | |
| 1046 // Modify the text in <p id="n4_1"> | |
| 1047 testDocument.getElementById("n4_1").innerText = "Try me!"; | |
| 1048 | |
| 1049 await timeout(REFRESH_INTERVAL); | |
| 1050 | |
| 1051 // When an element's text is modified, only the element or one of its | |
| 1052 // ancestors matching any selector is processed for :-abp-has() and | |
| 1053 // :-abp-contains() | |
| 1054 for (let element of [...testDocument.getElementsByTagName("div"), | |
| 1055 ...testDocument.getElementsByTagName("p")]) | |
| 1056 { | |
| 1057 if (element.id == "n4" || element.id == "n4_1") | |
| 1058 expectProcessed(test, element, element.id); | |
| 1059 else | |
| 1060 expectNotProcessed(test, element, element.id); | |
| 1061 } | |
| 1062 | |
| 1063 // Create a new <p id="n2_3"> element with no text. | |
| 1064 createElement(testDocument.getElementById("n2"), "p", "n2_3"); | |
| 1065 | |
| 1066 await timeout(REFRESH_INTERVAL); | |
| 1067 | |
| 1068 // When a new element is added, only the element or one of its ancestors | |
| 1069 // matching any selector is processed for :-abp-has() and :-abp-contains() | |
| 1070 for (let element of [...testDocument.getElementsByTagName("div"), | |
| 1071 ...testDocument.getElementsByTagName("p")]) | |
| 1072 { | |
| 1073 if (element.id == "n2" || element.id == "n2_3") | |
| 1074 expectProcessed(test, element, element.id); | |
| 1075 else | |
| 1076 expectNotProcessed(test, element, element.id); | |
| 1077 } | |
| 1078 } | |
| 1079 | |
| 1080 test.done(); | |
| 1081 }; | |
| OLD | NEW |