Index: test/browser/elemHideEmulation.js |
=================================================================== |
--- a/test/browser/elemHideEmulation.js |
+++ b/test/browser/elemHideEmulation.js |
@@ -10,1123 +10,1089 @@ |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
* 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/>. |
*/ |
+/* global assert */ |
+ |
"use strict"; |
const {ElemHideEmulation, setTestMode, |
getTestInfo} = require("../../lib/content/elemHideEmulation"); |
const {timeout} = require("./_utils"); |
-const REFRESH_INTERVAL = 200; |
- |
-let testDocument = null; |
- |
-exports.setUp = function(callback) |
-{ |
- setTestMode(); |
- |
- let iframe = document.createElement("iframe"); |
- document.body.appendChild(iframe); |
- testDocument = iframe.contentDocument; |
- |
- callback(); |
-}; |
- |
-exports.tearDown = function(callback) |
-{ |
- let iframe = testDocument.defaultView.frameElement; |
- iframe.parentNode.removeChild(iframe); |
- testDocument = null; |
- |
- callback(); |
-}; |
- |
-function unexpectedError(test, error) |
-{ |
- console.error(error); |
- test.ok(false, "Unexpected error: " + error); |
-} |
- |
-function expectHidden(test, element, id) |
-{ |
- let withId = ""; |
- if (typeof id != "undefined") |
- withId = ` with ID '${id}'`; |
- |
- test.equal( |
- window.getComputedStyle(element).display, "none", |
- `The element${withId}'s display property should be set to 'none'`); |
-} |
- |
-function expectVisible(test, element, id) |
-{ |
- let withId = ""; |
- if (typeof id != "undefined") |
- withId = ` with ID '${id}'`; |
- |
- test.notEqual( |
- window.getComputedStyle(element).display, "none", |
- `The element${withId}'s display property should not be set to 'none'`); |
-} |
- |
-function expectProcessed(test, element, id = null) |
-{ |
- let withId = ""; |
- if (id) |
- withId = ` with ID '${id}'`; |
- |
- test.ok( |
- getTestInfo().lastProcessedElements.has(element), |
- `The element${withId} should have been processed`); |
-} |
- |
-function expectNotProcessed(test, element, id = null) |
-{ |
- let withId = ""; |
- if (id) |
- withId = ` with ID '${id}'`; |
- |
- test.ok( |
- !getTestInfo().lastProcessedElements.has(element), |
- `The element${withId} should not have been processed`); |
-} |
- |
-function findUniqueId() |
-{ |
- let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); |
- if (!testDocument.getElementById(id)) |
- return id; |
- return findUniqueId(); |
-} |
- |
-function insertStyleRule(rule) |
+describe("Element Hiding Emulation", () => |
{ |
- let styleElement; |
- let styleElements = testDocument.head.getElementsByTagName("style"); |
- if (styleElements.length) |
- styleElement = styleElements[0]; |
- else |
- { |
- styleElement = testDocument.createElement("style"); |
- testDocument.head.appendChild(styleElement); |
- } |
- styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
-} |
+ const REFRESH_INTERVAL = 200; |
-function createElement(parent, type = "div", id = findUniqueId(), |
- innerText = null) |
-{ |
- let element = testDocument.createElement(type); |
- element.id = id; |
- if (!parent) |
- testDocument.body.appendChild(element); |
- else |
- parent.appendChild(element); |
- if (innerText) |
- element.innerText = innerText; |
- return element; |
-} |
+ let testDocument = null; |
-// 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. |
-async function applyElemHideEmulation(test, selectors) |
-{ |
- await Promise.resolve(); |
- |
- try |
+ beforeEach(() => |
{ |
- let elemHideEmulation = new ElemHideEmulation( |
- elems => |
- { |
- for (let elem of elems) |
- elem.style.display = "none"; |
- } |
- ); |
+ setTestMode(); |
- elemHideEmulation.document = testDocument; |
- elemHideEmulation.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2; |
- elemHideEmulation.apply(selectors.map( |
- selector => ({selector, text: selector}) |
- )); |
- |
- return elemHideEmulation; |
- } |
- catch (error) |
- { |
- unexpectedError(test, error); |
- } |
-} |
+ let iframe = document.createElement("iframe"); |
+ document.body.appendChild(iframe); |
+ testDocument = iframe.contentDocument; |
+ }); |
-exports.testVerbatimPropertySelector = async function(test) |
-{ |
- let toHide = createElementWithStyle("{background-color: #000}"); |
- let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- expectHidden(test, toHide); |
- |
- test.done(); |
-}; |
+ afterEach(() => |
+ { |
+ let iframe = testDocument.defaultView.frameElement; |
+ iframe.parentNode.removeChild(iframe); |
+ testDocument = null; |
+ }); |
-exports.testVerbatimPropertySelectorWithPrefix = async function(test) |
-{ |
- let parent = createElementWithStyle("{background-color: #000}"); |
- let toHide = createElementWithStyle("{background-color: #000}", parent); |
- |
- let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ function unexpectedError(error) |
{ |
- expectVisible(test, parent); |
- expectHidden(test, toHide); |
+ console.error(error); |
+ assert.ok(false, "Unexpected error: " + error); |
} |
- test.done(); |
-}; |
+ function expectHidden(element, id) |
+ { |
+ let withId = ""; |
+ if (typeof id != "undefined") |
+ withId = ` with ID '${id}'`; |
+ |
+ assert.equal( |
+ window.getComputedStyle(element).display, "none", |
+ `The element${withId}'s display property should be set to 'none'`); |
+ } |
+ |
+ function expectVisible(element, id) |
+ { |
+ let withId = ""; |
+ if (typeof id != "undefined") |
+ withId = ` with ID '${id}'`; |
-exports.testVerbatimPropertySelectorWithPrefixNoMatch = async function(test) |
-{ |
- let parent = createElementWithStyle("{background-color: #000}"); |
- let toHide = createElementWithStyle("{background-color: #fff}", parent); |
+ assert.notEqual( |
+ window.getComputedStyle(element).display, "none", |
+ `The element${withId}'s display property should not be set to 'none'`); |
+ } |
+ |
+ function expectProcessed(element, id = null) |
+ { |
+ let withId = ""; |
+ if (id) |
+ withId = ` with ID '${id}'`; |
- let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; |
+ assert.ok( |
+ getTestInfo().lastProcessedElements.has(element), |
+ `The element${withId} should have been processed`); |
+ } |
- if (await applyElemHideEmulation(test, selectors)) |
+ function expectNotProcessed(element, id = null) |
{ |
- expectVisible(test, parent); |
- expectVisible(test, toHide); |
+ let withId = ""; |
+ if (id) |
+ withId = ` with ID '${id}'`; |
+ |
+ assert.ok( |
+ !getTestInfo().lastProcessedElements.has(element), |
+ `The element${withId} should not have been processed`); |
} |
- test.done(); |
-}; |
- |
-exports.testVerbatimPropertySelectorWithSuffix = async function(test) |
-{ |
- let parent = createElementWithStyle("{background-color: #000}"); |
- let toHide = createElementWithStyle("{background-color: #000}", parent); |
- |
- let selectors = [":-abp-properties(background-color: rgb(0, 0, 0)) > div"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ function findUniqueId() |
{ |
- expectVisible(test, parent); |
- expectHidden(test, toHide); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testVerbatimPropertyPseudoSelectorWithPrefixAndSuffix = async function(test) |
-{ |
- let parent = createElementWithStyle("{background-color: #000}"); |
- let middle = createElementWithStyle("{background-color: #000}", parent); |
- let toHide = createElementWithStyle("{background-color: #000}", middle); |
- |
- let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0)) > div"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- expectVisible(test, parent); |
- expectVisible(test, middle); |
- expectHidden(test, toHide); |
+ let id = "elemHideEmulationTest-" + Math.floor(Math.random() * 10000); |
+ if (!testDocument.getElementById(id)) |
+ return id; |
+ return findUniqueId(); |
} |
- test.done(); |
-}; |
- |
-// Add the style. Then add the element for that style. |
-// This should retrigger the filtering and hide it. |
-exports.testPropertyPseudoSelectorAddStyleAndElement = async function(test) |
-{ |
- let styleElement; |
- let toHide; |
- |
- let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ function insertStyleRule(rule) |
{ |
- styleElement = testDocument.createElement("style"); |
- testDocument.head.appendChild(styleElement); |
- styleElement.sheet.insertRule("#toHide {background-color: #000}"); |
- await timeout(REFRESH_INTERVAL); |
- |
- toHide = createElement(); |
- toHide.id = "toHide"; |
- expectVisible(test, toHide); |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, toHide); |
+ let styleElement; |
+ let styleElements = testDocument.head.getElementsByTagName("style"); |
+ if (styleElements.length) |
+ styleElement = styleElements[0]; |
+ else |
+ { |
+ styleElement = testDocument.createElement("style"); |
+ testDocument.head.appendChild(styleElement); |
+ } |
+ styleElement.sheet.insertRule(rule, styleElement.sheet.cssRules.length); |
} |
- test.done(); |
-}; |
- |
-exports.testPropertySelectorWithWildcard = async function(test) |
-{ |
- let toHide = createElementWithStyle("{background-color: #000}"); |
- let selectors = [":-abp-properties(*color: rgb(0, 0, 0))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- expectHidden(test, toHide); |
- |
- test.done(); |
-}; |
- |
-exports.testPropertySelectorWithRegularExpression = async function(test) |
-{ |
- let toHide = createElementWithStyle("{background-color: #000}"); |
- let selectors = [":-abp-properties(/.*color: rgb\\(0, 0, 0\\)/)"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- expectHidden(test, toHide); |
- |
- test.done(); |
-}; |
- |
-exports.testDynamicallyChangedProperty = async function(test) |
-{ |
- let toHide = createElementWithStyle("{}"); |
- let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ function createElement(parent, type = "div", id = findUniqueId(), |
+ innerText = null) |
{ |
- expectVisible(test, toHide); |
- insertStyleRule("#" + toHide.id + " {background-color: #000}"); |
- |
- await timeout(0); |
- |
- // Re-evaluation will only happen after a delay |
- expectVisible(test, toHide); |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, toHide); |
+ let element = testDocument.createElement(type); |
+ element.id = id; |
+ if (!parent) |
+ testDocument.body.appendChild(element); |
+ else |
+ parent.appendChild(element); |
+ if (innerText) |
+ element.innerText = innerText; |
+ return element; |
} |
- test.done(); |
-}; |
- |
-exports.testPseudoClassWithPropBeforeSelector = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{background-color: #000}", parent); |
- |
- let selectors = ["div:-abp-properties(content: \"publicite\")"]; |
- |
- insertStyleRule(`#${child.id}::before {content: "publicite"}`); |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ // Insert a <div> with a unique id and a CSS rule |
+ // for the the selector matching the id. |
+ function createElementWithStyle(styleBlock, parent) |
{ |
- expectHidden(test, child); |
- expectVisible(test, parent); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testPseudoClassHasSelector = async function(test) |
-{ |
- let toHide = createElementWithStyle("{}"); |
- |
- if (await applyElemHideEmulation(test, ["div:-abp-has(div)"])) |
- expectVisible(test, toHide); |
- |
- test.done(); |
-}; |
- |
-exports.testPseudoClassHasSelectorWithPrefix = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{}", parent); |
- |
- if (await applyElemHideEmulation(test, ["div:-abp-has(div)"])) |
- { |
- expectHidden(test, parent); |
- expectVisible(test, child); |
+ let element = createElement(parent); |
+ insertStyleRule("#" + element.id + " " + styleBlock); |
+ return element; |
} |
- test.done(); |
-}; |
- |
-exports.testPseudoClassHasSelectorWithSuffix = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let middle = createElementWithStyle("{}", parent); |
- let child = createElementWithStyle("{}", middle); |
- |
- if (await applyElemHideEmulation(test, ["div:-abp-has(div) > div"])) |
+ // Create a new ElemHideEmulation instance with @selectors. |
+ async function applyElemHideEmulation(selectors) |
{ |
- expectVisible(test, parent); |
- expectHidden(test, middle); |
- expectHidden(test, child); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testPseudoClassHasSelectorWithSuffixSibling = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let middle = createElementWithStyle("{}", parent); |
- let toHide = createElementWithStyle("{}"); |
- |
- if (await applyElemHideEmulation(test, ["div:-abp-has(div) + div"])) |
- { |
- expectVisible(test, parent); |
- expectVisible(test, middle); |
- expectHidden(test, toHide); |
- } |
- |
- test.done(); |
-}; |
+ await Promise.resolve(); |
-exports.testPseudoClassHasSelectorWithSuffixSiblingChild = async 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); |
+ try |
+ { |
+ let elemHideEmulation = new ElemHideEmulation( |
+ elems => |
+ { |
+ for (let elem of elems) |
+ elem.style.display = "none"; |
+ } |
+ ); |
- if (await applyElemHideEmulation(test, ["div:-abp-has(div) + div > div"])) |
- { |
- expectVisible(test, parent); |
- expectVisible(test, middle); |
- expectVisible(test, sibling); |
- expectHidden(test, toHide); |
- } |
- |
- test.done(); |
-}; |
+ elemHideEmulation.document = testDocument; |
+ elemHideEmulation.MIN_INVOCATION_INTERVAL = REFRESH_INTERVAL / 2; |
+ elemHideEmulation.apply(selectors.map( |
+ selector => ({selector, text: selector}) |
+ )); |
-function compareExpectations(test, elems, expectations) |
-{ |
- for (let elem in expectations) |
- { |
- if (elems[elem]) |
+ return elemHideEmulation; |
+ } |
+ catch (error) |
{ |
- if (expectations[elem]) |
- expectVisible(test, elems[elem], elem); |
- else |
- expectHidden(test, elems[elem], elem); |
+ unexpectedError(error); |
} |
} |
-} |
-async function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(test, selector, expectations) |
-{ |
- testDocument.body.innerHTML = `<div id="parent"> |
- <div id="middle"> |
- <div id="middle1"><div id="inside" class="inside"></div></div> |
- </div> |
- <div id="sibling"> |
- <div id="tohide"><span>to hide</span></div> |
- </div> |
- <div id="sibling2"> |
- <div id="sibling21"><div id="sibling211" class="inside"></div></div> |
- </div> |
- </div>`; |
- let elems = { |
- parent: testDocument.getElementById("parent"), |
- middle: testDocument.getElementById("middle"), |
- inside: testDocument.getElementById("inside"), |
- sibling: testDocument.getElementById("sibling"), |
- sibling2: testDocument.getElementById("sibling2"), |
- toHide: testDocument.getElementById("tohide") |
- }; |
- |
- insertStyleRule(".inside {}"); |
- |
- if (await applyElemHideEmulation(test, [selector])) |
- compareExpectations(test, elems, expectations); |
- |
- test.done(); |
-} |
+ describe("Verbatim Property Selector", () => |
+ { |
+ it("Regular", async() => |
+ { |
+ let toHide = createElementWithStyle("{background-color: #000}"); |
+ let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
-exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middile: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: false |
- }; |
- runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
- test, "div:-abp-has(:-abp-has(div.inside)) + div > div", expectations); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ expectHidden(toHide); |
+ }); |
-exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling2 = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middile: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: false |
- }; |
- runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
- test, "div:-abp-has(:-abp-has(> div.inside)) + div > div", expectations); |
-}; |
+ it("With Prefix", async() => |
+ { |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #000}", parent); |
-exports.testPseudoClassHasSelectorWithHasAndWithSuffixSibling3 = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middile: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: false |
- }; |
- runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
- test, "div:-abp-has(> div:-abp-has(div.inside)) + div > div", expectations); |
-}; |
+ let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; |
-exports.testPseudoClassHasSelectorWithSuffixSiblingNoop = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middile: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
- test, "div:-abp-has(> body div.inside) + div > div", expectations); |
-}; |
- |
-exports.testPseudoClassHasSelectorWithSuffixSiblingContains = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middile: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
- test, "div:-abp-has(> span:-abp-contains(Advertisment))", expectations); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(parent); |
+ expectHidden(toHide); |
+ } |
+ }); |
-async function runTestQualifier(test, selector) |
-{ |
- testDocument.body.innerHTML = ` |
- <style> |
- span::before { |
- content: "any"; |
- } |
- </style> |
- <div id="toHide"> |
- <a> |
- <p> |
- <span></span> |
- </p> |
- </a> |
- </div>`; |
+ it("With Prefix No Match", async() => |
+ { |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #fff}", parent); |
- if (await applyElemHideEmulation(test, [selector])) |
- expectHidden(test, testDocument.getElementById("toHide")); |
- |
- test.done(); |
-} |
+ let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0))"]; |
-// See issue https://issues.adblockplus.org/ticket/7428 |
-exports.testPropertySelectorCombinatorQualifier = function(test) |
-{ |
- runTestQualifier( |
- test, |
- "div:-abp-has(> a p > :-abp-properties(content: \"any\"))" |
- ); |
-}; |
- |
-// See issue https://issues.adblockplus.org/ticket/7359 |
-exports.testPropertySelectorCombinatorQualifierNested = function(test) |
-{ |
- runTestQualifier( |
- test, |
- "div:-abp-has(> a p:-abp-has(> :-abp-properties(content: \"any\")))" |
- ); |
-}; |
- |
-// See issue https://issues.adblockplus.org/ticket/7400 |
-exports.testPropertySelectorIdenticalTypeQualifier = function(test) |
-{ |
- runTestQualifier( |
- test, |
- "div:-abp-has(span:-abp-properties(content: \"any\"))" |
- ); |
-}; |
- |
-// See issue https://issues.adblockplus.org/ticket/7400 |
-exports.testPropertySelectorIdenticalTypeQualifierNested = function(test) |
-{ |
- runTestQualifier( |
- test, |
- "div:-abp-has(p:-abp-has(span:-abp-properties(content: \"any\")))" |
- ); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(parent); |
+ expectVisible(toHide); |
+ } |
+ }); |
-async function runTestPseudoClassContains(test, selector, expectations) |
-{ |
- testDocument.body.innerHTML = `<div id="parent"> |
- <div id="middle"> |
- <div id="middle1"><div id="inside" class="inside"></div></div> |
- </div> |
- <div id="sibling"> |
- <div id="tohide">to hide \ud83d\ude42!</div> |
- </div> |
- <div id="sibling2"> |
- <div id="sibling21"><div id="sibling211" class="inside">Ad*</div></div> |
- </div> |
- </div>`; |
- let elems = { |
- parent: testDocument.getElementById("parent"), |
- middle: testDocument.getElementById("middle"), |
- inside: testDocument.getElementById("inside"), |
- sibling: testDocument.getElementById("sibling"), |
- sibling2: testDocument.getElementById("sibling2"), |
- toHide: testDocument.getElementById("tohide") |
- }; |
+ it("With Suffix", async() => |
+ { |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let toHide = createElementWithStyle("{background-color: #000}", parent); |
- if (await applyElemHideEmulation(test, [selector])) |
- compareExpectations(test, elems, expectations); |
- |
- test.done(); |
-} |
+ let selectors = [":-abp-properties(background-color: rgb(0, 0, 0)) > div"]; |
-exports.testPseudoClassContainsText = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: false, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(to hide)", expectations); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(parent); |
+ expectHidden(toHide); |
+ } |
+ }); |
-exports.testPseudoClassContainsRegexp = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: false, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(/to\\shide/)", expectations); |
-}; |
- |
-exports.testPseudoClassContainsRegexpIFlag = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: false, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(/to\\sHide/i)", expectations); |
-}; |
-exports.testPseudoClassContainsRegexpUFlag = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: false, |
- sibling2: true, |
- toHide: true |
- }; |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(/to\\shide\\s.!/u)", expectations); |
-}; |
+ it("With prefix and suffix", async() => |
+ { |
+ let parent = createElementWithStyle("{background-color: #000}"); |
+ let middle = createElementWithStyle("{background-color: #000}", parent); |
+ let toHide = createElementWithStyle("{background-color: #000}", middle); |
-exports.testPseudoClassContainsWildcardNoMatch = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: true, |
- sibling2: true, |
- toHide: true |
- }; |
- // this filter shouldn't match anything as "*" has no meaning. |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(to *hide)", expectations); |
-}; |
- |
-exports.testPseudoClassContainsWildcardMatch = function(test) |
-{ |
- let expectations = { |
- parent: true, |
- middle: true, |
- inside: true, |
- sibling: true, |
- sibling2: false, |
- toHide: true |
- }; |
- runTestPseudoClassContains( |
- test, "#parent div:-abp-contains(Ad*)", expectations); |
-}; |
- |
-exports.testPseudoClassHasSelectorWithPropSelector = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{background-color: #000}", parent); |
+ let selectors = ["div > :-abp-properties(background-color: rgb(0, 0, 0)) > div"]; |
- let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- expectVisible(test, child); |
- expectHidden(test, parent); |
- } |
- |
- test.done(); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(parent); |
+ expectVisible(middle); |
+ expectHidden(toHide); |
+ } |
+ }); |
+ }); |
-exports.testPseudoClassHasSelectorWithPropSelector2 = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{}", parent); |
- |
- let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
- |
- insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ // Add the style. Then add the element for that style. |
+ // This should retrigger the filtering and hide it. |
+ it("Property Pseudo Selector Add Style and elemment", async() => |
{ |
- expectVisible(test, child); |
- expectHidden(test, parent); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testDomUpdatesStyle = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{}", parent); |
+ let styleElement; |
+ let toHide; |
- let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- expectVisible(test, child); |
- expectVisible(test, parent); |
- |
- insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); |
- await timeout(0); |
- |
- expectVisible(test, child); |
- expectVisible(test, parent); |
- await timeout(REFRESH_INTERVAL); |
+ let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
- expectVisible(test, child); |
- expectHidden(test, parent); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testDomUpdatesContent = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{}", parent); |
- |
- if (await applyElemHideEmulation(test, ["div > div:-abp-contains(hide me)"])) |
- { |
- expectVisible(test, parent); |
- expectVisible(test, child); |
- |
- child.textContent = "hide me"; |
- await timeout(0); |
- |
- expectVisible(test, parent); |
- expectVisible(test, child); |
- await timeout(REFRESH_INTERVAL); |
- |
- expectVisible(test, parent); |
- expectHidden(test, child); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testDomUpdatesNewElement = async function(test) |
-{ |
- let parent = createElementWithStyle("{}"); |
- let child = createElementWithStyle("{ background-color: #000}", parent); |
- let sibling; |
- let child2; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ styleElement = testDocument.createElement("style"); |
+ testDocument.head.appendChild(styleElement); |
+ styleElement.sheet.insertRule("#toHide {background-color: #000}"); |
+ await timeout(REFRESH_INTERVAL); |
- let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- |
- sibling = createElementWithStyle("{}"); |
- await timeout(0); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- expectVisible(test, sibling); |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- expectVisible(test, sibling); |
+ toHide = createElement(); |
+ toHide.id = "toHide"; |
+ expectVisible(toHide); |
+ await timeout(REFRESH_INTERVAL); |
- child2 = createElementWithStyle("{ background-color: #000}", |
- sibling); |
- await timeout(0); |
- |
- expectVisible(test, child2); |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- expectHidden(test, sibling); |
- expectVisible(test, child2); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testPseudoClassPropertiesOnStyleSheetLoad = async function(test) |
-{ |
- let parent = createElement(); |
- let child = createElement(parent); |
+ expectHidden(toHide); |
+ } |
+ }); |
- let selectors = [ |
- "div:-abp-properties(background-color: rgb(0, 0, 0))", |
- "div:-abp-contains(hide me)", |
- "div:-abp-has(> div.hideMe)" |
- ]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- await timeout(REFRESH_INTERVAL); |
- |
- 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}"); |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testPlainAttributeOnDomMutation = async function(test) |
-{ |
- let parent = createElement(); |
- let child = createElement(parent); |
- |
- let selectors = [ |
- "div:-abp-properties(background-color: rgb(0, 0, 0))", |
- "div[data-hide-me]", |
- "div:-abp-contains(hide me)", |
- "div:-abp-has(> div.hideMe)" |
- ]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ describe("Property Selector", () => |
{ |
- await timeout(REFRESH_INTERVAL); |
- |
- expectVisible(test, parent); |
- expectVisible(test, child); |
+ it("With Wildcard", async() => |
+ { |
+ let toHide = createElementWithStyle("{background-color: #000}"); |
+ let selectors = [":-abp-properties(*color: rgb(0, 0, 0))"]; |
- // 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", ""); |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- expectVisible(test, parent); |
- expectHidden(test, child); |
- } |
+ if (await applyElemHideEmulation(selectors)) |
+ expectHidden(toHide); |
+ }); |
- test.done(); |
-}; |
- |
-exports.testPseudoClassContainsOnDomMutation = async function(test) |
-{ |
- let parent = createElement(); |
- let child = createElement(parent); |
+ it("With regular expression", async() => |
+ { |
+ let toHide = createElementWithStyle("{background-color: #000}"); |
+ let selectors = [":-abp-properties(/.*color: rgb\\(0, 0, 0\\)/)"]; |
- let selectors = [ |
- "div:-abp-properties(background-color: rgb(0, 0, 0))", |
- "div[data-hide-me]", |
- "div:-abp-contains(hide me)", |
- "div:-abp-has(> div.hideMe)" |
- ]; |
+ if (await applyElemHideEmulation(selectors)) |
+ expectHidden(toHide); |
+ }); |
+ }); |
- child.innerText = "do nothing"; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ it("Dynamically Changed Property", async() => |
{ |
- await timeout(REFRESH_INTERVAL); |
- |
- expectVisible(test, parent); |
- expectVisible(test, child); |
+ let toHide = createElementWithStyle("{}"); |
+ let selectors = [":-abp-properties(background-color: rgb(0, 0, 0))"]; |
- // 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"; |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- } |
- |
- test.done(); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(toHide); |
+ insertStyleRule("#" + toHide.id + " {background-color: #000}"); |
-exports.testPseudoClassHasOnDomMutation = async function(test) |
-{ |
- let parent = createElement(); |
- let child = null; |
- |
- let selectors = [ |
- "div:-abp-properties(background-color: rgb(0, 0, 0))", |
- "div[data-hide-me]", |
- "div:-abp-contains(hide me)", |
- "div:-abp-has(> div)" |
- ]; |
+ await timeout(0); |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- await timeout(REFRESH_INTERVAL); |
- |
- 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); |
- |
- await timeout(REFRESH_INTERVAL); |
+ // Re-evaluation will only happen after a delay |
+ expectVisible(toHide); |
+ await timeout(REFRESH_INTERVAL); |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- } |
- |
- test.done(); |
-}; |
+ expectHidden(toHide); |
+ } |
+ }); |
-exports.testPseudoClassHasWithClassOnDomMutation = async function(test) |
-{ |
- let parent = createElement(); |
- let child = createElement(parent); |
- |
- let selectors = [ |
- "div:-abp-properties(background-color: rgb(0, 0, 0))", |
- "div[data-hide-me]", |
- "div:-abp-contains(hide me)", |
- "div:-abp-has(> div.hideMe)" |
- ]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
+ describe("Pseudo Class", () => |
{ |
- await timeout(REFRESH_INTERVAL); |
- |
- 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"; |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- expectHidden(test, parent); |
- expectVisible(test, child); |
- } |
- |
- test.done(); |
-}; |
- |
-exports.testPseudoClassHasWithPseudoClassContainsOnDomMutation = async function(test) |
-{ |
- let parent = createElement(); |
- let child = createElement(parent); |
+ it("With prop before selector", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{background-color: #000}", parent); |
- let selectors = [ |
- "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))" |
- ]; |
+ let selectors = ["div:-abp-properties(content: \"publicite\")"]; |
- child.innerText = "do nothing"; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- await timeout(REFRESH_INTERVAL); |
- |
- expectVisible(test, parent); |
- expectVisible(test, child); |
+ insertStyleRule(`#${child.id}::before {content: "publicite"}`); |
- // 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"; |
- |
- await timeout(REFRESH_INTERVAL); |
- |
- // 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); |
- } |
- |
- test.done(); |
-}; |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectHidden(child); |
+ expectVisible(parent); |
+ } |
+ }); |
-exports.testOnlyRelevantElementsProcessed = async function(test) |
-{ |
- // <body> |
- // <div id="n1"> |
- // <p id="n1_1"></p> |
- // <p id="n1_2"></p> |
- // <p id="n1_4">Hello</p> |
- // </div> |
- // <div id="n2"> |
- // <p id="n2_1"></p> |
- // <p id="n2_2"></p> |
- // <p id="n2_4">Hello</p> |
- // </div> |
- // <div id="n3"> |
- // <p id="n3_1"></p> |
- // <p id="n3_2"></p> |
- // <p id="n3_4">Hello</p> |
- // </div> |
- // <div id="n4"> |
- // <p id="n4_1"></p> |
- // <p id="n4_2"></p> |
- // <p id="n4_4">Hello</p> |
- // </div> |
- // </body> |
- for (let i of [1, 2, 3, 4]) |
- { |
- let n = createElement(null, "div", `n${i}`); |
- for (let [j, text] of [[1], [2], [4, "Hello"]]) |
- createElement(n, "p", `n${i}_${j}`, text); |
- } |
- |
- let selectors = [ |
- "p:-abp-contains(Hello)", |
- "div:-abp-contains(Try me!)", |
- "div:-abp-has(p:-abp-contains(This is good))" |
- ]; |
- |
- if (await applyElemHideEmulation(test, selectors)) |
- { |
- await timeout(REFRESH_INTERVAL); |
- |
- // This is only a sanity check to make sure everything else is working |
- // before we do the actual test. |
- for (let i of [1, 2, 3, 4]) |
+ function compareExpectations(elems, expectations) |
{ |
- for (let j of [1, 2, 4]) |
+ for (let elem in expectations) |
{ |
- let id = `n${i}_${j}`; |
- if (j == 4) |
- expectHidden(test, testDocument.getElementById(id), id); |
- else |
- expectVisible(test, testDocument.getElementById(id), id); |
+ if (elems[elem]) |
+ { |
+ if (expectations[elem]) |
+ expectVisible(elems[elem], elem); |
+ else |
+ expectHidden(elems[elem], elem); |
+ } |
} |
} |
- // All <div> and <p> elements should be processed initially. |
- for (let element of [...testDocument.getElementsByTagName("div"), |
- ...testDocument.getElementsByTagName("p")]) |
+ describe("Has Selector", () => |
+ { |
+ it("Simple", async() => |
+ { |
+ let toHide = createElementWithStyle("{}"); |
+ |
+ if (await applyElemHideEmulation(["div:-abp-has(div)"])) |
+ expectVisible(toHide); |
+ }); |
+ |
+ it("With prefix", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ |
+ if (await applyElemHideEmulation(["div:-abp-has(div)"])) |
+ { |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ |
+ it("With suffix", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let child = createElementWithStyle("{}", middle); |
+ |
+ if (await applyElemHideEmulation(["div:-abp-has(div) > div"])) |
+ { |
+ expectVisible(parent); |
+ expectHidden(middle); |
+ expectHidden(child); |
+ } |
+ }); |
+ |
+ it("With suffix sibling", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let toHide = createElementWithStyle("{}"); |
+ |
+ if (await applyElemHideEmulation(["div:-abp-has(div) + div"])) |
+ { |
+ expectVisible(parent); |
+ expectVisible(middle); |
+ expectHidden(toHide); |
+ } |
+ }); |
+ |
+ it("With suffix sibling child", async() => |
+ { |
+ // <div> |
+ // <div></div> |
+ // <div> |
+ // <div>to hide</div> |
+ // </div> |
+ // </div> |
+ let parent = createElementWithStyle("{}"); |
+ let middle = createElementWithStyle("{}", parent); |
+ let sibling = createElementWithStyle("{}"); |
+ let toHide = createElementWithStyle("{}", sibling); |
+ |
+ if (await applyElemHideEmulation(["div:-abp-has(div) + div > div"])) |
+ { |
+ expectVisible(parent); |
+ expectVisible(middle); |
+ expectVisible(sibling); |
+ expectHidden(toHide); |
+ } |
+ }); |
+ |
+ async function runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling(selector, expectations) |
+ { |
+ testDocument.body.innerHTML = `<div id="parent"> |
+ <div id="middle"> |
+ <div id="middle1"><div id="inside" class="inside"></div></div> |
+ </div> |
+ <div id="sibling"> |
+ <div id="tohide"><span>to hide</span></div> |
+ </div> |
+ <div id="sibling2"> |
+ <div id="sibling21"><div id="sibling211" class="inside"></div></div> |
+ </div> |
+ </div>`; |
+ let elems = { |
+ parent: testDocument.getElementById("parent"), |
+ middle: testDocument.getElementById("middle"), |
+ inside: testDocument.getElementById("inside"), |
+ sibling: testDocument.getElementById("sibling"), |
+ sibling2: testDocument.getElementById("sibling2"), |
+ toHide: testDocument.getElementById("tohide") |
+ }; |
+ |
+ insertStyleRule(".inside {}"); |
+ if (await applyElemHideEmulation([selector])) |
+ compareExpectations(elems, expectations); |
+ } |
+ |
+ it("With has and with suffix sibling", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middile: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: false |
+ }; |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
+ "div:-abp-has(:-abp-has(div.inside)) + div > div", expectations); |
+ }); |
+ |
+ it("With has an with suffix sibling (2)", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middile: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: false |
+ }; |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
+ "div:-abp-has(:-abp-has(> div.inside)) + div > div", expectations); |
+ }); |
+ |
+ it("With has an with suffix sibling (3)", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middile: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: false |
+ }; |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
+ "div:-abp-has(> div:-abp-has(div.inside)) + div > div", expectations); |
+ }); |
+ |
+ it("With suffix sibling no-op", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middile: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
+ "div:-abp-has(> body div.inside) + div > div", expectations); |
+ }); |
+ |
+ it("With suffix sibling contains", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middile: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassHasSelectorWithHasAndWithSuffixSibling( |
+ "div:-abp-has(> span:-abp-contains(Advertisment))", expectations); |
+ }); |
+ }); |
+ |
+ describe("Property Selector Qualifiers", () => |
+ { |
+ async function runTestQualifier(selector) |
+ { |
+ testDocument.body.innerHTML = ` |
+ <style> |
+ span::before { |
+ content: "any"; |
+ } |
+ </style> |
+ <div id="toHide"> |
+ <a> |
+ <p> |
+ <span></span> |
+ </p> |
+ </a> |
+ </div>`; |
+ |
+ if (await applyElemHideEmulation([selector])) |
+ expectHidden(testDocument.getElementById("toHide")); |
+ } |
+ |
+ // See issue https://issues.adblockplus.org/ticket/7428 |
+ it("Combinator", () => |
+ { |
+ runTestQualifier( |
+ "div:-abp-has(> a p > :-abp-properties(content: \"any\"))" |
+ ); |
+ }); |
+ |
+ // See issue https://issues.adblockplus.org/ticket/7359 |
+ it("Nested Combinator", () => |
+ { |
+ runTestQualifier( |
+ "div:-abp-has(> a p:-abp-has(> :-abp-properties(content: \"any\")))" |
+ ); |
+ }); |
+ |
+ // See issue https://issues.adblockplus.org/ticket/7400 |
+ it("Identical", () => |
+ { |
+ runTestQualifier( |
+ "div:-abp-has(span:-abp-properties(content: \"any\"))" |
+ ); |
+ }); |
+ |
+ // See issue https://issues.adblockplus.org/ticket/7400 |
+ it("Nested Identical", () => |
+ { |
+ runTestQualifier( |
+ "div:-abp-has(p:-abp-has(span:-abp-properties(content: \"any\")))" |
+ ); |
+ }); |
+ }); |
+ |
+ describe("Contains selector", () => |
+ { |
+ async function runTestPseudoClassContains(selector, expectations) |
+ { |
+ testDocument.body.innerHTML = `<div id="parent"> |
+ <div id="middle"> |
+ <div id="middle1"><div id="inside" class="inside"></div></div> |
+ </div> |
+ <div id="sibling"> |
+ <div id="tohide">to hide \ud83d\ude42!</div> |
+ </div> |
+ <div id="sibling2"> |
+ <div id="sibling21"> |
+ <div id="sibling211" class="inside">Ad*</div> |
+ </div> |
+ </div> |
+ </div>`; |
+ let elems = { |
+ parent: testDocument.getElementById("parent"), |
+ middle: testDocument.getElementById("middle"), |
+ inside: testDocument.getElementById("inside"), |
+ sibling: testDocument.getElementById("sibling"), |
+ sibling2: testDocument.getElementById("sibling2"), |
+ toHide: testDocument.getElementById("tohide") |
+ }; |
+ |
+ if (await applyElemHideEmulation([selector])) |
+ compareExpectations(elems, expectations); |
+ } |
+ |
+ it("Text", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: false, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(to hide)", expectations); |
+ }); |
+ |
+ it("Regexp", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: false, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(/to\\shide/)", expectations); |
+ }); |
+ |
+ it("Regexp i flag", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: false, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(/to\\sHide/i)", expectations); |
+ }); |
+ |
+ it("Regexp u flag", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: false, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(/to\\shide\\s.!/u)", expectations); |
+ }); |
+ |
+ it("Wildcard no match", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: true, |
+ toHide: true |
+ }; |
+ // this filter shouldn't match anything as "*" has no meaning. |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(to *hide)", expectations); |
+ }); |
+ |
+ it("Wildcard match", () => |
+ { |
+ let expectations = { |
+ parent: true, |
+ middle: true, |
+ inside: true, |
+ sibling: true, |
+ sibling2: false, |
+ toHide: true |
+ }; |
+ runTestPseudoClassContains( |
+ "#parent div:-abp-contains(Ad*)", expectations); |
+ }); |
+ }); |
+ |
+ describe("Has Selector with prop selector", () => |
{ |
- expectProcessed(test, element, element.id); |
+ it("Already present", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{background-color: #000}", parent); |
+ |
+ let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(child); |
+ expectHidden(parent); |
+ } |
+ }); |
+ |
+ it("Dynamically added", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ |
+ let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
+ |
+ insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(child); |
+ expectHidden(parent); |
+ } |
+ }); |
+ }); |
+ }); |
+ |
+ describe("DOM updates", () => |
+ { |
+ it("Style", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ |
+ let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectVisible(child); |
+ expectVisible(parent); |
+ |
+ insertStyleRule("body #" + parent.id + " > div { background-color: #000}"); |
+ await timeout(0); |
+ |
+ expectVisible(child); |
+ expectVisible(parent); |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(child); |
+ expectHidden(parent); |
+ } |
+ }); |
+ |
+ it("Content", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{}", parent); |
+ |
+ if (await applyElemHideEmulation(["div > div:-abp-contains(hide me)"])) |
+ { |
+ expectVisible(parent); |
+ expectVisible(child); |
+ |
+ child.textContent = "hide me"; |
+ await timeout(0); |
+ |
+ expectVisible(parent); |
+ expectVisible(child); |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectHidden(child); |
+ } |
+ }); |
+ |
+ it("New element", async() => |
+ { |
+ let parent = createElementWithStyle("{}"); |
+ let child = createElementWithStyle("{ background-color: #000}", parent); |
+ let sibling; |
+ let child2; |
+ |
+ let selectors = ["div:-abp-has(:-abp-properties(background-color: rgb(0, 0, 0)))"]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ expectHidden(parent); |
+ expectVisible(child); |
+ |
+ sibling = createElementWithStyle("{}"); |
+ await timeout(0); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ expectVisible(sibling); |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ expectVisible(sibling); |
+ |
+ child2 = createElementWithStyle("{ background-color: #000}", |
+ sibling); |
+ await timeout(0); |
+ |
+ expectVisible(child2); |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ expectHidden(sibling); |
+ expectVisible(child2); |
+ } |
+ }); |
+ }); |
+ |
+ it("Pseudo class properties on stylesheet load", async() => |
+ { |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ let selectors = [ |
+ "div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)" |
+ ]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectVisible(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}"); |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ |
+ describe("On DOM mutation", () => |
+ { |
+ it("Plain attributes", async() => |
+ { |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ let selectors = [ |
+ "div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)" |
+ ]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectVisible(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", ""); |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectHidden(child); |
+ } |
+ }); |
+ |
+ it("Pseudo class contains", async() => |
+ { |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ let selectors = [ |
+ "div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)" |
+ ]; |
+ |
+ child.innerText = "do nothing"; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectVisible(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"; |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ |
+ it("Pseudo class has", async() => |
+ { |
+ let parent = createElement(); |
+ let child = null; |
+ |
+ let selectors = [ |
+ "div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div)" |
+ ]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(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); |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ |
+ it("Pseudo class has", async() => |
+ { |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ let selectors = [ |
+ "div:-abp-properties(background-color: rgb(0, 0, 0))", |
+ "div[data-hide-me]", |
+ "div:-abp-contains(hide me)", |
+ "div:-abp-has(> div.hideMe)" |
+ ]; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectVisible(child); |
+ |
+ // Set the child element's class to "hideMe". This should run only the |
+ // "div:-abp-has(> div.hideMe)" pattern. |
+ child.className = "hideMe"; |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ |
+ it("Pseudo class has with pseudo class contains", async() => |
+ { |
+ let parent = createElement(); |
+ let child = createElement(parent); |
+ |
+ let selectors = [ |
+ "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))" |
+ ]; |
+ |
+ child.innerText = "do nothing"; |
+ |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ expectVisible(parent); |
+ expectVisible(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"; |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ // Note: Even though it runs both the :-abp-contains() patterns, it only |
+ // hides the parent element because of revision d7d51d29aa34. |
+ expectHidden(parent); |
+ expectVisible(child); |
+ } |
+ }); |
+ }); |
+ |
+ it("Only relevant elements are processed", async() => |
+ { |
+ // <body> |
+ // <div id="n1"> |
+ // <p id="n1_1"></p> |
+ // <p id="n1_2"></p> |
+ // <p id="n1_4">Hello</p> |
+ // </div> |
+ // <div id="n2"> |
+ // <p id="n2_1"></p> |
+ // <p id="n2_2"></p> |
+ // <p id="n2_4">Hello</p> |
+ // </div> |
+ // <div id="n3"> |
+ // <p id="n3_1"></p> |
+ // <p id="n3_2"></p> |
+ // <p id="n3_4">Hello</p> |
+ // </div> |
+ // <div id="n4"> |
+ // <p id="n4_1"></p> |
+ // <p id="n4_2"></p> |
+ // <p id="n4_4">Hello</p> |
+ // </div> |
+ // </body> |
+ for (let i of [1, 2, 3, 4]) |
+ { |
+ let n = createElement(null, "div", `n${i}`); |
+ for (let [j, text] of [[1], [2], [4, "Hello"]]) |
+ createElement(n, "p", `n${i}_${j}`, text); |
} |
- // Modify the text in <p id="n4_1"> |
- testDocument.getElementById("n4_1").innerText = "Try me!"; |
+ let selectors = [ |
+ "p:-abp-contains(Hello)", |
+ "div:-abp-contains(Try me!)", |
+ "div:-abp-has(p:-abp-contains(This is good))" |
+ ]; |
- await timeout(REFRESH_INTERVAL); |
+ if (await applyElemHideEmulation(selectors)) |
+ { |
+ await timeout(REFRESH_INTERVAL); |
- // When an element's text is modified, only the element or one of its |
- // ancestors matching any selector is processed for :-abp-has() and |
- // :-abp-contains() |
- for (let element of [...testDocument.getElementsByTagName("div"), |
- ...testDocument.getElementsByTagName("p")]) |
- { |
- if (element.id == "n4" || element.id == "n4_1") |
- expectProcessed(test, element, element.id); |
- else |
- expectNotProcessed(test, element, element.id); |
- } |
+ // This is only a sanity check to make sure everything else is working |
+ // before we do the actual test. |
+ for (let i of [1, 2, 3, 4]) |
+ { |
+ for (let j of [1, 2, 4]) |
+ { |
+ let id = `n${i}_${j}`; |
+ if (j == 4) |
+ expectHidden(testDocument.getElementById(id), id); |
+ else |
+ expectVisible(testDocument.getElementById(id), id); |
+ } |
+ } |
+ |
+ // All <div> and <p> elements should be processed initially. |
+ for (let element of [...testDocument.getElementsByTagName("div"), |
+ ...testDocument.getElementsByTagName("p")]) |
+ { |
+ expectProcessed(element, element.id); |
+ } |
- // Create a new <p id="n2_3"> element with no text. |
- createElement(testDocument.getElementById("n2"), "p", "n2_3"); |
+ // Modify the text in <p id="n4_1"> |
+ testDocument.getElementById("n4_1").innerText = "Try me!"; |
+ |
+ await timeout(REFRESH_INTERVAL); |
- await timeout(REFRESH_INTERVAL); |
+ // When an element's text is modified, only the element or one of its |
+ // ancestors matching any selector is processed for :-abp-has() and |
+ // :-abp-contains() |
+ for (let element of [...testDocument.getElementsByTagName("div"), |
+ ...testDocument.getElementsByTagName("p")]) |
+ { |
+ if (element.id == "n4" || element.id == "n4_1") |
+ expectProcessed(element, element.id); |
+ else |
+ expectNotProcessed(element, element.id); |
+ } |
- // When a new element is added, only the element or one of its ancestors |
- // matching any selector is processed for :-abp-has() and :-abp-contains() |
- for (let element of [...testDocument.getElementsByTagName("div"), |
- ...testDocument.getElementsByTagName("p")]) |
- { |
- if (element.id == "n2" || element.id == "n2_3") |
- expectProcessed(test, element, element.id); |
- else |
- expectNotProcessed(test, element, element.id); |
+ // Create a new <p id="n2_3"> element with no text. |
+ createElement(testDocument.getElementById("n2"), "p", "n2_3"); |
+ |
+ await timeout(REFRESH_INTERVAL); |
+ |
+ // When a new element is added, only the element or one of its ancestors |
+ // matching any selector is processed for :-abp-has() and :-abp-contains() |
+ for (let element of [...testDocument.getElementsByTagName("div"), |
+ ...testDocument.getElementsByTagName("p")]) |
+ { |
+ if (element.id == "n2" || element.id == "n2_3") |
+ expectProcessed(element, element.id); |
+ else |
+ expectNotProcessed(element, element.id); |
+ } |
} |
- } |
- |
- test.done(); |
-}; |
+ }); |
+}); |