Index: test/browser/elemHideEmulation.js |
=================================================================== |
--- a/test/browser/elemHideEmulation.js |
+++ b/test/browser/elemHideEmulation.js |
@@ -43,16 +43,21 @@ exports.setUp = function(callback) |
callback(); |
}; |
exports.tearDown = function(callback) |
{ |
var styleElements = document.head.getElementsByTagName("style"); |
while (styleElements.length) |
styleElements[0].parentNode.removeChild(styleElements[0]); |
+ var child; |
+ while(child = document.body.firstChild) |
+ { |
+ document.body.removeChild(child); |
+ } |
callback(); |
}; |
function expectHidden(test, element) |
{ |
test.equal(window.getComputedStyle(element).display, "none", |
"The element's display property should be set to 'none'"); |
} |
@@ -80,77 +85,227 @@ function insertStyleRule(rule) |
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) |
{ |
var 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, callback) |
+// 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(callback) |
{ |
if (typeof ElemHideEmulation == "undefined") |
{ |
loadScript(myUrl + "/../../../lib/common.js", function() |
{ |
loadScript(myUrl + "/../../../chrome/content/elemHideEmulation.js", |
function() |
{ |
- applyElemHideEmulation(selectors, callback); |
+ loadElemHideEmulation(callback); |
}); |
}); |
return; |
} |
- var elemHideEmulation = new ElemHideEmulation( |
- window, |
- function(callback) |
- { |
- var patterns = []; |
- selectors.forEach(function(selector) |
- { |
- patterns.push({selector: selector}); |
- }); |
- callback(patterns); |
- }, |
- function(selectors) |
- { |
- if (!selectors.length) |
- return; |
- var selector = selectors.join(", "); |
- insertStyleRule(selector + "{display: none !important;}"); |
- } |
- ); |
- |
- elemHideEmulation.apply(); |
callback(); |
} |
+// instantiate a ElemHideEmulation with @selectors. |
+function applyElemHideEmulation(selectors, callback) |
+{ |
+ loadElemHideEmulation(function() |
+ { |
+ var elemHideEmulation = new ElemHideEmulation( |
+ window, |
+ function(callback) |
+ { |
+ var patterns = []; |
+ selectors.forEach(function(selector) |
+ { |
+ patterns.push({selector: selector}); |
+ }); |
+ callback(patterns); |
+ }, |
+ function(selectors) |
+ { |
+ if (!selectors.length) |
+ return; |
+ var selector = selectors.join(", "); |
+ insertStyleRule(selector + "{display: none !important;}"); |
+ }, |
+ function(elements) |
+ { |
+ if (!elements.length) |
+ return; |
+ for (var i = 0; i < elements.length; i++) |
+ elements[i].style.display = "none"; |
+ } |
+ ); |
+ |
+ elemHideEmulation.apply(); |
+ callback(); |
+ }.bind(this)); |
+} |
+ |
+exports.testPseudoHasRule = function(test) |
+{ |
+ loadElemHideEmulation(function() |
+ { |
+ var selectors = ["div:has(span)"]; |
+ // testing the regexp |
+ var match = pseudoClassHasSelectorRegExp.exec(selectors[0]); |
+ test.ok(match); |
+ test.equal(match[1], "span"); |
+ |
+ selectors = [":has(div.inside)"]; |
+ match = pseudoClassHasSelectorRegExp.exec(selectors[0]); |
+ test.ok(match); |
+ test.equal(match[1], "div.inside"); |
+ |
+ test.done(); |
+ }); |
+}; |
+ |
+exports.testExtraFirstSelector = function(test) |
+{ |
+ loadElemHideEmulation(function() |
+ { |
+ var myselector = "elem.class1.class2"; |
+ var shortSel = extractFirstSelector(myselector); |
+ |
+ test.equal(shortSel, myselector); |
+ |
+ myselector = "elem > elem2"; |
+ shortSel = extractFirstSelector(myselector); |
+ |
+ test.equal(shortSel, "elem"); |
+ |
+ myselector = "elem+elem2 > elem3"; |
+ shortSel = extractFirstSelector(myselector); |
+ |
+ test.equal(shortSel, "elem"); |
+ |
+ myselector = "elem~elem2 > elem3"; |
+ shortSel = extractFirstSelector(myselector); |
+ |
+ test.equal(shortSel, "elem"); |
+ |
+ test.done(); |
+ }); |
+}; |
+ |
+exports.testSplitStyleRule = function(test) |
+{ |
+ loadElemHideEmulation(function() |
+ { |
+ var selectors = splitSelector("div:has(div) > [-abp-properties='background-color: rgb(0, 0, 0)'] > span"); |
+ test.ok(selectors); |
+ test.equal(selectors.length, 1, "There is only one selector"); |
+ |
+ selectors = splitSelector("div:has(div), [-abp-properties='background-color: rgb(0, 0, 0)']"); |
+ test.ok(selectors); |
+ test.equal(selectors.length, 2, "There are two selectors"); |
+ |
+ test.done(); |
+ }); |
+}; |
+ |
exports.testVerbatimPropertySelector = function(test) |
{ |
var toHide = createElementWithStyle("{background-color: #000}"); |
applyElemHideEmulation( |
["[-abp-properties='background-color: rgb(0, 0, 0)']"], |
function() |
{ |
expectHidden(test, toHide); |
test.done(); |
} |
); |
}; |
+exports.testVerbatimPropertySelectorWithPrefix = function(test) |
+{ |
+ var parent = createElementWithStyle("{background-color: #000}"); |
+ var toHide = createElementWithStyle("{background-color: #000}", parent); |
+ applyElemHideEmulation( |
+ ["div > [-abp-properties='background-color: rgb(0, 0, 0)']"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testVerbatimPropertySelectorWithPrefixNoMatch = function(test) |
+{ |
+ var parent = createElementWithStyle("{background-color: #000}"); |
+ var toHide = createElementWithStyle("{background-color: #fff}", parent); |
+ applyElemHideEmulation( |
+ ["div > [-abp-properties='background-color: rgb(0, 0, 0)']"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testVerbatimPropertySelectorWithSuffix = function(test) |
+{ |
+ var parent = createElementWithStyle("{background-color: #000}"); |
+ var toHide = createElementWithStyle("{background-color: #000}", parent); |
+ applyElemHideEmulation( |
+ ["[-abp-properties='background-color: rgb(0, 0, 0)'] > div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testVerbatimPropertySelectorWithPrefixAndSuffix = function(test) |
+{ |
+ var parent = createElementWithStyle("{background-color: #000}"); |
+ var middle = createElementWithStyle("{background-color: #000}", parent); |
+ var toHide = createElementWithStyle("{background-color: #000}", middle); |
+ applyElemHideEmulation( |
+ ["div > [-abp-properties='background-color: rgb(0, 0, 0)'] > div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
exports.testPropertySelectorWithWildcard = function(test) |
{ |
var toHide = createElementWithStyle("{background-color: #000}"); |
applyElemHideEmulation( |
["[-abp-properties='*color: rgb(0, 0, 0)']"], |
function() |
{ |
expectHidden(test, toHide); |
@@ -210,8 +365,157 @@ exports.testDynamicallyChangedProperty = |
window.setTimeout(function() |
{ |
expectHidden(test, toHide); |
test.done(); |
}, 0); |
} |
); |
}; |
+ |
+exports.testPseudoClassHasMatcher = function(test) |
+{ |
+ var parent = createElementWithStyle("{}"); |
+ var child = createElementWithStyle("{}", parent); |
+ loadElemHideEmulation(function() |
+ { |
+ var matcher = new PseudoHasMatcher("div"); |
+ test.equal(matcher.match(parent).length, 1, "Parent should contain what is expected"); |
+ test.equal(matcher.match(child).length, 0, "Child shouldn't match"); |
+ |
+ var matcher2 = new PseudoHasMatcher("span"); |
+ test.equal(matcher2.match(parent), 0, "Doesn't have a <span> child, shouldn't mactch"); |
+ test.equal(matcher2.match(child), 0, "Child shouldn't match"); |
+ |
+ test.done(); |
+ }); |
+}; |
+ |
+exports.testPseudoClassHasSelector = function(test) |
+{ |
+ var toHide = createElementWithStyle("{}"); |
+ applyElemHideEmulation( |
+ ["div:has(div)"], |
+ function() |
+ { |
+ expectVisible(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithPrefix = function(test) |
+{ |
+ var parent = createElementWithStyle("{}"); |
+ var child = createElementWithStyle("{}", parent); |
+ applyElemHideEmulation( |
+ ["div:has(div)"], |
+ function() |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffix = function(test) |
+{ |
+ var parent = createElementWithStyle("{}"); |
+ var middle = createElementWithStyle("{}", parent); |
+ var child = createElementWithStyle("{}", middle); |
+ applyElemHideEmulation( |
+ ["div:has(div) > div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectHidden(test, child); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffixSibling = function(test) |
+{ |
+ var parent = createElementWithStyle("{}"); |
+ var middle = createElementWithStyle("{}", parent); |
+ var toHide = createElementWithStyle("{}", parent); |
+ applyElemHideEmulation( |
+ ["div:has(div) + div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithSuffixSibling = function(test) |
+{ |
+ // <div> |
+ // <div></div> |
+ // <div> |
+ // <div>to hide</div> |
+ // </div> |
+ // </div> |
+ var parent = createElementWithStyle("{}"); |
+ var middle = createElementWithStyle("{}", parent); |
+ var sibling = createElementWithStyle("{}", parent); |
+ var toHide = createElementWithStyle("{}", sibling); |
+ applyElemHideEmulation( |
+ ["div:has(div) + div > div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectVisible(test, sibling); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) |
+{ |
+ // <div> |
+ // <div><div class="inside"></div></div> |
+ // <div> |
+ // <div>to hide</div> |
+ // </div> |
+ // </div> |
+ var parent = createElementWithStyle("{}"); |
+ var middle = createElementWithStyle("{}", parent); |
+ var inside = createElementWithStyle("{}", middle); |
+ inside.className = "inside"; |
+ var sibling = createElementWithStyle("{}", parent); |
+ var toHide = createElementWithStyle("{}", sibling); |
+ applyElemHideEmulation( |
+ ["div:has(:has(div.inside)) + div > div"], |
+ function() |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, middle); |
+ expectVisible(test, inside); |
+ expectVisible(test, sibling); |
+ expectHidden(test, toHide); |
+ test.done(); |
+ } |
+ ); |
+}; |
+ |
+ |
+exports.testPseudoClassHasSelectorWithPropSelector = function(test) |
+{ |
+ var parent = createElementWithStyle("{}"); |
+ var child = createElementWithStyle("{background-color: #000}", parent); |
+ applyElemHideEmulation( |
+ ["div:has([-abp-properties='background-color: rgb(0, 0, 0)'])"], |
+ function() |
+ { |
+ expectVisible(test, child); |
+ expectHidden(test, parent); |
+ test.done(); |
+ } |
+ ); |
+}; |