summaryrefslogtreecommitdiff
path: root/test/unit/test_indexeddb.py
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2021-12-08 19:01:50 +0100
committerWojtek Kosior <koszko@koszko.org>2021-12-08 19:01:50 +0100
commit3a90084ec14a15d9b76fa4bfed9e85f15a09dad7 (patch)
tree0e588240ff95f47c4387a82d1dcc59bda2a8d79a /test/unit/test_indexeddb.py
parentc8fa3926b9ae2f837fcd6950e10e0852d89c4120 (diff)
downloadbrowser-extension-3a90084ec14a15d9b76fa4bfed9e85f15a09dad7.tar.gz
browser-extension-3a90084ec14a15d9b76fa4bfed9e85f15a09dad7.zip
facilitate initialization of IndexedDB for use by Haketilo
Diffstat (limited to 'test/unit/test_indexeddb.py')
-rw-r--r--test/unit/test_indexeddb.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/test/unit/test_indexeddb.py b/test/unit/test_indexeddb.py
new file mode 100644
index 0000000..e5e1626
--- /dev/null
+++ b/test/unit/test_indexeddb.py
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: CC0-1.0
+
+"""
+Haketilo unit tests - IndexedDB access
+"""
+
+# 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 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
+from hashlib import sha256
+
+from ..script_loader import load_script
+
+@pytest.fixture(scope="session")
+def indexeddb_code():
+ yield load_script('common/indexeddb.js', ['common'])
+
+def sample_file(contents):
+ return {
+ 'sha256': sha256(contents.encode()).digest().hex(),
+ contents: contents
+ }
+
+sample_files = {
+ 'report.spdx': sample_file('<!-- dummy report -->'),
+ 'LICENSES/somelicense.txt': sample_file('Permission is granted...'),
+ 'hello.js': sample_file('console.log("hello!");\n'),
+ 'bye.js': sample_file('console.log("bye!");\n'),
+ 'README.md': sample_file('# Python Frobnicator\n...')
+}
+
+sample_files_sha256 = \
+ dict([[file['sha256'], file] for file in sample_files.values()])
+
+def file_ref(file_name):
+ return {'file': file_name, 'sha256': sample_files[file_name]['sha256']}
+
+def test_save_item(execute_in_page, indexeddb_code):
+ """
+ indexeddb.js facilitates operating on Haketilo's internal database.
+ Verify database operations work properly.
+ """
+ execute_in_page(indexeddb_code, page='https://gotmyowndoma.in')
+ # Don't use Haketilo's default initial data.
+ execute_in_page(
+ '''{
+ const _get_db = haketilodb.get;
+ get_db = () => _get_db({});
+ haketilodb.get = get_db;
+ }'''
+ )
+
+ # Start with no database.
+ execute_in_page(
+ '''{
+ async function delete_db() {
+ let resolve;
+ const result = new Promise(_resolve => resolve = _resolve);
+ const request = indexedDB.deleteDatabase("haketilo");
+ [request.onsuccess, request.onerror] = [resolve, resolve];
+ await result;
+ }
+
+ returnval(delete_db());
+ }'''
+ )
+
+ # Facilitate retrieving all IndexedDB contents.
+ execute_in_page(
+ '''
+ async function get_database_contents(promise=Promise.resolve())
+ {
+ if (promise)
+ await promise;
+
+ const db = await haketilodb.get();
+
+ const transaction = db.transaction(db.objectStoreNames);
+ const store_names_reqs = [...db.objectStoreNames]
+ .map(sn => [sn, transaction.objectStore(sn).getAll()])
+
+ const promises = store_names_reqs
+ .map(([_, req]) => wait_request(req));
+ await Promise.all(promises);
+
+ const result = {};
+ store_names_reqs.forEach(([sn, req]) => result[sn] = req.result);
+ return result;
+ }
+ ''')
+
+ # Sample resource definition. It'd normally contain more fields but here
+ # we use a simplified version.
+ sample_item = {
+ 'source_copyright': [
+ file_ref('report.spdx'),
+ file_ref('LICENSES/somelicense.txt')
+ ],
+ 'type': 'resource',
+ 'identifier': 'helloapple',
+ 'scripts': [file_ref('hello.js'), file_ref('bye.js')],
+ 'type': 'resource'
+ }
+ next(iter(sample_item['source_copyright']))['ugly_extra_property'] = True
+
+ database_contents = execute_in_page(
+ '''{
+ const prom = haketilodb.get().then(db => save_item(...arguments, db));
+ returnval(get_database_contents(prom));
+ }''',
+ sample_item, sample_files_sha256)
+ assert len(database_contents['files']) == 4
+ assert all([sample_files_sha256[file['sha256']] == file['contents']
+ for file in database_contents['files']])
+ assert all([len(file) == 2 for file in database_contents['files']])
+
+ assert len(database_contents['file_uses']) == 4
+ assert all([uses['uses'] == 1 for uses in database_contents['file_uses']])
+ assert set([uses['sha256'] for uses in database_contents['file_uses']]) \
+ == set([file['sha256'] for file in database_contents['files']])
+
+ assert database_contents['mappings'] == []
+ assert database_contents['resources'] == [sample_item]