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: Rebased on patch for issue 3143. Created June 1, 2017, 6:29 p.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("> div) > div");
156 test.equal(parsed.text, "> div");
157 test.equal(parsed.end, 5);
158
159 parsed = parseSelectorContent("\"> div\") > div");
160 test.equal(parsed.text, "\"> div\"");
161 test.equal(parsed.end, 7);
162 parsed = parseSelectorContent(" \"> div\" ) > div");
163 test.equal(parsed.text, " \"> div\" ");
164 test.equal(parsed.end, 9);
165
166 // parens not closed.
167 parsed = parseSelectorContent("> div > div");
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 {
177 let {selectors, hide} = parseSelector("");
178 test.equal(selectors.length, 0);
179 test.ok(!hide);
180 }
181
182 let selector = "div > :-abp-properties('background-color: rgb(0, 0, 0)')";
183 let parsed = parseSelector(selector);
184 test.equal(parsed.selectors.length, 2);
185 test.ok(!parsed.hide);
186 test.ok(parsed.selectors[0] instanceof PlainSelector);
187 test.ok(parsed.selectors[1] instanceof PropsSelector);
188
189 selector = "div > :-abp-has(> div.inside) > div";
190 parsed = parseSelector(selector);
191 test.equal(parsed.selectors.length, 3);
192 test.ok(parsed.hide);
193 test.ok(parsed.selectors[0] instanceof PlainSelector);
194 test.ok(parsed.selectors[1] instanceof HasSelector);
195 test.ok(parsed.selectors[2] instanceof PlainSelector);
196
197 selector = "div > div:-abp-has(> div.inside) > div";
198 parsed = parseSelector(selector);
199
200 test.equal(parsed.selectors.length, 3);
201 test.ok(parsed.hide);
202 test.ok(parsed.selectors[0] instanceof PlainSelector);
203 test.ok(parsed.selectors[1] instanceof HasSelector);
204 test.ok(parsed.selectors[2] instanceof PlainSelector);
205
206 selector = "div > :-abp-has(> div.inside) > :-abp-properties(background-colo r: rgb(0, 0, 0))";
207 parsed = parseSelector(selector);
208
209 test.equal(parsed.selectors.length, 4);
210 test.ok(parsed.hide);
211 test.ok(parsed.selectors[0] instanceof PlainSelector);
212 test.ok(parsed.selectors[1] instanceof HasSelector);
213 test.ok(parsed.selectors[2] instanceof PlainSelector);
214 test.ok(parsed.selectors[3] instanceof PropsSelector);
215
216 selector = "div > :-abp-has(> div.inside > :-abp-properties(background-color : rgb(0, 0, 0))";
217 parsed = parseSelector(selector);
218 test.equal(parsed.selectors, null);
219
220 selector = 'div[arial-label="Story"]:-abp-has(> div > div > span > span:-abp -contains("Suggested Post"))';
221 parsed = parseSelector(selector);
222 let {selectors} = parsed;
223 test.equal(selectors.length, 2);
224 test.ok(selectors[0] instanceof PlainSelector);
225 test.ok(selectors[1] instanceof HasSelector);
226
227 selectors = selectors[1]._innerSelectors;
228 test.equals(selectors.length, 2);
229 test.ok(selectors[0] instanceof PlainSelector);
230 test.ok(selectors[1] instanceof ContainsSelector);
231
232 // -abp-has-unsupported() is unknown. Ensure we fail parsing.
233 selector = 'div[arial-label="Story"]:-abp-has(> div > div > span > span:-abp -unsupported("Suggested Post"))';
234 parsed = parseSelector(selector);
235 test.equal(parsed.selectors, null);
236 }).catch(unexpectedError.bind(test)).then(() => test.done());
237 };
238
239 function buildDom(doc)
240 {
241 doc.body.innerHTML = `<div id="parent">
242 <div id="middle">
243 <div id="middle1"><div id="inside" class="inside"></div></div>
244 </div>
245 <div id="sibling">
246 <div id="tohide">to hide</div>
247 </div>
248 <div id="sibling2">
249 <div id="sibling21"><div id="sibling211" class="inside"></div></div>
250 </div>
251 </div>`;
252 let parent = document.getElementById("parent");
253 let middle = document.getElementById("middle");
254 let middle1 = document.getElementById("middle1");
255 let inside = document.getElementById("inside");
256 let sibling = document.getElementById("sibling");
257 let sibling2 = document.getElementById("sibling2");
258 let toHide = document.getElementById("tohide");
259 return {parent, middle, middle1, inside, sibling, sibling2, toHide};
260 }
261
262 exports.testPositionInParent = function(test)
263 {
264 let nodes = buildDom(document);
265
266 loadElemHideEmulation().then(() =>
267 {
268 test.equal(positionInParent(nodes.middle1), 1);
269 test.equal(positionInParent(nodes.inside), 1);
270 test.equal(positionInParent(nodes.sibling2), 3);
271 }).catch(unexpectedError.bind(test)).then(() => test.done());
272 };
273
274 exports.testMakeSelector = function(test)
275 {
276 let nodes = buildDom(document);
277
278 loadElemHideEmulation().then(() =>
279 {
280 test.equal(makeSelector(nodes.middle, ""),
281 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(1)" );
282 test.equal(makeSelector(nodes.toHide, ""),
283 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(2) > DIV:nth-child(1)");
284 }).catch(unexpectedError.bind(test)).then(() => test.done());
285 };
286
287 exports.testPlainSelector = function(test)
288 {
289 buildDom(document);
290
291 loadElemHideEmulation().then(() =>
292 {
293 let selector = new PlainSelector("div > div");
294
295 let iter = selector.getSelectors("foo > ");
296 let value = iter.next();
297 test.equal(value.value[0], "foo > div > div");
298 test.ok(iter.next().done);
299 }).catch(unexpectedError.bind(test)).then(() => test.done());
300 };
301
302 exports.testHasSelector = function(test)
303 {
304 buildDom(document);
305
306 loadElemHideEmulation().then(() =>
307 {
308 let selector = new HasSelector("> div.inside");
309
310 let iter = selector.getSelectors("", document, document.sheet);
311 let value = iter.next();
312 test.ok(!value.done);
313 test.equal(value.value[0],
314 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(1) > DIV:nth-child(1)");
315
316 iter = selector.getElements("", document, document.sheet);
317 value = iter.next();
318 test.ok(!value.done);
319 test.equal(value.value.id, "middle1");
320 value = iter.next();
321 test.ok(!value.done);
322 test.equal(value.value.id, "sibling21");
323 value = iter.next();
324 test.ok(value.done);
325
326 selector = new HasSelector(":-abp-has(> div.inside)");
327
328 test.ok(selector._innerSelectors);
329 }).catch(unexpectedError.bind(test)).then(() => test.done());
330 };
331
332 exports.testContainsSelector = function(test)
333 {
334 let {toHide} = buildDom(document);
335
336 loadElemHideEmulation().then(() =>
337 {
338 let selector = new ContainsSelector("to hide");
339
340 let iter = selector.getSelectors("", document, document.sheet);
341 let value = iter.next();
342 test.ok(!value.done);
343 test.equal(value.value[0],
344 ":root > BODY:nth-child(2) > DIV:nth-child(1) > DIV:nth-child(2) > DIV:nth-child(1)");
345
346 iter = selector.getElements("", document, document.sheet);
347 value = iter.next();
348 test.ok(!value.done);
349 test.equal(value.value, toHide);
350 value = iter.next();
351 test.ok(value.done);
352 }).catch(unexpectedError.bind(test)).then(() => test.done());
353 };
354
355 exports.testSplitStyleRule = function(test)
356 {
357 loadElemHideEmulation().then(() =>
358 {
359 let selectors = splitSelector("div:-abp-has(div) > [-abp-properties='backgro und-color: rgb(0, 0, 0)'] > span");
360 test.ok(selectors);
361 test.equal(selectors.length, 1, "There is only one selector");
362
363 selectors = splitSelector("div:-abp-has(div), [-abp-properties='background-c olor: rgb(0, 0, 0)']");
364 test.ok(selectors);
365 test.equal(selectors.length, 2, "There are two selectors");
366 }).catch(unexpectedError.bind(test)).then(() => test.done());
367 };
368 143
369 exports.testVerbatimPropertySelector = function(test) 144 exports.testVerbatimPropertySelector = function(test)
370 { 145 {
371 let toHide = createElementWithStyle("{background-color: #000}"); 146 let toHide = createElementWithStyle("{background-color: #000}");
372 applyElemHideEmulation( 147 applyElemHideEmulation(
373 [":-abp-properties(background-color: rgb(0, 0, 0))"] 148 [":-abp-properties(background-color: rgb(0, 0, 0))"]
374 ).then(() => 149 ).then(() =>
375 { 150 {
376 expectHidden(test, toHide); 151 expectHidden(test, toHide);
377 }).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
610 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) 385 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test)
611 { 386 {
612 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(div.inside)) + div > div"); 387 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(div.inside)) + div > div");
613 }; 388 };
614 389
615 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test) 390 exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test)
616 { 391 {
617 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(> div.inside)) + div > div"); 392 runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(: -abp-has(> div.inside)) + div > div");
618 }; 393 };
619 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
620 exports.testPseudoClassHasSelectorWithPropSelector = function(test) 428 exports.testPseudoClassHasSelectorWithPropSelector = function(test)
621 { 429 {
622 let parent = createElementWithStyle("{}"); 430 let parent = createElementWithStyle("{}");
623 let child = createElementWithStyle("{background-color: #000}", parent); 431 let child = createElementWithStyle("{background-color: #000}", parent);
624 applyElemHideEmulation( 432 applyElemHideEmulation(
625 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"] 433 ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]
626 ).then(() => 434 ).then(() =>
627 { 435 {
628 expectVisible(test, child); 436 expectVisible(test, child);
629 expectHidden(test, parent); 437 expectHidden(test, parent);
630 }).catch(unexpectedError.bind(test)).then(() => test.done()); 438 }).catch(unexpectedError.bind(test)).then(() => test.done());
631 }; 439 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld