summaryrefslogtreecommitdiffstats
path: root/tests/selenium/widgets_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/selenium/widgets_test.py')
-rw-r--r--tests/selenium/widgets_test.py344
1 files changed, 344 insertions, 0 deletions
diff --git a/tests/selenium/widgets_test.py b/tests/selenium/widgets_test.py
new file mode 100644
index 0000000..d8bc2b5
--- /dev/null
+++ b/tests/selenium/widgets_test.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+import unittest
+
+import pbtest
+
+from time import sleep
+
+from selenium.common.exceptions import (
+ NoSuchElementException,
+ StaleElementReferenceException,
+ TimeoutException
+)
+from selenium.webdriver.common.keys import Keys
+
+
+class WidgetsTest(pbtest.PBSeleniumTest):
+
+ FIXTURES_URL = "https://efforg.github.io/privacybadger-test-fixtures/html/"
+ BASIC_FIXTURE_URL = FIXTURES_URL + "widget_basic.html"
+ DYNAMIC_FIXTURE_URL = FIXTURES_URL + "widget_dynamic.html"
+ THIRD_PARTY_DOMAIN = "privacybadger-tests.eff.org"
+ TYPE3_WIDGET_NAME = "Type 3 Widget"
+ TYPE4_WIDGET_NAME = "Type 4 Widget"
+ TYPE4_WIDGET_CLASS = "pb-type4-test-widget"
+
+ def setUp(self):
+ self.set_up_widgets()
+
+ def set_up_widgets(self):
+ """Reinitializes Privacy Badger's widget replacement definitions."""
+
+ widgetsJson = {
+ self.TYPE3_WIDGET_NAME: {
+ "domain": self.THIRD_PARTY_DOMAIN,
+ "buttonSelectors": [
+ "iframe#pb-type3-test-widget"
+ ],
+ "replacementButton": {
+ "unblockDomains": [
+ self.THIRD_PARTY_DOMAIN
+ ],
+ "type": 3
+ }
+ },
+ self.TYPE4_WIDGET_NAME: {
+ "domains": [
+ self.THIRD_PARTY_DOMAIN
+ ],
+ "buttonSelectors": [
+ "div." + self.TYPE4_WIDGET_CLASS
+ ],
+ "scriptSelectors": [
+ "script." + self.TYPE4_WIDGET_CLASS
+ ],
+ "replacementButton": {
+ "unblockDomains": [
+ self.THIRD_PARTY_DOMAIN
+ ],
+ "type": 4
+ }
+ }
+ }
+
+ # reinitialize widgets using above JSON
+ self.load_url(self.options_url)
+ self.js((
+ "(function (widgetsJson) {"
+ " let bg = chrome.extension.getBackgroundPage();"
+ " bg.badger.widgetList = bg.widgetLoader.initializeWidgets(widgetsJson);"
+ "}(arguments[0]));"
+ ), widgetsJson)
+
+ def switch_to_frame(self, selector):
+ self.wait_for_and_switch_to_frame(selector, timeout=1)
+
+ def assert_widget(self, kind="type3"):
+ if kind == "type3":
+ self._assert_type3_widget()
+ elif kind == "type4":
+ self._assert_type4_widget()
+ else:
+ self.fail("Unknown widget type")
+
+ def _assert_type3_widget(self):
+ try:
+ self.switch_to_frame('iframe[src]')
+ except (StaleElementReferenceException, TimeoutException):
+ self.fail("Unable to find widget frame")
+
+ try:
+ self.wait_for_text('body', "Hello world!")
+ except TimeoutException:
+ self.fail("Unable to find expected widget text")
+
+ self.driver.switch_to.default_content()
+
+ def _assert_type4_widget(self):
+ try:
+ self.wait_for_text('div.' + self.TYPE4_WIDGET_CLASS,
+ "A third-party widget script was here")
+ except TimeoutException:
+ self.fail("Unable to find expected widget output")
+
+ def assert_replacement(self, widget_name=None):
+ if not widget_name:
+ widget_name = self.TYPE3_WIDGET_NAME
+
+ try:
+ self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
+ except (StaleElementReferenceException, TimeoutException):
+ self.fail("Unable to find widget placeholder frame")
+
+ try:
+ self.find_el_by_css("button[id^='btn-once-']")
+ self.find_el_by_css("button[id^='btn-site-']")
+ except TimeoutException:
+ self.fail("Unable to find expected widget placeholder buttons")
+
+ self.driver.switch_to.default_content()
+
+ def assert_widget_blocked(self):
+ try:
+ self.switch_to_frame('iframe[src]')
+ except TimeoutException:
+ self.fail("Widget frame should still be here")
+
+ self.assertFalse(
+ self.txt_by_css('body'), "Widget frame should be empty")
+
+ self.driver.switch_to.default_content()
+
+ def assert_no_widget(self):
+ try:
+ self.switch_to_frame('iframe[src]')
+ self.fail("Widget frame should be missing")
+ except TimeoutException:
+ pass
+ self.driver.switch_to.default_content()
+
+ def assert_no_replacement(self, widget_name=None):
+ if not widget_name:
+ widget_name = self.TYPE3_WIDGET_NAME
+ try:
+ self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
+ self.fail("Widget placeholder frame should be missing")
+ except TimeoutException:
+ pass
+ self.driver.switch_to.default_content()
+
+ def activate_widget(self, widget_name=None, once=True):
+ if not widget_name:
+ widget_name = self.TYPE3_WIDGET_NAME
+ id_prefix = 'btn-once' if once else 'btn-site'
+ self.switch_to_frame('iframe[srcdoc*="{}"]'.format(widget_name))
+ self.find_el_by_css("button[id^='%s']" % id_prefix).click()
+ self.driver.switch_to.default_content()
+
+ def test_replacement_basic(self):
+ # visit the basic widget fixture
+ self.load_url(self.BASIC_FIXTURE_URL)
+ # verify the widget is present
+ self.assert_widget()
+
+ # block the test widget's domain
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+
+ # revisit the fixture
+ self.load_url(self.BASIC_FIXTURE_URL)
+ # verify the widget got replaced
+ self.assert_replacement()
+
+ def test_replacement_dynamic(self):
+ # visit the dynamic widget fixture
+ self.load_url(self.DYNAMIC_FIXTURE_URL)
+ # verify the widget is initially missing
+ self.assert_no_widget()
+
+ # verify the widget shows up once you click on the trigger element
+ self.find_el_by_css('#widget-trigger').click()
+ self.assert_widget()
+
+ # block the test widget's domain
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+
+ # revisit the fixture
+ self.load_url(self.DYNAMIC_FIXTURE_URL)
+ # click on the trigger element
+ self.find_el_by_css('#widget-trigger').click()
+ # verify the widget got replaced
+ self.assert_replacement()
+
+ def test_activation(self):
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+ self.load_url(self.BASIC_FIXTURE_URL)
+ self.assert_replacement()
+
+ # click the "allow once" button
+ self.activate_widget()
+
+ # verify the original widget is restored
+ self.assert_widget()
+
+ # verify the type 4 widget is still replaced
+ try:
+ self.driver.find_element_by_css_selector(
+ 'div.' + self.TYPE4_WIDGET_CLASS)
+ self.fail("Widget output container div should be missing")
+ except NoSuchElementException:
+ pass
+ self.assert_replacement(self.TYPE4_WIDGET_NAME)
+
+ self.activate_widget(self.TYPE4_WIDGET_NAME)
+
+ # assert all script attributes were copied
+ script_el = self.driver.find_element_by_css_selector(
+ 'script.' + self.TYPE4_WIDGET_CLASS)
+ self.assertEqual(script_el.get_attribute('async'), "true")
+ self.assertEqual(script_el.get_attribute('data-foo'), "bar")
+
+ self.assert_widget("type4")
+
+ def test_activation_site(self):
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+ self.load_url(self.BASIC_FIXTURE_URL)
+ self.assert_replacement()
+
+ # click the "allow once" button
+ self.activate_widget()
+
+ # verify the original widget is restored
+ self.assert_widget()
+
+ # open a new window (to get around widget activation caching)
+ self.open_window()
+ self.load_url(self.BASIC_FIXTURE_URL)
+
+ # verify the widget got replaced
+ self.assert_replacement()
+
+ # click the "allow on site" button
+ self.activate_widget(once=False)
+
+ # verify the original widget is restored
+ self.assert_widget()
+
+ # open a new window (to get around widget activation caching)
+ self.open_window()
+ self.load_url(self.BASIC_FIXTURE_URL)
+
+ # verify basic widget is neither replaced nor blocked
+ self.assert_no_replacement()
+ self.assert_widget()
+
+ def test_disabling_site(self):
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+
+ self.disable_badger_on_site(self.BASIC_FIXTURE_URL)
+
+ # verify basic widget is neither replaced nor blocked
+ self.load_url(self.BASIC_FIXTURE_URL)
+ self.assert_no_replacement()
+ self.assert_widget()
+ # type 4 replacement should also be missing
+ self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
+ # while the type 4 widget script should have executed
+ self.assert_widget("type4")
+
+ # verify dynamic widget is neither replaced nor blocked
+ self.load_url(self.DYNAMIC_FIXTURE_URL)
+ self.find_el_by_css('#widget-trigger').click()
+ self.assert_no_replacement()
+ self.assert_widget()
+
+ def test_disabling_all_replacement(self):
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+
+ # disable widget replacement
+ self.load_url(self.options_url)
+ self.wait_for_script("return window.OPTIONS_INITIALIZED")
+ self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
+ self.driver.find_element_by_id('replace-widgets-checkbox').click()
+
+ # verify basic widget is no longer replaced
+ self.load_url(self.BASIC_FIXTURE_URL)
+ self.assert_no_replacement()
+ self.assert_widget_blocked()
+ # type 4 replacement should also be missing
+ self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
+ # type 4 widget should also have gotten blocked
+ try:
+ widget_div = self.driver.find_element_by_css_selector(
+ 'div.pb-type4-test-widget')
+ except NoSuchElementException:
+ self.fail("Widget div should still be here")
+ # check the div's text a few times to make sure it stays empty
+ for _ in range(3):
+ self.assertFalse(widget_div.text,
+ "Widget output container should remain empty")
+ sleep(1)
+
+ # verify dynamic widget is no longer replaced
+ self.load_url(self.DYNAMIC_FIXTURE_URL)
+ self.find_el_by_css('#widget-trigger').click()
+ self.assert_no_replacement()
+ self.assert_widget_blocked()
+
+ def test_disabling_replacement_for_one_widget(self):
+ self.block_domain(self.THIRD_PARTY_DOMAIN)
+
+ # add the widget to the list of exceptions
+ self.load_url(self.options_url)
+ self.wait_for_script("return window.OPTIONS_INITIALIZED")
+ self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
+ self.find_el_by_css('input[type="search"]').send_keys(
+ self.TYPE3_WIDGET_NAME, Keys.ENTER)
+
+ # verify basic widget is no longer replaced
+ self.load_url(self.BASIC_FIXTURE_URL)
+ self.assert_no_replacement()
+ self.assert_widget_blocked()
+ # verify the type 4 widget is still replaced
+ self.assert_replacement(self.TYPE4_WIDGET_NAME)
+
+ # verify dynamic widget is no longer replaced
+ self.load_url(self.DYNAMIC_FIXTURE_URL)
+ self.find_el_by_css('#widget-trigger').click()
+ self.assert_no_replacement()
+ self.assert_widget_blocked()
+
+ def test_no_replacement_when_cookieblocked(self):
+ self.cookieblock_domain(self.THIRD_PARTY_DOMAIN)
+ self.load_url(self.BASIC_FIXTURE_URL)
+
+ self.assert_no_replacement()
+ self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
+
+ self.assert_widget()
+ self.assert_widget("type4")
+
+
+if __name__ == "__main__":
+ unittest.main()