Index: test/browser/elemHideEmulation.js |
=================================================================== |
--- a/test/browser/elemHideEmulation.js |
+++ b/test/browser/elemHideEmulation.js |
@@ -94,26 +94,32 @@ |
else |
{ |
styleElement = testDocument.createElement("style"); |
testDocument.head.appendChild(styleElement); |
} |
styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
} |
-// Insert a <div> with a unique id and a CSS rule |
-// for the the selector matching the id. |
-function createElementWithStyle(styleBlock, parent) |
+function createElement(parent) |
{ |
let element = testDocument.createElement("div"); |
element.id = findUniqueId(); |
if (!parent) |
testDocument.body.appendChild(element); |
else |
parent.appendChild(element); |
+ return element; |
+} |
+ |
+// Insert a <div> with a unique id and a CSS rule |
+// for the the selector matching the id. |
+function createElementWithStyle(styleBlock, parent) |
+{ |
+ let element = createElement(parent); |
insertStyleRule("#" + element.id + " " + styleBlock); |
return element; |
} |
// Create a new ElemHideEmulation instance with @selectors. |
function applyElemHideEmulation(selectors) |
{ |
return Promise.resolve().then(() => |
@@ -130,17 +136,19 @@ |
{ |
for (let elem of elems) |
elem.style.display = "none"; |
} |
); |
elemHideEmulation.document = testDocument; |
elemHideEmulation.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2; |
- elemHideEmulation.apply(selectors.map(selector => ({selector}))); |
+ elemHideEmulation.apply(selectors.map( |
+ selector => ({selector, text: selector}) |
+ )); |
return elemHideEmulation; |
}); |
} |
exports.testVerbatimPropertySelector = function(test) |
{ |
let toHide = createElementWithStyle("{background-color: #000}"); |
applyElemHideEmulation( |
@@ -694,8 +702,185 @@ |
}).then(() => |
{ |
expectHidden(test, parent); |
expectVisible(test, child); |
expectHidden(test, sibling); |
expectVisible(test, child2); |
}).catch(unexpectedError.bind(test)).then(() => test.done()); |
}; |
+ |
+exports.testPseudoClassPropertiesOnStyleSheetLoad = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, child); |
+ |
+ // Load a style sheet that targets the parent element. This should run only |
+ // the "div:-abp-properties(background-color: rgb(0, 0, 0))" pattern. |
+ insertStyleRule("#" + parent.id + " {background-color: #000}"); |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPlainAttributeOnDomMutation = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, child); |
+ |
+ // Set the "data-hide-me" attribute on the child element. |
+ // |
+ // Note: Since the "div[data-hide-me]" pattern has already been processed |
+ // and the selector added to the document's style sheet, this will in fact |
+ // not do anything at our end, but the browser will just match the selector |
+ // and hide the element. |
+ child.setAttribute("data-hide-me", ""); |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectHidden(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassContainsOnDomMutation = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ child.innerText = "do nothing"; |
+ |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, child); |
+ |
+ // Set the child element's text to "hide me". This should run only the |
+ // "div:-abp-contains(hide me)" pattern. |
+ // |
+ // Note: We need to set Node.innerText here in order to trigger the |
+ // "characterData" DOM mutation on Chromium. If we set Node.textContent |
+ // instead, it triggers the "childList" DOM mutation instead. |
+ child.innerText = "hide me"; |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasOnDomMutation = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = null; |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div)"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ |
+ // Add the child element. This should run all the DOM-dependent patterns |
+ // ("div:-abp-contains(hide me)" and "div:-abp-has(> div)"). |
+ child = createElement(parent); |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasWithClassOnDomMutation = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, child); |
+ |
+ // Set the child element's class to "hideMe". This should run only the |
+ // "div:-abp-has(> div.hideMe)" pattern. |
+ child.className = "hideMe"; |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |
+ |
+exports.testPseudoClassHasWithPseudoClassContainsOnDomMutation = function(test) |
+{ |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ child.innerText = "do nothing"; |
+ |
+ applyElemHideEmulation( |
+ ["div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div:-abp-contains(hide me))"] |
+ ).then(() => timeout(REFRESH_INTERVAL) |
+ ).then(() => |
+ { |
+ expectVisible(test, parent); |
+ expectVisible(test, child); |
+ |
+ // Set the child element's text to "hide me". This should run only the |
+ // "div:-abp-contains(hide me)" and |
+ // "div:-abp-has(> div:-abp-contains(hide me))" patterns. |
+ child.innerText = "hide me"; |
+ |
+ return timeout(REFRESH_INTERVAL); |
+ }).then(() => |
+ { |
+ // Note: Even though it runs both the :-abp-contains() patterns, it only |
+ // hides the parent element because of revision d7d51d29aa34. |
+ expectHidden(test, parent); |
+ expectVisible(test, child); |
+ }).catch(unexpectedError.bind(test)).then(() => test.done()); |
+}; |