Left: | ||
Right: |
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 "use strict"; | 18 "use strict"; |
19 | 19 |
20 const {ElemHideEmulation} = require("../../lib/content/elemHideEmulation"); | 20 const {ElemHideEmulation} = require("../../lib/content/elemHideEmulation"); |
21 | 21 |
22 exports.tearDown = function(callback) | 22 const REFRESH_INTERVAL = 200; |
23 | |
24 let testDocument = null; | |
25 | |
26 exports.setUp = function(callback) | |
23 { | 27 { |
24 let styleElements = document.head.getElementsByTagName("style"); | 28 let iframe = document.createElement("iframe"); |
25 while (styleElements.length) | 29 document.body.appendChild(iframe); |
26 styleElements[0].parentNode.removeChild(styleElements[0]); | 30 testDocument = iframe.contentDocument; |
27 | |
28 let child; | |
29 while (child = document.body.firstChild) | |
30 child.parentNode.removeChild(child); | |
31 | 31 |
32 callback(); | 32 callback(); |
33 }; | 33 }; |
34 | 34 |
35 exports.tearDown = function(callback) | |
36 { | |
37 let iframe = testDocument.defaultView.frameElement; | |
38 iframe.parentNode.removeChild(iframe); | |
39 testDocument = null; | |
40 | |
41 callback(); | |
42 }; | |
43 | |
44 function timeout(delay) | |
45 { | |
46 return new Promise((resolve, reject) => | |
47 { | |
48 window.setTimeout(resolve, delay); | |
49 }); | |
50 } | |
51 | |
35 function unexpectedError(error) | 52 function unexpectedError(error) |
36 { | 53 { |
37 console.error(error); | 54 console.error(error); |
38 this.ok(false, "Unexpected error: " + error); | 55 this.ok(false, "Unexpected error: " + error); |
39 } | 56 } |
40 | 57 |
41 function expectHidden(test, element) | 58 function expectHidden(test, element) |
42 { | 59 { |
43 test.equal(window.getComputedStyle(element).display, "none", | 60 test.equal(window.getComputedStyle(element).display, "none", |
44 "The element's display property should be set to 'none'"); | 61 "The element's display property should be set to 'none'"); |
45 } | 62 } |
46 | 63 |
47 function expectVisible(test, element) | 64 function expectVisible(test, element) |
48 { | 65 { |
49 test.notEqual(window.getComputedStyle(element).display, "none", | 66 test.notEqual(window.getComputedStyle(element).display, "none", |
50 "The element's display property should not be set to 'none'"); | 67 "The element's display property should not be set to 'none'"); |
51 } | 68 } |
52 | 69 |
53 function findUniqueId() | 70 function findUniqueId() |
54 { | 71 { |
55 let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); | 72 let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); |
56 if (!document.getElementById(id)) | 73 if (!testDocument.getElementById(id)) |
57 return id; | 74 return id; |
58 return findUniqueId(); | 75 return findUniqueId(); |
59 } | 76 } |
60 | 77 |
61 function insertStyleRule(rule) | 78 function insertStyleRule(rule) |
62 { | 79 { |
63 let styleElement; | 80 let styleElement; |
64 let styleElements = document.head.getElementsByTagName("style"); | 81 let styleElements = testDocument.head.getElementsByTagName("style"); |
65 if (styleElements.length) | 82 if (styleElements.length) |
66 styleElement = styleElements[0]; | 83 styleElement = styleElements[0]; |
67 else | 84 else |
68 { | 85 { |
69 styleElement = document.createElement("style"); | 86 styleElement = testDocument.createElement("style"); |
70 document.head.appendChild(styleElement); | 87 testDocument.head.appendChild(styleElement); |
71 } | 88 } |
72 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); | 89 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
73 } | 90 } |
74 | 91 |
75 // Insert a <div> with a unique id and a CSS rule | 92 // Insert a <div> with a unique id and a CSS rule |
76 // for the the selector matching the id. | 93 // for the the selector matching the id. |
77 function createElementWithStyle(styleBlock, parent) | 94 function createElementWithStyle(styleBlock, parent) |
78 { | 95 { |
79 let element = document.createElement("div"); | 96 let element = testDocument.createElement("div"); |
80 element.id = findUniqueId(); | 97 element.id = findUniqueId(); |
81 if (!parent) | 98 if (!parent) |
82 document.body.appendChild(element); | 99 testDocument.body.appendChild(element); |
83 else | 100 else |
84 parent.appendChild(element); | 101 parent.appendChild(element); |
85 insertStyleRule("#" + element.id + " " + styleBlock); | 102 insertStyleRule("#" + element.id + " " + styleBlock); |
86 return element; | 103 return element; |
87 } | 104 } |
88 | 105 |
89 // Create a new ElemHideEmulation instance with @selectors. | 106 // Create a new ElemHideEmulation instance with @selectors. |
90 function applyElemHideEmulation(selectors) | 107 function applyElemHideEmulation(selectors) |
91 { | 108 { |
92 return Promise.resolve().then(() => | 109 return Promise.resolve().then(() => |
93 { | 110 { |
94 let elemHideEmulation = new ElemHideEmulation( | 111 let elemHideEmulation = new ElemHideEmulation( |
95 window, | 112 testDocument.defaultView, |
96 callback => | 113 callback => |
97 { | 114 { |
98 let patterns = []; | 115 let patterns = []; |
99 selectors.forEach(selector => | 116 selectors.forEach(selector => |
100 { | 117 { |
101 patterns.push({selector}); | 118 patterns.push({selector}); |
102 }); | 119 }); |
103 callback(patterns); | 120 callback(patterns); |
104 }, | 121 }, |
105 newSelectors => | 122 newSelectors => |
106 { | 123 { |
107 if (!newSelectors.length) | 124 if (!newSelectors.length) |
108 return; | 125 return; |
109 let selector = newSelectors.join(", "); | 126 let selector = newSelectors.join(", "); |
110 insertStyleRule(selector + "{display: none !important;}"); | 127 insertStyleRule(selector + "{display: none !important;}"); |
111 }, | 128 }, |
112 elems => | 129 elems => |
113 { | 130 { |
114 for (let elem of elems) | 131 for (let elem of elems) |
115 elem.style.display = "none"; | 132 elem.style.display = "none"; |
116 } | 133 } |
117 ); | 134 ); |
118 | 135 |
136 elemHideEmulation._invocationInterval = 100; | |
Wladimir Palant
2017/08/25 07:44:59
REFRESH_INTERVAL / 2?
hub
2017/08/25 13:48:13
Done.
| |
119 elemHideEmulation.apply(); | 137 elemHideEmulation.apply(); |
120 return elemHideEmulation; | 138 return elemHideEmulation; |
121 }); | 139 }); |
122 } | 140 } |
123 | 141 |
124 exports.testVerbatimPropertySelector = function(test) | 142 exports.testVerbatimPropertySelector = function(test) |
125 { | 143 { |
126 let toHide = createElementWithStyle("{background-color: #000}"); | 144 let toHide = createElementWithStyle("{background-color: #000}"); |
127 applyElemHideEmulation( | 145 applyElemHideEmulation( |
128 [":-abp-properties(background-color: rgb(0, 0, 0))"] | 146 [":-abp-properties(background-color: rgb(0, 0, 0))"] |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 | 250 |
233 exports.testDynamicallyChangedProperty = function(test) | 251 exports.testDynamicallyChangedProperty = function(test) |
234 { | 252 { |
235 let toHide = createElementWithStyle("{}"); | 253 let toHide = createElementWithStyle("{}"); |
236 applyElemHideEmulation( | 254 applyElemHideEmulation( |
237 [":-abp-properties(background-color: rgb(0, 0, 0))"] | 255 [":-abp-properties(background-color: rgb(0, 0, 0))"] |
238 ).then(() => | 256 ).then(() => |
239 { | 257 { |
240 expectVisible(test, toHide); | 258 expectVisible(test, toHide); |
241 insertStyleRule("#" + toHide.id + " {background-color: #000}"); | 259 insertStyleRule("#" + toHide.id + " {background-color: #000}"); |
242 return new Promise((resolve, reject) => | 260 |
243 { | 261 // Re-evaluation will only happen after a few seconds |
Wladimir Palant
2017/08/25 07:44:59
"after hundred milliseconds" or just "after a dela
hub
2017/08/25 13:48:12
Done.
| |
244 // Re-evaluation will only happen after a few seconds | 262 expectVisible(test, toHide); |
Wladimir Palant
2017/08/25 07:44:59
Testing for synchronous changes here and below is
hub
2017/08/25 13:48:14
Done.
Wladimir Palant
2017/08/25 20:57:40
You only fixed one instance of this issue. I noted
| |
245 expectVisible(test, toHide); | 263 return timeout(REFRESH_INTERVAL); |
246 window.setTimeout(() => | 264 }).then(() => |
247 { | 265 { |
248 expectHidden(test, toHide); | 266 expectHidden(test, toHide); |
249 resolve(); | |
250 }, 4000); | |
251 }); | |
252 }).catch(unexpectedError.bind(test)).then(() => test.done()); | 267 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
253 }; | 268 }; |
254 | 269 |
255 exports.testPseudoClassWithPropBeforeSelector = function(test) | 270 exports.testPseudoClassWithPropBeforeSelector = function(test) |
256 { | 271 { |
257 let parent = createElementWithStyle("{}"); | 272 let parent = createElementWithStyle("{}"); |
258 let child = createElementWithStyle("{background-color: #000}", parent); | 273 let child = createElementWithStyle("{background-color: #000}", parent); |
259 insertStyleRule(`#${child.id}::before {content: "publicite"}`); | 274 insertStyleRule(`#${child.id}::before {content: "publicite"}`); |
260 | 275 |
261 applyElemHideEmulation( | 276 applyElemHideEmulation( |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 { | 354 { |
340 expectVisible(test, parent); | 355 expectVisible(test, parent); |
341 expectVisible(test, middle); | 356 expectVisible(test, middle); |
342 expectVisible(test, sibling); | 357 expectVisible(test, sibling); |
343 expectHidden(test, toHide); | 358 expectHidden(test, toHide); |
344 }).catch(unexpectedError.bind(test)).then(() => test.done()); | 359 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
345 }; | 360 }; |
346 | 361 |
347 function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector , expectations) | 362 function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector , expectations) |
348 { | 363 { |
349 document.body.innerHTML = `<div id="parent"> | 364 testDocument.body.innerHTML = `<div id="parent"> |
350 <div id="middle"> | 365 <div id="middle"> |
351 <div id="middle1"><div id="inside" class="inside"></div></div> | 366 <div id="middle1"><div id="inside" class="inside"></div></div> |
352 </div> | 367 </div> |
353 <div id="sibling"> | 368 <div id="sibling"> |
354 <div id="tohide">to hide</div> | 369 <div id="tohide">to hide</div> |
355 </div> | 370 </div> |
356 <div id="sibling2"> | 371 <div id="sibling2"> |
357 <div id="sibling21"><div id="sibling211" class="inside"></div></div> | 372 <div id="sibling21"><div id="sibling211" class="inside"></div></div> |
358 </div> | 373 </div> |
359 </div>`; | 374 </div>`; |
360 let elems = { | 375 let elems = { |
361 parent: document.getElementById("parent"), | 376 parent: testDocument.getElementById("parent"), |
362 middle: document.getElementById("middle"), | 377 middle: testDocument.getElementById("middle"), |
363 inside: document.getElementById("inside"), | 378 inside: testDocument.getElementById("inside"), |
364 sibling: document.getElementById("sibling"), | 379 sibling: testDocument.getElementById("sibling"), |
365 sibling2: document.getElementById("sibling2"), | 380 sibling2: testDocument.getElementById("sibling2"), |
366 toHide: document.getElementById("tohide") | 381 toHide: testDocument.getElementById("tohide") |
367 }; | 382 }; |
368 | 383 |
369 insertStyleRule(".inside {}"); | 384 insertStyleRule(".inside {}"); |
370 | 385 |
371 applyElemHideEmulation( | 386 applyElemHideEmulation( |
372 [selector] | 387 [selector] |
373 ).then(() => | 388 ).then(() => |
374 { | 389 { |
375 for (let elem in expectations) | 390 for (let elem in expectations) |
376 if (elems[elem]) | 391 if (elems[elem]) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 sibling: true, | 435 sibling: true, |
421 sibling2: true, | 436 sibling2: true, |
422 toHide: true | 437 toHide: true |
423 }; | 438 }; |
424 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( | 439 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
425 test, "div:-abp-has(> body div.inside) + div > div", expectations); | 440 test, "div:-abp-has(> body div.inside) + div > div", expectations); |
426 }; | 441 }; |
427 | 442 |
428 exports.testPseudoClassContains = function(test) | 443 exports.testPseudoClassContains = function(test) |
429 { | 444 { |
430 document.body.innerHTML = `<div id="parent"> | 445 testDocument.body.innerHTML = `<div id="parent"> |
431 <div id="middle"> | 446 <div id="middle"> |
432 <div id="middle1"><div id="inside" class="inside"></div></div> | 447 <div id="middle1"><div id="inside" class="inside"></div></div> |
433 </div> | 448 </div> |
434 <div id="sibling"> | 449 <div id="sibling"> |
435 <div id="tohide">to hide</div> | 450 <div id="tohide">to hide</div> |
436 </div> | 451 </div> |
437 <div id="sibling2"> | 452 <div id="sibling2"> |
438 <div id="sibling21"><div id="sibling211" class="inside"></div></div> | 453 <div id="sibling21"><div id="sibling211" class="inside"></div></div> |
439 </div> | 454 </div> |
440 </div>`; | 455 </div>`; |
441 let parent = document.getElementById("parent"); | 456 let parent = testDocument.getElementById("parent"); |
442 let middle = document.getElementById("middle"); | 457 let middle = testDocument.getElementById("middle"); |
443 let inside = document.getElementById("inside"); | 458 let inside = testDocument.getElementById("inside"); |
444 let sibling = document.getElementById("sibling"); | 459 let sibling = testDocument.getElementById("sibling"); |
445 let sibling2 = document.getElementById("sibling2"); | 460 let sibling2 = testDocument.getElementById("sibling2"); |
446 let toHide = document.getElementById("tohide"); | 461 let toHide = testDocument.getElementById("tohide"); |
447 | 462 |
448 applyElemHideEmulation( | 463 applyElemHideEmulation( |
449 ["#parent div:-abp-contains(to hide)"] | 464 ["#parent div:-abp-contains(to hide)"] |
450 ).then(() => | 465 ).then(() => |
451 { | 466 { |
452 expectVisible(test, parent); | 467 expectVisible(test, parent); |
453 expectVisible(test, middle); | 468 expectVisible(test, middle); |
454 expectVisible(test, inside); | 469 expectVisible(test, inside); |
455 expectHidden(test, sibling); | 470 expectHidden(test, sibling); |
456 expectVisible(test, sibling2); | 471 expectVisible(test, sibling2); |
(...skipping 20 matching lines...) Expand all Loading... | |
477 let child = createElementWithStyle("{}", parent); | 492 let child = createElementWithStyle("{}", parent); |
478 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); | 493 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); |
479 applyElemHideEmulation( | 494 applyElemHideEmulation( |
480 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] | 495 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] |
481 ).then(() => | 496 ).then(() => |
482 { | 497 { |
483 expectVisible(test, child); | 498 expectVisible(test, child); |
484 expectHidden(test, parent); | 499 expectHidden(test, parent); |
485 }).catch(unexpectedError.bind(test)).then(() => test.done()); | 500 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
486 }; | 501 }; |
502 | |
503 exports.testDomUpdatesStyle = function(test) | |
504 { | |
505 let parent = createElementWithStyle("{}"); | |
506 let child = createElementWithStyle("{}", parent); | |
507 applyElemHideEmulation( | |
508 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] | |
509 ).then(() => | |
510 { | |
511 expectVisible(test, child); | |
512 expectVisible(test, parent); | |
513 | |
514 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); | |
515 | |
516 expectVisible(test, child); | |
517 expectVisible(test, parent); | |
518 return timeout(REFRESH_INTERVAL); | |
519 }).then(() => | |
520 { | |
521 expectVisible(test, child); | |
522 expectHidden(test, parent); | |
523 }).catch(unexpectedError.bind(test)).then(() => test.done()); | |
524 }; | |
525 | |
526 exports.testDomUpdatesContent = function(test) | |
527 { | |
528 let parent = createElementWithStyle("{}"); | |
529 let child = createElementWithStyle("{}", parent); | |
530 applyElemHideEmulation( | |
531 ["div > div:-abp-contains(hide me)"] | |
532 ).then(() => | |
533 { | |
534 expectVisible(test, parent); | |
535 expectVisible(test, child); | |
536 | |
537 child.textContent = "hide me"; | |
538 | |
539 expectVisible(test, parent); | |
540 expectVisible(test, child); | |
541 return timeout(REFRESH_INTERVAL); | |
542 }).then(() => | |
543 { | |
544 expectVisible(test, parent); | |
545 expectHidden(test, child); | |
546 }).catch(unexpectedError.bind(test)).then(() => test.done()); | |
547 }; | |
548 | |
549 exports.testDomUpdatesNewElement = function(test) | |
550 { | |
551 let parent = createElementWithStyle("{}"); | |
552 let child = createElementWithStyle("{ background-color: #000}", parent); | |
553 let sibling; | |
554 let child2; | |
555 applyElemHideEmulation( | |
556 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] | |
557 ).then(() => | |
558 { | |
559 expectHidden(test, parent); | |
560 expectVisible(test, child); | |
561 | |
562 sibling = createElementWithStyle("{}"); | |
563 expectVisible(test, sibling); | |
564 | |
Wladimir Palant
2017/08/25 07:44:59
I guess the two lines above should be removed? You
hub
2017/08/25 13:48:14
Done.
| |
565 expectHidden(test, parent); | |
566 expectVisible(test, child); | |
567 expectVisible(test, sibling); | |
568 | |
569 return timeout(REFRESH_INTERVAL); | |
570 }).then(() => | |
571 { | |
572 expectHidden(test, parent); | |
573 expectVisible(test, child); | |
574 expectVisible(test, sibling); | |
575 | |
576 child2 = createElementWithStyle("{ background-color: #000}", | |
577 sibling); | |
578 expectVisible(test, child2); | |
579 return timeout(REFRESH_INTERVAL); | |
580 }).then(() => | |
581 { | |
582 expectHidden(test, parent); | |
583 expectVisible(test, child); | |
584 expectHidden(test, sibling); | |
585 expectVisible(test, child2); | |
586 }).catch(unexpectedError.bind(test)).then(() => test.done()); | |
587 }; | |
OLD | NEW |