| Index: test/browser/elemHideEmulation.js | 
| =================================================================== | 
| --- a/test/browser/elemHideEmulation.js | 
| +++ b/test/browser/elemHideEmulation.js | 
| @@ -80,77 +80,187 @@ 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;}"); | 
| +      } | 
| +    ); | 
| + | 
| +    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"); | 
| + | 
| +    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 +320,54 @@ exports.testDynamicallyChangedProperty = | 
| window.setTimeout(function() | 
| { | 
| expectHidden(test, toHide); | 
| test.done(); | 
| }, 0); | 
| } | 
| ); | 
| }; | 
| + | 
| +exports.testPseudoClassHasMatcher = function(test) | 
| +{ | 
| +  var parent = createElementWithStyle("{}"); | 
| +  var toHide = createElementWithStyle("{}", parent); | 
| +  loadElemHideEmulation(function() | 
| +  { | 
| +    var matcher = new PseudoHasMatcher("div"); | 
| +    test.equal(matcher.match(parent).length, 1); | 
| +    test.equal(matcher.match(toHide).length, 0); | 
| + | 
| +    var matcher2 = new PseudoHasMatcher("span"); | 
| +    test.equal(matcher2.match(parent), 0); | 
| +    test.equal(matcher2.match(toHide), 0); | 
| + | 
| +    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 toHide = createElementWithStyle("{}", parent); | 
| +  applyElemHideEmulation( | 
| +    ["div:has(div)"], | 
| +    function() | 
| +    { | 
| +      expectVisible(test, parent); | 
| +      expectHidden(test, toHide); | 
| +      test.done(); | 
| +    } | 
| +  ); | 
| +}; | 
|  |