Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: test/browser/elemHideEmulation.js

Issue 29494577: Issue 5438 - Observer DOM changes to reapply filters. (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Created July 21, 2017, 7:53 p.m.
Right Patch Set: Addressed comments Created Aug. 26, 2017, 1:44 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « lib/content/elemHideEmulation.js ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
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 const REFRESH_INTERVAL = 200;
23
24 let testDocument = null;
25
26 exports.setUp = function(callback)
27 {
28 let iframe = document.createElement("iframe");
29 document.body.appendChild(iframe);
30 testDocument = iframe.contentDocument;
31
32 callback();
33 };
34
22 exports.tearDown = function(callback) 35 exports.tearDown = function(callback)
23 { 36 {
24 let styleElements = document.head.getElementsByTagName("style"); 37 let iframe = testDocument.defaultView.frameElement;
25 while (styleElements.length) 38 iframe.parentNode.removeChild(iframe);
26 styleElements[0].parentNode.removeChild(styleElements[0]); 39 testDocument = null;
27
28 let child;
29 while (child = document.body.firstChild)
30 child.parentNode.removeChild(child);
31 40
32 callback(); 41 callback();
33 }; 42 };
43
44 function timeout(delay)
45 {
46 return new Promise((resolve, reject) =>
47 {
48 window.setTimeout(resolve, delay);
49 });
50 }
34 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.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2;
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
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 return timeout(0);
244 // Re-evaluation will only happen after a few seconds 262 }).then(() =>
245 expectVisible(test, toHide); 263 {
246 window.setTimeout(() => 264 // Re-evaluation will only happen after a delay
247 { 265 expectVisible(test, toHide);
248 expectHidden(test, toHide); 266 return timeout(REFRESH_INTERVAL);
249 resolve(); 267 }).then(() =>
250 }, 4000); 268 {
251 }); 269 expectHidden(test, toHide);
252 }).catch(unexpectedError.bind(test)).then(() => test.done()); 270 }).catch(unexpectedError.bind(test)).then(() => test.done());
253 }; 271 };
254 272
255 exports.testPseudoClassWithPropBeforeSelector = function(test) 273 exports.testPseudoClassWithPropBeforeSelector = function(test)
256 { 274 {
257 let parent = createElementWithStyle("{}"); 275 let parent = createElementWithStyle("{}");
258 let child = createElementWithStyle("{background-color: #000}", parent); 276 let child = createElementWithStyle("{background-color: #000}", parent);
259 insertStyleRule(`#${child.id}::before {content: "publicite"}`); 277 insertStyleRule(`#${child.id}::before {content: "publicite"}`);
260 278
261 applyElemHideEmulation( 279 applyElemHideEmulation(
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 { 357 {
340 expectVisible(test, parent); 358 expectVisible(test, parent);
341 expectVisible(test, middle); 359 expectVisible(test, middle);
342 expectVisible(test, sibling); 360 expectVisible(test, sibling);
343 expectHidden(test, toHide); 361 expectHidden(test, toHide);
344 }).catch(unexpectedError.bind(test)).then(() => test.done()); 362 }).catch(unexpectedError.bind(test)).then(() => test.done());
345 }; 363 };
346 364
347 function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector , expectations) 365 function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector , expectations)
348 { 366 {
349 document.body.innerHTML = `<div id="parent"> 367 testDocument.body.innerHTML = `<div id="parent">
350 <div id="middle"> 368 <div id="middle">
351 <div id="middle1"><div id="inside" class="inside"></div></div> 369 <div id="middle1"><div id="inside" class="inside"></div></div>
352 </div> 370 </div>
353 <div id="sibling"> 371 <div id="sibling">
354 <div id="tohide">to hide</div> 372 <div id="tohide">to hide</div>
355 </div> 373 </div>
356 <div id="sibling2"> 374 <div id="sibling2">
357 <div id="sibling21"><div id="sibling211" class="inside"></div></div> 375 <div id="sibling21"><div id="sibling211" class="inside"></div></div>
358 </div> 376 </div>
359 </div>`; 377 </div>`;
360 let elems = { 378 let elems = {
361 parent: document.getElementById("parent"), 379 parent: testDocument.getElementById("parent"),
362 middle: document.getElementById("middle"), 380 middle: testDocument.getElementById("middle"),
363 inside: document.getElementById("inside"), 381 inside: testDocument.getElementById("inside"),
364 sibling: document.getElementById("sibling"), 382 sibling: testDocument.getElementById("sibling"),
365 sibling2: document.getElementById("sibling2"), 383 sibling2: testDocument.getElementById("sibling2"),
366 toHide: document.getElementById("tohide") 384 toHide: testDocument.getElementById("tohide")
367 }; 385 };
368 386
369 insertStyleRule(".inside {}"); 387 insertStyleRule(".inside {}");
370 388
371 applyElemHideEmulation( 389 applyElemHideEmulation(
372 [selector] 390 [selector]
373 ).then(() => 391 ).then(() =>
374 { 392 {
375 for (let elem in expectations) 393 for (let elem in expectations)
376 if (elems[elem]) 394 if (elems[elem])
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 sibling: true, 438 sibling: true,
421 sibling2: true, 439 sibling2: true,
422 toHide: true 440 toHide: true
423 }; 441 };
424 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( 442 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(
425 test, "div:-abp-has(> body div.inside) + div > div", expectations); 443 test, "div:-abp-has(> body div.inside) + div > div", expectations);
426 }; 444 };
427 445
428 exports.testPseudoClassContains = function(test) 446 exports.testPseudoClassContains = function(test)
429 { 447 {
430 document.body.innerHTML = `<div id="parent"> 448 testDocument.body.innerHTML = `<div id="parent">
431 <div id="middle"> 449 <div id="middle">
432 <div id="middle1"><div id="inside" class="inside"></div></div> 450 <div id="middle1"><div id="inside" class="inside"></div></div>
433 </div> 451 </div>
434 <div id="sibling"> 452 <div id="sibling">
435 <div id="tohide">to hide</div> 453 <div id="tohide">to hide</div>
436 </div> 454 </div>
437 <div id="sibling2"> 455 <div id="sibling2">
438 <div id="sibling21"><div id="sibling211" class="inside"></div></div> 456 <div id="sibling21"><div id="sibling211" class="inside"></div></div>
439 </div> 457 </div>
440 </div>`; 458 </div>`;
441 let parent = document.getElementById("parent"); 459 let parent = testDocument.getElementById("parent");
442 let middle = document.getElementById("middle"); 460 let middle = testDocument.getElementById("middle");
443 let inside = document.getElementById("inside"); 461 let inside = testDocument.getElementById("inside");
444 let sibling = document.getElementById("sibling"); 462 let sibling = testDocument.getElementById("sibling");
445 let sibling2 = document.getElementById("sibling2"); 463 let sibling2 = testDocument.getElementById("sibling2");
446 let toHide = document.getElementById("tohide"); 464 let toHide = testDocument.getElementById("tohide");
447 465
448 applyElemHideEmulation( 466 applyElemHideEmulation(
449 ["#parent div:-abp-contains(to hide)"] 467 ["#parent div:-abp-contains(to hide)"]
450 ).then(() => 468 ).then(() =>
451 { 469 {
452 expectVisible(test, parent); 470 expectVisible(test, parent);
453 expectVisible(test, middle); 471 expectVisible(test, middle);
454 expectVisible(test, inside); 472 expectVisible(test, inside);
455 expectHidden(test, sibling); 473 expectHidden(test, sibling);
456 expectVisible(test, sibling2); 474 expectVisible(test, sibling2);
(...skipping 20 matching lines...) Expand all
477 let child = createElementWithStyle("{}", parent); 495 let child = createElementWithStyle("{}", parent);
478 insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); 496 insertStyleRule("body #" + parent.id + " > div { background-color: #000}");
479 applyElemHideEmulation( 497 applyElemHideEmulation(
480 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] 498 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]
481 ).then(() => 499 ).then(() =>
482 { 500 {
483 expectVisible(test, child); 501 expectVisible(test, child);
484 expectHidden(test, parent); 502 expectHidden(test, parent);
485 }).catch(unexpectedError.bind(test)).then(() => test.done()); 503 }).catch(unexpectedError.bind(test)).then(() => test.done());
486 }; 504 };
505
506 exports.testDomUpdatesStyle = function(test)
507 {
508 let parent = createElementWithStyle("{}");
509 let child = createElementWithStyle("{}", parent);
510 applyElemHideEmulation(
511 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]
512 ).then(() =>
513 {
514 expectVisible(test, child);
515 expectVisible(test, parent);
516
517 insertStyleRule("body #" + parent.id + " > div { background-color: #000}");
518 return timeout(0);
519 }).then(() =>
520 {
521 expectVisible(test, child);
522 expectVisible(test, parent);
523 return timeout(REFRESH_INTERVAL);
524 }).then(() =>
525 {
526 expectVisible(test, child);
527 expectHidden(test, parent);
528 }).catch(unexpectedError.bind(test)).then(() => test.done());
529 };
530
531 exports.testDomUpdatesContent = function(test)
532 {
533 let parent = createElementWithStyle("{}");
534 let child = createElementWithStyle("{}", parent);
535 applyElemHideEmulation(
536 ["div > div:-abp-contains(hide me)"]
537 ).then(() =>
538 {
539 expectVisible(test, parent);
540 expectVisible(test, child);
541
542 child.textContent = "hide me";
543 return timeout(0);
544 }).then(() =>
545 {
546 expectVisible(test, parent);
547 expectVisible(test, child);
548 return timeout(REFRESH_INTERVAL);
549 }).then(() =>
550 {
551 expectVisible(test, parent);
552 expectHidden(test, child);
553 }).catch(unexpectedError.bind(test)).then(() => test.done());
554 };
555
556 exports.testDomUpdatesNewElement = function(test)
557 {
558 let parent = createElementWithStyle("{}");
559 let child = createElementWithStyle("{ background-color: #000}", parent);
560 let sibling;
561 let child2;
562 applyElemHideEmulation(
563 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]
564 ).then(() =>
565 {
566 expectHidden(test, parent);
567 expectVisible(test, child);
568
569 sibling = createElementWithStyle("{}");
570 return timeout(0);
571 }).then(() =>
572 {
573 expectHidden(test, parent);
574 expectVisible(test, child);
575 expectVisible(test, sibling);
576
577 return timeout(REFRESH_INTERVAL);
578 }).then(() =>
579 {
580 expectHidden(test, parent);
581 expectVisible(test, child);
582 expectVisible(test, sibling);
583
584 child2 = createElementWithStyle("{ background-color: #000}",
585 sibling);
586 return timeout(0);
587 }).then(() =>
588 {
589 expectVisible(test, child2);
590 return timeout(REFRESH_INTERVAL);
591 }).then(() =>
592 {
593 expectHidden(test, parent);
594 expectVisible(test, child);
595 expectHidden(test, sibling);
596 expectVisible(test, child2);
597 }).catch(unexpectedError.bind(test)).then(() => test.done());
598 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld