# SPDX-License-Identifier: CC0-1.0 """ Haketilo unit tests - IndexedDB access """ # This file is part of Haketilo # # Copyright (C) 2021, Wojtek Kosior # # 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(''), '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]