aboutsummaryrefslogtreecommitdiff
path: root/test/haketilo_test/unit/test_indexeddb_files_server.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/haketilo_test/unit/test_indexeddb_files_server.py')
-rw-r--r--test/haketilo_test/unit/test_indexeddb_files_server.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/test/haketilo_test/unit/test_indexeddb_files_server.py b/test/haketilo_test/unit/test_indexeddb_files_server.py
new file mode 100644
index 0000000..6ddfba8
--- /dev/null
+++ b/test/haketilo_test/unit/test_indexeddb_files_server.py
@@ -0,0 +1,171 @@
+# SPDX-License-Identifier: CC0-1.0
+
+"""
+Haketilo unit tests - serving indexeddb resource script files to content scripts
+"""
+
+# This file is part of Haketilo
+#
+# Copyright (C) 2021,2022 Wojtek Kosior <koszko@koszko.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the CC0 1.0 Universal License as published by
+# the Creative Commons Corporation.
+#
+# 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
+# CC0 1.0 Universal License for more details.
+
+import pytest
+import copy
+from uuid import uuid4
+from selenium.webdriver.support.ui import WebDriverWait
+
+from ..script_loader import load_script
+from .utils import *
+
+"""
+How many test resources we're going to have.
+"""
+count = 15
+
+sample_files_list = [(f'file_{n}_{i}', f'contents {n} {i}')
+ for n in range(count) for i in range(2)]
+
+sample_files = dict(sample_files_list)
+
+sample_files, sample_files_by_sha256 = make_sample_files(sample_files)
+
+def make_sample_resource_with_deps(n):
+ resource = make_sample_resource(with_files=False)
+
+ resource['identifier'] = f'res-{n}'
+ resource['dependencies'] = [{'identifier': f'res-{m}'}
+ for m in range(max(n - 4, 0), n)]
+ resource['scripts'] = [sample_file_ref(f'file_{n}_{i}', sample_files)
+ for i in range(2)]
+
+ return resource
+
+resources = [make_sample_resource_with_deps(n) for n in range(count)]
+
+sample_data = {
+ 'resource': sample_data_dict(resources),
+ 'mapping': {},
+ 'file': {
+ 'sha256': sample_files_by_sha256
+ }
+}
+
+def prepare_test_page(initial_indexeddb_data, execute_in_page):
+ js = load_script('background/indexeddb_files_server.js',
+ code_to_add='#IMPORT common/broadcast.js')
+ execute_in_page(js)
+
+ mock_broadcast(execute_in_page)
+ clear_indexeddb(execute_in_page)
+
+ execute_in_page(
+ '''
+ let registered_listener;
+ const new_addListener = cb => registered_listener = cb;
+
+ browser = {runtime: {onMessage: {addListener: new_addListener}}};
+
+ haketilodb.save_items(arguments[0]);
+
+ start();
+ ''',
+ initial_indexeddb_data)
+
+@pytest.mark.get_page('https://gotmyowndoma.in')
+def test_indexeddb_files_server_normal_usage(driver, execute_in_page):
+ """
+ Test querying resource files (with resource dependency resolution)
+ from IndexedDB and serving them in messages to content scripts.
+ """
+ prepare_test_page(sample_data, execute_in_page)
+
+ # Verify other types of messages are ignored.
+ function_returned_value = execute_in_page(
+ '''
+ returnval(registered_listener(["???"], {},
+ () => location.reload()));
+ ''')
+ assert function_returned_value == None
+
+ # Verify single resource's files get properly resolved.
+ function_returned_value = execute_in_page(
+ '''
+ var result_cb, contents_prom = new Promise(cb => result_cb = cb);
+
+ returnval(registered_listener(["indexeddb_files", "res-0"],
+ {}, result_cb));
+ ''')
+ assert function_returned_value == True
+
+ assert execute_in_page('returnval(contents_prom);') == \
+ {'files': [tuple[1] for tuple in sample_files_list[0:2]]}
+
+ # Verify multiple resources' files get properly resolved.
+ function_returned_value = execute_in_page(
+ '''
+ var result_cb, contents_prom = new Promise(cb => result_cb = cb);
+
+ returnval(registered_listener(["indexeddb_files", arguments[0]],
+ {}, result_cb));
+ ''',
+ f'res-{count - 1}')
+ assert function_returned_value == True
+
+ assert execute_in_page('returnval(contents_prom);') == \
+ {'files': [tuple[1] for tuple in sample_files_list]}
+
+@pytest.mark.get_page('https://gotmyowndoma.in')
+@pytest.mark.parametrize('error', [
+ 'missing',
+ 'circular',
+ 'db',
+ 'other'
+])
+def test_indexeddb_files_server_errors(driver, execute_in_page, error):
+ """
+ Test reporting of errors when querying resource files (with resource
+ dependency resolution) from IndexedDB and serving them in messages to
+ content scripts.
+ """
+ sample_data_copy = copy.deepcopy(sample_data)
+
+ if error == 'missing':
+ del sample_data_copy['resource']['res-3']
+ elif error == 'circular':
+ res3_defs = sample_data_copy['resource']['res-3'].values()
+ next(iter(res3_defs))['dependencies'].append({'identifier': 'res-8'})
+
+ prepare_test_page(sample_data_copy, execute_in_page)
+
+ if error == 'db':
+ execute_in_page('haketilodb.idb_get = t => t.onerror("oooops");')
+ elif error == 'other':
+ execute_in_page('haketilodb.idb_get = () => {throw "oooops"};')
+
+ response = execute_in_page(
+ '''
+ var result_cb, contents_prom = new Promise(cb => result_cb = cb);
+
+ registered_listener(["indexeddb_files", arguments[0]],
+ {}, result_cb);
+
+ returnval(contents_prom);
+ ''',
+ f'res-{count - 1}')
+
+ assert response['error']['haketilo_error_type'] == error
+
+ if error == 'missing':
+ assert response['error']['id'] == 'res-3'
+ elif error == 'circular':
+ assert response['error']['id'] in ('res-3', 'res-8')
+ elif error not in ('db', 'other'):
+ raise Exception('made a typo in test function params?')