diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/script_loader.py | 7 | ||||
-rw-r--r-- | test/unit/test_indexeddb.py | 134 |
2 files changed, 140 insertions, 1 deletions
diff --git a/test/script_loader.py b/test/script_loader.py index 15269c7..8f30944 100644 --- a/test/script_loader.py +++ b/test/script_loader.py @@ -51,7 +51,12 @@ def available_scripts(directory): def wrapped_script(script_path, wrap_partially=True): if script_path == 'exports_init.js': - with open(script_root / 'MOZILLA_exports_init.js') as script: + if not (script_root / 'exports_init.js').exists(): + subprocess.run([str(script_root / 'write_exports_init.sh'), + 'mozilla', '.', 'default_settings.json'], + cwd=script_root, check=True) + + with open(script_root / 'exports_init.js') as script: return script.read() command = 'partially_wrapped_code' if wrap_partially else 'wrapped_code' 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] |