| Index: test/browser/elemHideEmulation.js | 
| =================================================================== | 
| --- a/test/browser/elemHideEmulation.js | 
| +++ b/test/browser/elemHideEmulation.js | 
| @@ -12,24 +12,27 @@ | 
| * GNU General Public License for more details. | 
| * | 
| * You should have received a copy of the GNU General Public License | 
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 
| */ | 
| "use strict"; | 
| -const {ElemHideEmulation} = require("../../lib/content/elemHideEmulation"); | 
| +const {ElemHideEmulation, setTestMode, | 
| + getTestInfo} = require("../../lib/content/elemHideEmulation"); | 
| const REFRESH_INTERVAL = 200; | 
| let testDocument = null; | 
| exports.setUp = function(callback) | 
| { | 
| + setTestMode(); | 
| + | 
| let iframe = document.createElement("iframe"); | 
| document.body.appendChild(iframe); | 
| testDocument = iframe.contentDocument; | 
| callback(); | 
| }; | 
| exports.tearDown = function(callback) | 
| @@ -72,16 +75,38 @@ | 
| if (typeof id != "undefined") | 
| withId = ` with ID '${id}'`; | 
| test.notEqual( | 
| window.getComputedStyle(element).display, "none", | 
| `The element${withId}'s display property should not be set to 'none'`); | 
| } | 
| +function expectProcessed(test, element, id = null) | 
| +{ | 
| + let withId = ""; | 
| + if (id) | 
| + withId = ` with ID '${id}'`; | 
| + | 
| + test.ok( | 
| + getTestInfo().lastProcessedElements.has(element), | 
| + `The element${withId} should have been processed`); | 
| +} | 
| + | 
| +function expectNotProcessed(test, element, id = null) | 
| +{ | 
| + let withId = ""; | 
| + if (id) | 
| + withId = ` with ID '${id}'`; | 
| + | 
| + test.ok( | 
| + !getTestInfo().lastProcessedElements.has(element), | 
| + `The element${withId} should not have been processed`); | 
| +} | 
| + | 
| function findUniqueId() | 
| { | 
| let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); | 
| if (!testDocument.getElementById(id)) | 
| return id; | 
| return findUniqueId(); | 
| } | 
| @@ -94,24 +119,27 @@ | 
| else | 
| { | 
| styleElement = testDocument.createElement("style"); | 
| testDocument.head.appendChild(styleElement); | 
| } | 
| styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); | 
| } | 
| -function createElement(parent) | 
| +function createElement(parent, type = "div", id = findUniqueId(), | 
| + innerText = null) | 
| { | 
| - let element = testDocument.createElement("div"); | 
| - element.id = findUniqueId(); | 
| + let element = testDocument.createElement(type); | 
| + element.id = id; | 
| if (!parent) | 
| testDocument.body.appendChild(element); | 
| else | 
| parent.appendChild(element); | 
| + if (innerText) | 
| + element.innerText = innerText; | 
| return element; | 
| } | 
| // Insert a <div> with a unique id and a CSS rule | 
| // for the the selector matching the id. | 
| function createElementWithStyle(styleBlock, parent) | 
| { | 
| let element = createElement(parent); | 
| @@ -893,8 +921,104 @@ | 
| }).then(() => | 
| { | 
| // Note: Even though it runs both the :-abp-contains() patterns, it only | 
| // hides the parent element because of revision d7d51d29aa34. | 
| expectHidden(test, parent); | 
| expectVisible(test, child); | 
| }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| }; | 
| + | 
| +exports.testOnlyRelevantElementsProcessed = function(test) | 
| +{ | 
| + // <body> | 
| + // <div id="n1"> | 
| + // <p id="n1_1"></p> | 
| + // <p id="n1_2"></p> | 
| + // <p id="n1_4">Hello</p> | 
| + // </div> | 
| + // <div id="n2"> | 
| + // <p id="n2_1"></p> | 
| + // <p id="n2_2"></p> | 
| + // <p id="n2_4">Hello</p> | 
| + // </div> | 
| + // <div id="n3"> | 
| + // <p id="n3_1"></p> | 
| + // <p id="n3_2"></p> | 
| + // <p id="n3_4">Hello</p> | 
| + // </div> | 
| + // <div id="n4"> | 
| + // <p id="n4_1"></p> | 
| + // <p id="n4_2"></p> | 
| + // <p id="n4_4">Hello</p> | 
| + // </div> | 
| + // </body> | 
| + for (let i of [1, 2, 3, 4]) | 
| + { | 
| + let n = createElement(null, "div", `n${i}`); | 
| + for (let [j, text] of [[1], [2], [4, "Hello"]]) | 
| + createElement(n, "p", `n${i}_${j}`, text); | 
| + } | 
| + | 
| + applyElemHideEmulation( | 
| + ["p:-abp-contains(Hello)", | 
| + "div:-abp-contains(Try me!)", | 
| + "div:-abp-has(p:-abp-contains(This is good))"] | 
| + ).then(() => timeout(REFRESH_INTERVAL) | 
| + ).then(() => | 
| + { | 
| + // This is only a sanity check to make sure everything else is working | 
| + // before we do the actual test. | 
| + for (let i of [1, 2, 3, 4]) | 
| + { | 
| + for (let j of [1, 2, 4]) | 
| + { | 
| + let id = `n${i}_${j}`; | 
| + if (j == 4) | 
| + expectHidden(test, testDocument.getElementById(id), id); | 
| + else | 
| + expectVisible(test, testDocument.getElementById(id), id); | 
| + } | 
| + } | 
| + | 
| + // All <div> and <p> elements should be processed initially. | 
| + for (let element of [...testDocument.getElementsByTagName("div"), | 
| + ...testDocument.getElementsByTagName("p")]) | 
| + { | 
| + expectProcessed(test, element, element.id); | 
| + } | 
| + | 
| + // Modify the text in <p id="n4_1"> | 
| + testDocument.getElementById("n4_1").innerText = "Try me!"; | 
| + | 
| + return timeout(REFRESH_INTERVAL); | 
| + }).then(() => | 
| + { | 
| + // When an element's text is modified, only the element or one of its | 
| + // ancestors matching any selector is processed for :-abp-has() and | 
| + // :-abp-contains() | 
| + for (let element of [...testDocument.getElementsByTagName("div"), | 
| + ...testDocument.getElementsByTagName("p")]) | 
| + { | 
| + if (element.id == "n4" || element.id == "n4_1") | 
| + expectProcessed(test, element, element.id); | 
| + else | 
| + expectNotProcessed(test, element, element.id); | 
| + } | 
| + | 
| + // Create a new <p id="n2_3"> element with no text. | 
| + createElement(testDocument.getElementById("n2"), "p", "n2_3"); | 
| + | 
| + return timeout(REFRESH_INTERVAL); | 
| + }).then(() => | 
| + { | 
| + // When a new element is added, only the element or one of its ancestors | 
| + // matching any selector is processed for :-abp-has() and :-abp-contains() | 
| + for (let element of [...testDocument.getElementsByTagName("div"), | 
| + ...testDocument.getElementsByTagName("p")]) | 
| + { | 
| + if (element.id == "n2" || element.id == "n2_3") | 
| + expectProcessed(test, element, element.id); | 
| + else | 
| + expectNotProcessed(test, element, element.id); | 
| + } | 
| + }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| +}; |