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

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

Issue 29448560: Issue 5249 - Implement :-abp-contains() (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Updated and rebased Created June 8, 2017, 12:19 a.m.
Right Patch Set: Use includes() and improve test. Created June 28, 2017, 4:11 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « chrome/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
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-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 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 /* globals ElemHideEmulation, splitSelector, 20 /* globals ElemHideEmulation */
21 parseSelectorContent,
22 parseSelector, positionInParent, makeSelector,
23 PlainSelector, HasSelector, PropsSelector, ContainsSelector */
24 21
25 let myUrl = document.currentScript.src; 22 let myUrl = document.currentScript.src;
26 23
27 exports.tearDown = function(callback) 24 exports.tearDown = function(callback)
28 { 25 {
29 let styleElements = document.head.getElementsByTagName("style"); 26 let styleElements = document.head.getElementsByTagName("style");
30 while (styleElements.length) 27 while (styleElements.length)
31 styleElements[0].parentNode.removeChild(styleElements[0]); 28 styleElements[0].parentNode.removeChild(styleElements[0]);
32 29
33 let child; 30 let child;
34 while (child = document.body.firstChild) 31 while (child = document.body.firstChild)
35 document.body.removeChild(child); 32 child.parentNode.removeChild(child);
36 33
37 callback(); 34 callback();
38 }; 35 };
39 36
40 function unexpectedError(error) 37 function unexpectedError(error)
41 { 38 {
42 console.error(error); 39 console.error(error);
43 this.ok(false, "Unexpected error: " + error); 40 this.ok(false, "Unexpected error: " + error);
44 } 41 }
45 42
(...skipping 24 matching lines...) Expand all
70 if (styleElements.length) 67 if (styleElements.length)
71 styleElement = styleElements[0]; 68 styleElement = styleElements[0];
72 else 69 else
73 { 70 {
74 styleElement = document.createElement("style"); 71 styleElement = document.createElement("style");
75 document.head.appendChild(styleElement); 72 document.head.appendChild(styleElement);
76 } 73 }
77 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); 74 styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length);
78 } 75 }
79 76
80 // insert a <div> with a unique id and and empty CSS rule 77 // insert a <div> with a unique id and a CSS rule
81 // for the the selector matching the id. 78 // for the the selector matching the id.
82 function createElementWithStyle(styleBlock, parent) 79 function createElementWithStyle(styleBlock, parent)
83 { 80 {
84 let element = document.createElement("div"); 81 let element = document.createElement("div");
85 element.id = findUniqueId(); 82 element.id = findUniqueId();
86 if (!parent) 83 if (!parent)
87 document.body.appendChild(element); 84 document.body.appendChild(element);
88 else 85 else
89 parent.appendChild(element); 86 parent.appendChild(element);
90 insertStyleRule("#" + element.id + " " + styleBlock); 87 insertStyleRule("#" + element.id + " " + styleBlock);
91 return element; 88 return element;
92 } 89 }
93 90
94 // Will ensure the class ElemHideEmulation is loaded 91 // Will ensure the class ElemHideEmulation is loaded.
95 // and then will call the callback. 92 // NOTE: if it never loads, this will probably hang.
96 // NOTE: if it never loads, this will probably hang in an infinite
97 // loop
98 function loadElemHideEmulation() 93 function loadElemHideEmulation()
99 { 94 {
100 if (typeof ElemHideEmulation == "undefined") 95 if (typeof ElemHideEmulation == "undefined")
101 { 96 {
102 return loadScript(myUrl + "/../../../lib/common.js").then(() => 97 return loadScript(myUrl + "/../../../lib/common.js").then(() =>
103 { 98 {
104 return loadScript(myUrl + "/../../../chrome/content/elemHideEmulation.js") ; 99 return loadScript(myUrl + "/../../../chrome/content/elemHideEmulation.js") ;
105 }).then(() => 100 }).then(() =>
106 { 101 {
107 return loadElemHideEmulation(); 102 return loadElemHideEmulation();
108 }); 103 });
109 } 104 }
110 105
111 return Promise.resolve(); 106 return Promise.resolve();
112 } 107 }
113 108
114 // instantiate a ElemHideEmulation with @selectors. 109 // Create a new ElemHideEmulation instance with @selectors.
115 function applyElemHideEmulation(selectors) 110 function applyElemHideEmulation(selectors)
116 { 111 {
117 return loadElemHideEmulation().then(() => 112 return loadElemHideEmulation().then(() =>
118 { 113 {
119 let elemHideEmulation = new ElemHideEmulation( 114 let elemHideEmulation = new ElemHideEmulation(
120 window, 115 window,
121 callback => 116 callback =>
122 { 117 {
123 let patterns = []; 118 let patterns = [];
124 selectors.forEach(selector => 119 selectors.forEach(selector =>
125 { 120 {
126 patterns.push({selector}); 121 patterns.push({selector});
127 }); 122 });
128 callback(patterns); 123 callback(patterns);
129 }, 124 },
130 newSelectors => 125 newSelectors =>
131 { 126 {
132 if (!newSelectors.length) 127 if (!newSelectors.length)
133 return; 128 return;
134 let selector = newSelectors.join(", "); 129 let selector = newSelectors.join(", ");
135 insertStyleRule(selector + "{display: none !important;}"); 130 insertStyleRule(selector + "{display: none !important;}");
136 }, 131 },
137 elems => 132 elems =>
138 { 133 {
139 if (!elems.length)
140 return;
141 for (let elem of elems) 134 for (let elem of elems)
142 elem.style.display = "none"; 135 elem.style.display = "none";
143 } 136 }
144 ); 137 );
145 138
146 elemHideEmulation.apply(); 139 elemHideEmulation.apply();
147 return Promise.resolve(); 140 return Promise.resolve(elemHideEmulation);
148 }); 141 });
149 } 142 }
150
151 exports.testParseSelectorContent = function(test)
152 {
153 loadElemHideEmulation().then(() =>
154 {
155 let parsed = parseSelectorContent(":-abp-has(> div) > div", 10);
156 test.equal(parsed.text, "> div");
157 test.equal(parsed.end, 15);
158
159 parsed = parseSelectorContent("\"> div\") > div", 0);
160 test.equal(parsed.text, "\"> div\"");
161 test.equal(parsed.end, 7);
162 parsed = parseSelectorContent(" \"> div\" ) > div", 0);
163 test.equal(parsed.text, " \"> div\" ");
164 test.equal(parsed.end, 9);
165
166 // parens not closed.
167 parsed = parseSelectorContent("> div > div", 0);
168 test.equal(parsed, null);
169 }).catch(unexpectedError.bind(test)).then(() => test.done());
170 };
171
172 exports.testParseSelector = function(test)
173 {
174 loadElemHideEmulation().then(() =>
175 {
176 let selectors = parseSelector("");
177 test.equal(selectors.length, 0);
178
179 let selector = "div > :-abp-properties('background-color: rgb(0, 0, 0)')";
180 selectors = parseSelector(selector);
181 test.equal(selectors.length, 2);
182 test.ok(selectors[0] instanceof PlainSelector);
183 test.ok(selectors[1] instanceof PropsSelector);
184
185 selector = "div > :-abp-has(> div.inside) > div";
186 selectors = parseSelector(selector);
187 test.equal(selectors.length, 3);
188 test.ok(selectors[0] instanceof PlainSelector);
189 test.ok(selectors[1] instanceof HasSelector);
190 test.ok(selectors[2] instanceof PlainSelector);
191
192 selector = "div > div:-abp-has(> div.inside) > div";
193 selectors = parseSelector(selector);
194
195 test.equal(selectors.length, 3);
196 test.ok(selectors[0] instanceof PlainSelector);
197 test.ok(selectors[1] instanceof HasSelector);
198 test.ok(selectors[2] instanceof PlainSelector);
199
200 selector = "div > :-abp-has(> div.inside) > :-abp-properties(background-colo r: rgb(0, 0, 0))";
201 selectors = parseSelector(selector);
202
203 test.equal(selectors.length, 4);
204 test.ok(selectors[0] instanceof PlainSelector);
205 test.ok(selectors[1] instanceof HasSelector);
206 test.ok(selectors[2] instanceof PlainSelector);
207 test.ok(selectors[3] instanceof PropsSelector);
208
209 selector = "div > :-abp-has(> div.inside > :-abp-properties(background-color : rgb(0, 0, 0))";
210 selectors = parseSelector(selector);
211 test.equal(selectors, null);
212
213 selector = 'div[arial-label="Story"]:-abp-has(> div > div > span > span:-abp -contains(Suggested Post))';
214 selectors = parseSelector(selector);
215 test.equal(selectors.length, 2);
216 test.ok(selectors[0] instanceof PlainSelector);
217 test.ok(selectors[1] instanceof HasSelector);
218
219 selectors = selectors[1]._innerSelectors;
220 test.equals(selectors.length, 2);
221 test.ok(selectors[0] instanceof PlainSelector);
222 test.ok(selectors[1] instanceof ContainsSelector);
223 test.equals(selectors[1]._text, "Suggested Post");
224
225 // -abp-has-unsupported() is unknown. Ensure we fail parsing.
226 selector = 'div[arial-label="Story"]:-abp-has(> div > div > span > span:-abp -unsupported("Suggested Post"))';
227 selectors = parseSelector(selector);
228 test.equal(selectors, null);
229 }).catch(unexpectedError.bind(test)).then(() => test.done());
230 };
231
232 function buildDom(doc)
233 {
234 doc.body.innerHTML = `<div id="parent">
235 <div id="middle">
236 <div id="middle1"><div id="inside" class="inside"></div></div>
237 </div>
238 <div id="sibling">
239 <div id="tohide">to hide</div>
240 </div>
241 <div id="sibling2">
242 <div id="sibling21"><div id="sibling211" class="inside"></div></div>
243 </div>
244 </div>`;
245 let parent = document.getElementById("parent");
246 let middle = document.getElementById("middle");
247 let middle1 = document.getElementById("middle1");
248 let inside = document.getElementById("inside");
249 let sibling = document.getElementById("sibling");
250 let sibling2 = document.getElementById("sibling2");
251 let toHide = document.getElementById("tohide");
252 return {parent, middle, middle1, inside, sibling, sibling2, toHide};
253 }
254
255 exports.testPositionInParent = function(test)
256 {
257 let nodes = buildDom(document);
258
259 loadElemHideEmulation().then(() =>
260 {
261 test.equal(positionInParent(nodes.middle1), 1);
262 test.equal(positionInParent(nodes.inside), 1);
263 test.equal(positionInParent(nodes.sibling2), 3);
264 }).catch(unexpectedError.bind(test)).then(() => test.done());
265 };
266
267 exports.testMakeSelector = function(test)
268 {
269 let nodes = buildDom(document);
270
271 loadElemHideEmulation().then(() =>
272 {
273 test.equal(makeSelector(nodes.middle, ""),
274 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(1)" );
275 test.equal(makeSelector(nodes.toHide, ""),
276 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(2) > DIV:nth-child(1)");
277 }).catch(unexpectedError.bind(test)).then(() => test.done());
278 };
279
280 exports.testPlainSelector = function(test)
281 {
282 buildDom(document);
283
284 loadElemHideEmulation().then(() =>
285 {
286 let selector = new PlainSelector("div > div");
287
288 let iter = selector.getSelectors("foo > ");
289 let value = iter.next();
290 test.equal(value.value[0], "foo > div > div");
291 test.ok(iter.next().done);
292 }).catch(unexpectedError.bind(test)).then(() => test.done());
293 };
294
295 exports.testHasSelector = function(test)
296 {
297 buildDom(document);
298
299 loadElemHideEmulation().then(() =>
300 {
301 let selector = new HasSelector("> div.inside");
302
303 let iter = selector.getSelectors("", document, document.sheet);
304 let value = iter.next();
305 test.ok(!value.done);
306 test.equal(value.value[0],
307 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(1) > DIV:nth-child(1)");
308
309 iter = selector.getElements("", document, document.sheet);
310 value = iter.next();
311 test.ok(!value.done);
312 test.equal(value.value.id, "middle1");
313 value = iter.next();
314 test.ok(!value.done);
315 test.equal(value.value.id, "sibling21");
316 value = iter.next();
317 test.ok(value.done);
318
319 selector = new HasSelector(":-abp-has(> div.inside)");
320
321 test.ok(selector._innerSelectors);
322 }).catch(unexpectedError.bind(test)).then(() => test.done());
323 };
324
325 exports.testContainsSelector = function(test)
326 {
327 let {toHide} = buildDom(document);
328
329 loadElemHideEmulation().then(() =>
330 {
331 let selector = new ContainsSelector("to hide");
332
333 let iter = selector.getSelectors("", document, document.sheet);
334 let value = iter.next();
335 test.ok(!value.done);
336 test.equal(value.value[0],
337 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(2) > DIV:nth-child(1)");
338
339 iter = selector.getElements("", document, document.sheet);
340 value = iter.next();
341 test.ok(!value.done);
342 test.equal(value.value, toHide);
343 value = iter.next();
344 test.ok(value.done);
345 }).catch(unexpectedError.bind(test)).then(() => test.done());
346 };
347
348 exports.testSplitStyleRule = function(test)
349 {
350 loadElemHideEmulation().then(() =>
351 {
352 let selectors = splitSelector("div:-abp-has(div) > [-abp-properties='backgro und-color: rgb(0, 0, 0)'] > span");
353 test.ok(selectors);
354 test.equal(selectors.length, 1, "There is only one selector");
355
356 selectors = splitSelector("div:-abp-has(div), [-abp-properties='background-c olor: rgb(0, 0, 0)']");
357 test.ok(selectors);
358 test.equal(selectors.length, 2, "There are two selectors");
359 }).catch(unexpectedError.bind(test)).then(() => test.done());
360 };
361 143
362 exports.testVerbatimPropertySelector = function(test) 144 exports.testVerbatimPropertySelector = function(test)
363 { 145 {
364 let toHide = createElementWithStyle("{background-color: #000}"); 146 let toHide = createElementWithStyle("{background-color: #000}");
365 applyElemHideEmulation( 147 applyElemHideEmulation(
366 [":-abp-properties(background-color: rgb(0, 0, 0))"] 148 [":-abp-properties(background-color: rgb(0, 0, 0))"]
367 ).then(() => 149 ).then(() =>
368 { 150 {
369 expectHidden(test, toHide); 151 expectHidden(test, toHide);
370 }).catch(unexpectedError.bind(test)).then(() => test.done()); 152 }).catch(unexpectedError.bind(test)).then(() => test.done());
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) 385 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test)
604 { 386 {
605 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(div.inside)) + div > div"); 387 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(div.inside)) + div > div");
606 }; 388 };
607 389
608 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test) 390 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test)
609 { 391 {
610 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(> div.inside)) + div > div"); 392 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(> div.inside)) + div > div");
611 }; 393 };
612 394
395 exports.testPseudoClassContains = function(test)
396 {
397 document.body.innerHTML = `<div id="parent">
398 <div id="middle">
399 <div id="middle1"><div id="inside" class="inside"></div></div>
400 </div>
401 <div id="sibling">
402 <div id="tohide">to hide</div>
403 </div>
404 <div id="sibling2">
405 <div id="sibling21"><div id="sibling211" class="inside"></div></div>
406 </div>
407 </div>`;
408 let parent = document.getElementById("parent");
409 let middle = document.getElementById("middle");
410 let inside = document.getElementById("inside");
411 let sibling = document.getElementById("sibling");
412 let sibling2 = document.getElementById("sibling2");
413 let toHide = document.getElementById("tohide");
414
415 applyElemHideEmulation(
416 ["#parent div:-abp-contains(to hide)"]
417 ).then(() =>
418 {
419 expectVisible(test, parent);
420 expectVisible(test, middle);
421 expectVisible(test, inside);
422 expectHidden(test, sibling);
423 expectVisible(test, sibling2);
424 expectHidden(test, toHide);
425 }).catch(unexpectedError.bind(test)).then(() => test.done());
426 };
427
613 exports.testPseudoClassHasSelectorWithPropSelector = function(test) 428 exports.testPseudoClassHasSelectorWithPropSelector = function(test)
614 { 429 {
615 let parent = createElementWithStyle("{}"); 430 let parent = createElementWithStyle("{}");
616 let child = createElementWithStyle("{background-color: #000}", parent); 431 let child = createElementWithStyle("{background-color: #000}", parent);
617 applyElemHideEmulation( 432 applyElemHideEmulation(
618 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] 433 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]
619 ).then(() => 434 ).then(() =>
620 { 435 {
621 expectVisible(test, child); 436 expectVisible(test, child);
622 expectHidden(test, parent); 437 expectHidden(test, parent);
623 }).catch(unexpectedError.bind(test)).then(() => test.done()); 438 }).catch(unexpectedError.bind(test)).then(() => test.done());
624 }; 439 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld