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