Index: test/browser/elemHideEmulation.js |
=================================================================== |
--- a/test/browser/elemHideEmulation.js |
+++ b/test/browser/elemHideEmulation.js |
@@ -12,25 +12,31 @@ |
* 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"; |
-/* globals ElemHideEmulation */ |
+/* globals ElemHideEmulation, pseudoClassHasSelectorRegExp, splitSelector, |
+ parsePattern, PseudoHasMatcher */ |
let myUrl = document.currentScript.src; |
exports.tearDown = function(callback) |
{ |
let styleElements = document.head.getElementsByTagName("style"); |
while (styleElements.length) |
styleElements[0].parentNode.removeChild(styleElements[0]); |
+ |
+ let child; |
+ while (child = document.body.firstChild) |
+ document.body.removeChild(child); |
+ |
callback(); |
}; |
function unexpectedError(error) |
{ |
console.error(error); |
this.ok(false, "Unexpected error: " + error); |
} |
@@ -64,70 +70,244 @@ |
else |
{ |
styleElement = document.createElement("style"); |
document.head.appendChild(styleElement); |
} |
styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
} |
-function createElementWithStyle(styleBlock) |
+// insert a <div> with a unique id and and empty CSS rule |
+// for the the selector matching the id. |
+function createElementWithStyle(styleBlock, parent) |
{ |
let element = document.createElement("div"); |
element.id = findUniqueId(); |
- document.body.appendChild(element); |
+ if (!parent) |
+ document.body.appendChild(element); |
+ else |
+ parent.appendChild(element); |
insertStyleRule("#" + element.id + " " + styleBlock); |
return element; |
} |
-function applyElemHideEmulation(selectors) |
+// Will ensure the class ElemHideEmulation is loaded |
+// and then will call the callback. |
+// NOTE: if it never loads, this will probably hang in an infinite |
+// loop |
+function loadElemHideEmulation() |
{ |
if (typeof ElemHideEmulation == "undefined") |
{ |
return loadScript(myUrl + "/../../../lib/common.js").then(() => |
{ |
return loadScript(myUrl + "/../../../chrome/content/elemHideEmulation.js"); |
}).then(() => |
{ |
- return applyElemHideEmulation(selectors); |
+ return loadElemHideEmulation(); |
}); |
} |
- let elemHideEmulation = new ElemHideEmulation( |
- window, |
- callback => |
- { |
- let patterns = []; |
- selectors.forEach(selector => |
+ return Promise.resolve(); |
+} |
+ |
+// instantiate a ElemHideEmulation with @selectors. |
+function applyElemHideEmulation(selectors) |
+{ |
+ return loadElemHideEmulation().then(() => |
+ { |
+ let elemHideEmulation = new ElemHideEmulation( |
+ window, |
+ callback => |
+ { |
+ let patterns = []; |
+ selectors.forEach(selector => |
+ { |
+ patterns.push({selector}); |
+ }); |
+ callback(patterns); |
+ }, |
+ newSelectors => |
+ { |
+ if (!newSelectors.length) |
+ return; |
+ let selector = newSelectors.join(", "); |
+ insertStyleRule(selector + "{display: none !important;}"); |
+ }, |
+ elements => |
{ |
- patterns.push({selector}); |
- }); |
- callback(patterns); |
- }, newSelectors => |
- { |
- if (!newSelectors.length) |
- return; |
- let selector = newSelectors.join(", "); |
- insertStyleRule(selector + "{display: none !important;}"); |
- } |
- ); |
+ if (!elements.length) |
+ return; |
+ for (let element of elements) |
+ element.style.display = "none"; |
+ } |
+ ); |
+ |
+ elemHideEmulation.apply(); |
+ return Promise.resolve(); |
+ }); |
+} |
+ |
+exports.testPseudoHasRule = function(test) |
+{ |
+ loadElemHideEmulation().then(() => |
+ { |
+ let selector = "div:-abp-has(span)"; |
+ // testing the regexp |
+ let match = pseudoClassHasSelectorRegExp.exec(selector); |
+ test.ok(match); |
+ test.equal(match[1], "span"); |
+ |
+ selector = ":-abp-has(div.inside)"; |
+ match = pseudoClassHasSelectorRegExp.exec(selector); |
+ test.ok(match); |
+ test.equal(match[1], "div.inside"); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testSplitStyleRule = function(test) |
+{ |
+ loadElemHideEmulation().then(() => |
+ { |
+ let selectors = splitSelector("div:-abp-has(div) > [-abp-properties='background-color: rgb(0, 0, 0)'] > span"); |
+ test.ok(selectors); |
+ test.equal(selectors.length, 1, "There is only one selector"); |
- elemHideEmulation.apply(); |
- return Promise.resolve(); |
+ selectors = splitSelector("div:-abp-has(div), [-abp-properties='background-color: rgb(0, 0, 0)']"); |
+ test.ok(selectors); |
+ test.equal(selectors.length, 2, "There are two selectors"); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testParsePattern = function(test) |
+{ |
+ loadElemHideEmulation().then(() => |
+ { |
+ let pattern = parsePattern({selector: "[-abp-properties='background-color: rgb(0, 0, 0)']"}); |
+ test.ok(pattern); |
+ test.equal(pattern.type, "props"); |
+ pattern = parsePattern({selector: "[-abp-properties='background-color: rgb(0, 0, 0)']"}); |
+ test.ok(pattern); |
+ test.equal(pattern.type, "props"); |
+ |
+ pattern = parsePattern({selector: ":-abp-has(div)"}); |
+ test.ok(pattern); |
+ test.equal(pattern.type, "has"); |
+ |
+ pattern = parsePattern({selector: ":-abp-properties('background-color: rgb(0, 0, 0)')"}); |
+ test.ok(pattern); |
+ test.equal(pattern.type, "props"); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+function runTestVerbatimPropertySelector(test, selector) |
+{ |
+ let toHide = createElementWithStyle("{background-color: #000}"); |
+ applyElemHideEmulation( |
+ [selector] |
+ ).then(() => |
+ { |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
} |
exports.testVerbatimPropertySelector = function(test) |
{ |
- let toHide = createElementWithStyle("{background-color: #000}"); |
+ runTestVerbatimPropertySelector(test, "[-abp-properties='background-color: rgb(0, 0, 0)']"); |
+}; |
+ |
+/* Testing the new syntax */ |
+exports.testVerbatimPropertyPseudoSelector = function(test) |
+{ |
+ runTestVerbatimPropertySelector(test, ":-abp-properties('background-color: rgb(0, 0, 0)')"); |
+}; |
+ |
+function runTestVerbatimPropertySelectorWithPrefix(test, selector) |
+{ |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #000}", parent); |
applyElemHideEmulation( |
- ["[-abp-properties='background-color: rgb(0, 0, 0)']"] |
+ [selector] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+} |
+ |
+exports.testVerbatimPropertySelectorWithPrefix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithPrefix(test, "div > [-abp-properties='background-color: rgb(0, 0, 0)']"); |
+}; |
+ |
+// testing the new syntax |
+exports.testVerbatimPropertyPseudoSelectorWithPrefix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithPrefix(test, "div > :-abp-properties('background-color: rgb(0, 0, 0)')"); |
+}; |
+ |
+exports.testVerbatimPropertySelectorWithPrefixNoMatch = function(test) |
+{ |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #fff}", parent); |
+ applyElemHideEmulation( |
+ ["div > [-abp-properties='background-color: rgb(0, 0, 0)']"] |
).then(() => |
{ |
+ expectVisible(test, parent); |
+ expectVisible(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+function runTestVerbatimPropertySelectorWithSuffix(test, selector) |
+{ |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #000}", parent); |
+ applyElemHideEmulation( |
+ [selector] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
expectHidden(test, toHide); |
}).catch(unexpectedError.bind(test)).then(() => test.done()); |
+} |
+ |
+exports.testVerbatimPropertySelectorWithSuffix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithSuffix(test, "[-abp-properties='background-color: rgb(0, 0, 0)'] > div"); |
+}; |
+ |
+exports.testVerbatimPropertyPseudoSelectorWithSuffix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithSuffix(test, ":-abp-properties('background-color: rgb(0, 0, 0)') > div"); |
+}; |
+ |
+function runTestVerbatimPropertySelectorWithPrefixAndSuffix(test, selector) |
+{ |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let middle = createElementWithStyle("{background-color: #000}", parent); |
+ let toHide = createElementWithStyle("{background-color: #000}", middle); |
+ applyElemHideEmulation( |
+ [selector] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+} |
+ |
+exports.testVerbatimPropertySelectorWithPrefixAndSuffix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithPrefixAndSuffix(test, "div > [-abp-properties='background-color: rgb(0, 0, 0)'] > div"); |
+}; |
+ |
+exports.testVerbatimPropertyPseudoSelectorWithPrefixAndSuffix = function(test) |
+{ |
+ runTestVerbatimPropertySelectorWithPrefixAndSuffix(test, "div > :-abp-properties('background-color: rgb(0, 0, 0)') > div"); |
}; |
exports.testPropertySelectorWithWildcard = function(test) |
{ |
let toHide = createElementWithStyle("{background-color: #000}"); |
applyElemHideEmulation( |
["[-abp-properties='*color: rgb(0, 0, 0)']"] |
).then(() => |
@@ -183,8 +363,157 @@ |
window.setTimeout(() => |
{ |
expectHidden(test, toHide); |
resolve(); |
}, 0); |
}); |
}).catch(unexpectedError.bind(test)).then(() => test.done()); |
}; |
+ |
+exports.testPseudoClassHasMatcher = function(test) |
+{ |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ loadElemHideEmulation().then(() => |
+ { |
+ let matcher = new PseudoHasMatcher("div"); |
+ test.equal(matcher.match(parent), true, "Parent should contain what is expected"); |
+ test.equal(matcher.match(child), false, "Child shouldn't match"); |
+ |
+ let matcher2 = new PseudoHasMatcher("span"); |
+ test.equal(matcher2.match(parent), false, "Doesn't have a <span> child, shouldn't match"); |
+ test.equal(matcher2.match(child), false, "Child shouldn't match"); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasSelector = function(test) |
+{ |
+ let toHide = createElementWithStyle("{}"); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(div)"] |
+ ).then(() => |
+ { |
+ expectVisible(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithPrefix = function(test) |
+{ |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(div)"] |
+ ).then(() => |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffix = function(test) |
+{ |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let child = createElementWithStyle("{}", middle); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(div) > div"] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectHidden(test, middle); |
+ expectHidden(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffixSibling = function(test) |
+{ |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let toHide = createElementWithStyle("{}"); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(div) + div"] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffixSiblingChild = function(test) |
+{ |
+ // <div> |
+ // <div></div> |
+ // <div> |
+ // <div>to hide</div> |
+ // </div> |
+ // </div> |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let sibling = createElementWithStyle("{}"); |
+ let toHide = createElementWithStyle("{}", sibling); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(div) + div > div"] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectVisible(test, sibling); |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector) |
+{ |
+ document.body.innerHTML = `<div id="parent"> |
+ <div id="middle"> |
+ <div id="middle.1"><div id="inside" class="inside"></div></div> |
+ </div> |
+ <div id="sibling"> |
+ <div id="tohide">to hide</div> |
+ </div> |
+ <div id="sibling2"> |
+ <div id="sibling2.1"><div id="sibling2.1.1" class="inside"></div></div> |
+ </div> |
+ </div>`; |
+ let parent = document.getElementById("parent"); |
+ let middle = document.getElementById("middle"); |
+ let inside = document.getElementById("inside"); |
+ let sibling = document.getElementById("sibling"); |
+ let sibling2 = document.getElementById("sibling2"); |
+ let toHide = document.getElementById("tohide"); |
+ |
+ applyElemHideEmulation( |
+ [selector] |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectVisible(test, inside); |
+ expectVisible(test, sibling); |
+ expectVisible(test, sibling2); |
+ expectHidden(test, toHide); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+} |
+ |
+exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) |
+{ |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(:-abp-has(div.inside)) + div > div"); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test) |
+{ |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, "div:-abp-has(:-abp-has(> div.inside)) + div > div"); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithPropSelector = function(test) |
+{ |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{background-color: #000}", parent); |
+ applyElemHideEmulation( |
+ ["div:-abp-has(:-abp-properties(\"background-color: rgb(0, 0, 0)\"))"] |
+ ).then(() => |
+ { |
+ expectVisible(test, child); |
+ expectHidden(test, parent); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |