aboutsummaryrefslogtreecommitdiff
path: root/test/unit
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/conftest.py163
-rw-r--r--test/unit/test_basic.py4
-rw-r--r--test/unit/test_broadcast.py3
-rw-r--r--test/unit/test_content.py8
-rw-r--r--test/unit/test_indexeddb.py2
-rw-r--r--test/unit/test_patterns_query_manager.py19
-rw-r--r--test/unit/test_repo_query_cacher.py11
7 files changed, 31 insertions, 179 deletions
diff --git a/test/unit/conftest.py b/test/unit/conftest.py
deleted file mode 100644
index a3064f1..0000000
--- a/test/unit/conftest.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-"""
-Common fixtures for Haketilo unit tests
-"""
-
-# This file is part of Haketilo.
-#
-# Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# 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 this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# I, Wojtek Kosior, thereby promise not to sue for violation of this file's
-# license. Although I request that you do not make use of this code in a
-# proprietary program, I am not going to enforce this in court.
-
-import pytest
-from pathlib import Path
-from selenium.webdriver.common.by import By
-from selenium.webdriver.support.ui import WebDriverWait
-from selenium.webdriver.support import expected_conditions as EC
-
-from ..profiles import firefox_safe_mode
-from ..server import do_an_internet
-from ..extension_crafting import make_extension
-from ..world_wide_library import start_serving_script, dump_scripts
-
-@pytest.fixture(scope="package")
-def proxy():
- httpd = do_an_internet()
- yield httpd
- httpd.shutdown()
-
-@pytest.fixture(scope="package")
-def _driver(proxy):
- with firefox_safe_mode() as driver:
- yield driver
- driver.quit()
-
-def close_all_but_one_window(driver):
- while len(driver.window_handles) > 1:
- driver.switch_to.window(driver.window_handles[-1])
- driver.close()
- driver.switch_to.window(driver.window_handles[0])
-
-@pytest.fixture()
-def driver(_driver, request):
- nav_target = request.node.get_closest_marker('get_page')
- close_all_but_one_window(_driver)
- _driver.get(nav_target.args[0] if nav_target else 'about:blank')
- _driver.implicitly_wait(0)
- yield _driver
-
-@pytest.fixture()
-def webextension(driver, request):
- ext_data = request.node.get_closest_marker('ext_data')
- if ext_data is None:
- raise Exception('"webextension" fixture requires "ext_data" marker to be set')
- ext_data = ext_data.args[0].copy()
-
- navigate_to = ext_data.get('navigate_to')
- if navigate_to is not None:
- del ext_data['navigate_to']
-
- driver.get('https://gotmyowndoma.in/')
- ext_path = make_extension(Path(driver.firefox_profile.path), **ext_data)
- addon_id = driver.install_addon(str(ext_path), temporary=True)
- WebDriverWait(driver, 10).until(
- EC.url_matches('^moz-extension://.*')
- )
-
- if navigate_to is not None:
- testpage_url = driver.execute_script('return window.location.href;')
- driver.get(testpage_url.replace('testpage.html', navigate_to))
-
- yield
-
- close_all_but_one_window(driver)
- driver.get('https://gotmyowndoma.in/')
- driver.uninstall_addon(addon_id)
- ext_path.unlink()
-
-script_injector_script = '''\
-/*
- * Selenium by default executes scripts in some weird one-time context. We want
- * separately-loaded scripts to be able to access global variables defined
- * before, including those declared with `const` or `let`. To achieve that, we
- * run our scripts by injecting them into the page with a <script> tag that runs
- * javascript served by our proxy. We use custom properties of the `window`
- * object to communicate with injected code.
- */
-const inject = async () => {
- delete window.haketilo_selenium_return_value;
- delete window.haketilo_selenium_exception;
- window.returnval = val => window.haketilo_selenium_return_value = val;
-
- const injectee = document.createElement('script');
- injectee.src = arguments[0];
- injectee.type = "application/javascript";
- injectee.async = true;
- const prom = new Promise(cb => injectee.onload = cb);
-
- window.arguments = arguments[1];
- document.body.append(injectee);
-
- await prom;
-
- /*
- * To ease debugging, we want this script to signal all exceptions from the
- * injectee.
- */
- if (window.haketilo_selenium_exception !== false)
- throw ['haketilo_selenium_error',
- 'Error in injected script! Check your geckodriver.log and ./injected_scripts/!'];
-
- return window.haketilo_selenium_return_value;
-}
-return inject();
-'''
-
-def _execute_in_page_context(driver, script, args):
- script = script + '\n;\nwindow.haketilo_selenium_exception = false;'
- script_url = start_serving_script(script)
-
- try:
- result = driver.execute_script(script_injector_script, script_url, args)
- if type(result) is list and len(result) == 2 and \
- result[0] == 'haketilo_selenium_error':
- raise Exception(result[1])
- return result
- except Exception as e:
- dump_scripts()
- raise e from None
-
-# Some fixtures here just define functions that operate on driver. We should
-# consider making them into webdriver wrapper class methods.
-
-@pytest.fixture()
-def execute_in_page(driver):
- def do_execute(script, *args):
- return _execute_in_page_context(driver, script, args)
-
- yield do_execute
-
-@pytest.fixture()
-def wait_elem_text(driver):
- def do_wait(id, text):
- WebDriverWait(driver, 10).until(
- EC.text_to_be_present_in_element((By.ID, id), text)
- )
-
- yield do_wait
diff --git a/test/unit/test_basic.py b/test/unit/test_basic.py
index 5f42f5d..6ec54cc 100644
--- a/test/unit/test_basic.py
+++ b/test/unit/test_basic.py
@@ -40,9 +40,9 @@ def test_script_loader(execute_in_page):
A trivial test case that verifies Haketilo's .js files can be properly
loaded into a test page together with their dependencies.
"""
- execute_in_page(load_script('common/stored_types.js'))
+ execute_in_page(load_script('common/indexeddb.js'))
- assert execute_in_page('returnval(TYPE_PREFIX.VAR);') == '_'
+ assert 'mapping' in execute_in_page('returnval(stores.map(s => s[0]));')
@pytest.mark.ext_data({})
@pytest.mark.usefixtures('webextension')
diff --git a/test/unit/test_broadcast.py b/test/unit/test_broadcast.py
index 7de6c80..7c2c051 100644
--- a/test/unit/test_broadcast.py
+++ b/test/unit/test_broadcast.py
@@ -18,6 +18,7 @@ Haketilo unit tests - message broadcasting
# CC0 1.0 Universal License for more details.
import pytest
+from selenium.webdriver.support.ui import WebDriverWait
from ..script_loader import load_script
from .utils import broker_js
@@ -55,8 +56,8 @@ def test_broadcast(driver, execute_in_page, wait_elem_text):
window.open(window.location.href, "_blank");
window.open(window.location.href, "_blank");
''')
+ WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 3)
windows = [*driver.window_handles]
- assert len(windows) == 3
# Let's first test if a simple message can be successfully broadcasted
driver.switch_to.window(windows[0])
diff --git a/test/unit/test_content.py b/test/unit/test_content.py
index 35ab027..8220160 100644
--- a/test/unit/test_content.py
+++ b/test/unit/test_content.py
@@ -33,7 +33,7 @@ dynamic_script = \
''';
this.haketilo_secret = "abracadabra";
this.haketilo_pattern_tree = {};
- this.haketilo_defualt_allow = false;
+ this.haketilo_default_allow = false;
if (this.haketilo_content_script_main)
this.haketilo_content_script_main();
@@ -69,7 +69,7 @@ content_script = \
async function mock_payload_ok([type, res_id]) {
if (type === "indexeddb_files")
- return [1, 2].map(n => `window.haketilo_injected_${n} = ${n}${n};`);
+ return {files: [1, 2].map(n => `window.hak_injected_${n} = ${n};`)};
}
if (/payload_error/.test(document.URL)) {
@@ -162,7 +162,7 @@ def test_content_unprivileged_page(driver, execute_in_page, target1, target2):
def vars_made_by_payload(driver):
vars_values = driver.execute_script(
- 'return [1, 2].map(n => window[`haketilo_injected_${n}`]);'
+ 'return [1, 2].map(n => window[`hak_injected_${n}`]);'
)
if vars_values != [None, None]:
return vars_values
@@ -174,7 +174,7 @@ def test_content_unprivileged_page(driver, execute_in_page, target1, target2):
}
elif target2 == 'payload_ok':
vars_values = WebDriverWait(driver, 10).until(vars_made_by_payload)
- assert vars_values == [11, 22]
+ assert vars_values == [1, 2]
@pytest.mark.ext_data({'content_script': content_script})
@pytest.mark.usefixtures('webextension')
diff --git a/test/unit/test_indexeddb.py b/test/unit/test_indexeddb.py
index b320cff..550b923 100644
--- a/test/unit/test_indexeddb.py
+++ b/test/unit/test_indexeddb.py
@@ -318,8 +318,8 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text):
# will be used to make changes to IndexedDB and window 0 to "track" those
# changes.
driver.execute_script('window.open(window.location.href, "_blank");')
+ WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 2)
windows = [*driver.window_handles]
- assert len(windows) == 2
# Create elements that will have tracked data inserted under them.
driver.switch_to.window(windows[0])
diff --git a/test/unit/test_patterns_query_manager.py b/test/unit/test_patterns_query_manager.py
index c6ebb81..5daf3a0 100644
--- a/test/unit/test_patterns_query_manager.py
+++ b/test/unit/test_patterns_query_manager.py
@@ -150,14 +150,14 @@ def test_pqm_tree_building(driver, execute_in_page):
all([m['identifier'] in last_script for m in sample_mappings]))
execute_in_page(
- '''
+ '''{
const new_setting_val = {name: "default_allow", value: false};
settingchange({key: "default_allow", new_val: new_setting_val});
for (const mapping of arguments[0])
mappingchange({key: mapping.identifier, new_val: mapping});
for (const blocking of arguments[1])
blockingchange({key: blocking.pattern, new_val: blocking});
- ''',
+ }''',
sample_mappings[2:], sample_blocking[2:])
WebDriverWait(driver, 10).until(condition_all_added)
@@ -201,6 +201,19 @@ def test_pqm_tree_building(driver, execute_in_page):
WebDriverWait(driver, 10).until(condition_all_removed)
+ def condition_default_allowed_again(driver):
+ content_script = execute_in_page('returnval(last_script);')
+ cs_values = get_content_script_values(driver, content_script)
+ return cs_values['haketilo_default_allow'] == True
+
+ execute_in_page(
+ '''{
+ const new_setting_val = {name: "default_allow", value: true};
+ settingchange({key: "default_allow", new_val: new_setting_val});
+ }''')
+
+ WebDriverWait(driver, 10).until(condition_default_allowed_again)
+
content_js = '''
let already_run = false;
this.haketilo_content_script_main = function() {
@@ -229,8 +242,8 @@ def test_pqm_script_injection(driver, execute_in_page):
# Let's open a normal page in a second window. Window 0 will be used to make
# changed to IndexedDB and window 1 to test the working of content scripts.
driver.execute_script('window.open("about:blank", "_blank");')
+ WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 2)
windows = [*driver.window_handles]
- assert len(windows) == 2
def run_content_script():
driver.switch_to.window(windows[1])
diff --git a/test/unit/test_repo_query_cacher.py b/test/unit/test_repo_query_cacher.py
index b1ce4c8..5fbc5cd 100644
--- a/test/unit/test_repo_query_cacher.py
+++ b/test/unit/test_repo_query_cacher.py
@@ -65,18 +65,19 @@ def run_content_script_in_new_window(driver, url):
Open the provided url in a new tab, find its tab id and return it, with
current window changed back to the initial one.
"""
- initial_handle = driver.current_window_handle
- handles = driver.window_handles
+ handle0 = driver.current_window_handle
+ initial_handles = [*driver.window_handles]
driver.execute_script('window.open(arguments[0], "_blank");', url)
- WebDriverWait(driver, 10).until(lambda d: d.window_handles is not handles)
- new_handle = [h for h in driver.window_handles if h not in handles][0]
+ window_added = lambda d: set(d.window_handles) != set(initial_handles)
+ WebDriverWait(driver, 10).until(window_added)
+ new_handle = [*set(driver.window_handles).difference(initial_handles)][0]
driver.switch_to.window(new_handle)
get_tab_id = lambda d: d.execute_script('return window.haketilo_tab;')
tab_id = WebDriverWait(driver, 10).until(get_tab_id)
- driver.switch_to.window(initial_handle)
+ driver.switch_to.window(handle0)
return tab_id
@pytest.mark.ext_data({