diff options
Diffstat (limited to 'test/unit/test_indexeddb.py')
-rw-r--r-- | test/unit/test_indexeddb.py | 193 |
1 files changed, 120 insertions, 73 deletions
diff --git a/test/unit/test_indexeddb.py b/test/unit/test_indexeddb.py index 476690c..df3df81 100644 --- a/test/unit/test_indexeddb.py +++ b/test/unit/test_indexeddb.py @@ -75,26 +75,9 @@ def make_sample_mapping(): def file_ref(file_name): return {'file': file_name, 'hash_key': sample_files[file_name]['hash_key']} -@pytest.mark.get_page('https://gotmyowndoma.in') -def test_haketilodb_save_remove(execute_in_page): - """ - indexeddb.js facilitates operating on Haketilo's internal database. - Verify database operations work properly. - """ - execute_in_page(indexeddb_js()) - # Mock some unwanted imports. +def clear_indexeddb(execute_in_page): execute_in_page( '''{ - const broadcast_mock = {}; - const nop = () => {}; - for (const key in broadcast) - broadcast_mock[key] = nop; - broadcast = broadcast_mock; - }''') - - # Start with no database. - execute_in_page( - ''' async function delete_db() { if (db) { db.close(); @@ -108,12 +91,13 @@ def test_haketilodb_save_remove(execute_in_page): } returnval(delete_db()); - ''' + }''' ) +def get_db_contents(execute_in_page): # Facilitate retrieving all IndexedDB contents. - execute_in_page( - ''' + return execute_in_page( + '''{ async function get_database_contents() { const db = await get_db(); @@ -130,20 +114,45 @@ def test_haketilodb_save_remove(execute_in_page): store_names_reqs.forEach(([sn, req]) => result[sn] = req.result); return result; } - ''') + returnval(get_database_contents()); + }''') + +def mock_broadcast(execute_in_page): + execute_in_page( + '''{ + const broadcast_mock = {}; + const nop = () => {}; + for (const key in broadcast) + broadcast_mock[key] = nop; + broadcast = broadcast_mock; + }''') + +@pytest.mark.get_page('https://gotmyowndoma.in') +def test_haketilodb_item_modifications(driver, execute_in_page): + """ + indexeddb.js facilitates operating on Haketilo's internal database. + Verify database operations on mappings/resources work properly. + """ + execute_in_page(indexeddb_js()) + mock_broadcast(execute_in_page) + + # Start with no database. + clear_indexeddb(execute_in_page) sample_item = make_sample_resource() sample_item['source_copyright'][0]['extra_prop'] = True - database_contents = execute_in_page( + execute_in_page( '''{ const promise = start_items_transaction(["resources"], arguments[1]) .then(ctx => save_item(arguments[0], ctx).then(() => ctx)) - .then(finalize_items_transaction) - .then(get_database_contents); + .then(finalize_transaction); returnval(promise); }''', sample_item, sample_files_by_hash) + + database_contents = get_db_contents(execute_in_page) + assert len(database_contents['files']) == 4 assert all([sample_files_by_hash[file['hash_key']] == file['contents'] for file in database_contents['files']]) @@ -162,31 +171,33 @@ def test_haketilodb_save_remove(execute_in_page): sample_item['scripts'].append(file_ref('combined.js')) incomplete_files = {**sample_files_by_hash} incomplete_files.pop(sample_files['combined.js']['hash_key']) - result = execute_in_page( + exception = execute_in_page( '''{ - const promise = (async () => { + const args = arguments; + async function try_add_item() + { const context = - await start_items_transaction(["resources"], arguments[1]); + await start_items_transaction(["resources"], args[1]); try { - await save_item(arguments[0], context); - await finalize_items_transaction(context); - return {}; + await save_item(args[0], context); + await finalize_transaction(context); + return; } catch(e) { - var exception = e; + return e; } - - return {exception, db_contents: await get_database_contents()}; - })(); - returnval(promise); + } + returnval(try_add_item()); }''', sample_item, incomplete_files) - assert result - assert 'file not present' in result['exception'] + previous_database_contents = database_contents + database_contents = get_db_contents(execute_in_page) + + assert 'file not present' in exception for key, val in database_contents.items(): keyfun = lambda item: item.get('hash_key') or item['identifier'] - assert sorted(result['db_contents'][key], key=keyfun) \ - == sorted(val, key=keyfun) + assert sorted(previous_database_contents[key], key=keyfun) \ + == sorted(val, key=keyfun) # See if adding another item that partially uses first's files works OK. sample_item = make_sample_mapping() @@ -194,12 +205,13 @@ def test_haketilodb_save_remove(execute_in_page): '''{ const promise = start_items_transaction(["mappings"], arguments[1]) .then(ctx => save_item(arguments[0], ctx).then(() => ctx)) - .then(finalize_items_transaction) - .then(get_database_contents); + .then(finalize_transaction); returnval(promise); }''', sample_item, sample_files_by_hash) + database_contents = get_db_contents(execute_in_page) + names = ['README.md', 'report.spdx', 'LICENSES/somelicense.txt', 'hello.js', 'bye.js'] sample_files_list = [sample_files[name] for name in names] @@ -222,17 +234,18 @@ def test_haketilodb_save_remove(execute_in_page): # Try removing the items to get an empty database again. results = [None, None] for i, item_type in enumerate(['resource', 'mapping']): - results[i] = execute_in_page( + execute_in_page( f'''{{ const remover = remove_{item_type}; const promise = start_items_transaction(["{item_type}s"], {{}}) .then(ctx => remover('helloapple', ctx).then(() => ctx)) - .then(finalize_items_transaction) - .then(get_database_contents); + .then(finalize_transaction); returnval(promise); }}''') + results[i] = get_db_contents(execute_in_page) + names = ['README.md', 'report.spdx'] sample_files_list = [sample_files[name] for name in names] uses_list = [1, 1] @@ -271,22 +284,48 @@ def test_haketilodb_save_remove(execute_in_page): }, 'files': sample_files_by_hash } - database_contents = execute_in_page( - ''' - initial_data = arguments[0]; - returnval(delete_db().then(() => get_database_contents())); - ''', - initial_data) + + clear_indexeddb(execute_in_page) + execute_in_page('initial_data = arguments[0];', initial_data) + database_contents = get_db_contents(execute_in_page) + assert database_contents['resources'] == [sample_resource] assert database_contents['mappings'] == [sample_mapping] +@pytest.mark.get_page('https://gotmyowndoma.in') +def test_haketilodb_settings(driver, execute_in_page): + """ + indexeddb.js facilitates operating on Haketilo's internal database. + Verify database assigning/retrieving values of simple "settings" works + properly. + """ + execute_in_page(indexeddb_js()) + mock_broadcast(execute_in_page) + + # Start with no database. + clear_indexeddb(execute_in_page) + + assert get_db_contents(execute_in_page)['settings'] == [] + + assert execute_in_page('returnval(get_setting("option15"));') == None + + execute_in_page('returnval(set_setting("option15", "disable"));') + assert execute_in_page('returnval(get_setting("option15"));') == 'disable' + + execute_in_page('returnval(set_setting("option15", "enable"));') + assert execute_in_page('returnval(get_setting("option15"));') == 'enable' + test_page_html = ''' <!DOCTYPE html> <script src="/testpage.js"></script> +<script>console.log("inline!")</script> +<script nonce="123456789">console.log("inline nonce!")</script> <h2>resources</h2> <ul id="resources"></ul> <h2>mappings</h2> <ul id="mappings"></ul> +<h2>settings</h2> +<ul id="settings"></ul> ''' @pytest.mark.ext_data({ @@ -328,15 +367,21 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text): } for window in reversed(windows): driver.switch_to.window(window) - execute_in_page('initial_data = arguments[0];', initial_data) - - # See if track_*() functions properly return the already-existing items. + try : + driver.execute_script('console.log("uuuuuuu");') + execute_in_page('initial_data = arguments[0];', initial_data) + except: + from time import sleep + sleep(100000) + execute_in_page('returnval(set_setting("option15", "123"));') + + # See if track.*() functions properly return the already-existing items. execute_in_page( ''' function update_item(store_name, change) { console.log('update', ...arguments); - const elem_id = `${store_name}_${change.identifier}`; + const elem_id = `${store_name}_${change.key}`; let elem = document.getElementById(elem_id); elem = elem || document.createElement("li"); elem.id = elem_id; @@ -348,35 +393,32 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text): let resource_tracking, resource_items, mapping_tracking, mapping_items; - async function start_tracking() + async function start_reporting() { - const update_resource = change => update_item("resources", change); - const update_mapping = change => update_item("mappings", change); - - [resource_tracking, resource_items] = - await track_resources(update_resource); - [mapping_tracking, mapping_items] = - await track_mappings(update_mapping); - - for (const item of resource_items) - update_resource({identifier: item.identifier, new_val: item}); - for (const item of mapping_items) - update_mapping({identifier: item.identifier, new_val: item}); + for (const store_name of ["resources", "mappings", "settings"]) { + [tracking, items] = + await track[store_name](ch => update_item(store_name, ch)); + const prop = store_name === "settings" ? "name" : "identifier"; + for (const item of items) + update_item(store_name, {key: item[prop], new_val: item}); + } } - returnval(start_tracking()); + returnval(start_reporting()); ''') item_counts = driver.execute_script( ''' const childcount = id => document.getElementById(id).childElementCount; - return ["resources", "mappings"].map(childcount); + return ["resources", "mappings", "settings"].map(childcount); ''') - assert item_counts == [1, 1] + assert item_counts == [1, 1, 1] resource_json = driver.find_element_by_id('resources_helloapple').text mapping_json = driver.find_element_by_id('mappings_helloapple').text + setting_json = driver.find_element_by_id('settings_option15').text assert json.loads(resource_json) == sample_resource assert json.loads(mapping_json) == sample_mapping + assert json.loads(setting_json) == {'name': 'option15', 'value': '123'} # See if item additions get tracked properly. driver.switch_to.window(windows[1]) @@ -398,14 +440,17 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text): 'files': sample_files_by_hash } execute_in_page('returnval(save_items(arguments[0]));', sample_data) + execute_in_page('returnval(set_setting("option22", "abc"));') driver.switch_to.window(windows[0]) driver.implicitly_wait(10) resource_json = driver.find_element_by_id('resources_helloapple-copy').text mapping_json = driver.find_element_by_id('mappings_helloapple-copy').text + setting_json = driver.find_element_by_id('settings_option22').text driver.implicitly_wait(0) assert json.loads(resource_json) == sample_resource2 assert json.loads(mapping_json) == sample_mapping2 + assert json.loads(setting_json) == {'name': 'option22', 'value': 'abc'} # See if item deletions get tracked properly. driver.switch_to.window(windows[1]) @@ -417,7 +462,8 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text): const ctx = await start_items_transaction(store_names, {}); await remove_resource("helloapple", ctx); await remove_mapping("helloapple-copy", ctx); - await finalize_items_transaction(ctx); + await finalize_transaction(ctx); + await set_setting("option22", null); } returnval(remove_items()); }''') @@ -430,7 +476,8 @@ def test_haketilodb_track(driver, execute_in_page, wait_elem_text): return False except WebDriverException: pass - return True + option_text = driver.find_element_by_id('settings_option22').text + return json.loads(option_text)['value'] == None driver.switch_to.window(windows[0]) WebDriverWait(driver, 10).until(condition_items_absent) |