diff options
-rw-r--r-- | common/indexeddb.js | 43 | ||||
-rw-r--r-- | default_settings.json | 2 | ||||
-rw-r--r-- | test/haketilo_test/test_integration.py | 2 | ||||
-rw-r--r-- | test/haketilo_test/unit/test_indexeddb.py | 44 |
4 files changed, 78 insertions, 13 deletions
diff --git a/common/indexeddb.js b/common/indexeddb.js index bd87399..d83e605 100644 --- a/common/indexeddb.js +++ b/common/indexeddb.js @@ -53,11 +53,13 @@ let initial_data = ( ); /* Update when changes are made to database schema. Must have 3 elements */ -const db_version = [1, 0, 0]; +const db_version = [1, 0, 1]; const nr_reductor = ([i, s], num) => [i - 1, s + num * 1024 ** i]; const version_nr = ver => ver.slice(0, 3).reduce(nr_reductor, [2, 0])[1]; +let db_version_nr = version_nr(db_version); + const stores = [ ["file", {keyPath: "sha256"}], ["file_uses", {keyPath: "sha256"}], @@ -100,19 +102,38 @@ async function idb_del(transaction, store_name, key) } async function perform_upgrade(event) { + if (event.oldVersion > db_version_nr) + throw "bad db version: " + event.oldVersion; + const opened_db = event.target.result; + const transaction = event.target.transaction; - /* When we move to a new database schema, we will add upgrade logic here. */ - if (event.oldVersion > 0) - throw "bad db version: " + event.oldVersion; + if (event.oldVersion == 0) { + for (const [store_name, key_mode] of stores) + opened_db.createObjectStore(store_name, key_mode); + } - let store; - for (const [store_name, key_mode] of stores) - store = opened_db.createObjectStore(store_name, key_mode); + if (event.oldVersion > 0 && event.oldVersion < db_version_nr) { + const v1_url = "https://hydrilla.koszko.org/api_v1/"; + const v1_entry = await idb_get(transaction, "repo", v1_url); - const ctx = make_context(store.transaction, initial_data.file); - await _save_items(initial_data.resource, initial_data.mapping, - initial_data.repo || [], ctx); + if (v1_entry) { + const v2_url = "https://hydrilla.koszko.org/api_v2/"; + + await idb_del(transaction, "repo", v1_url); + await idb_put(transaction, "repo", {url: v2_url}); + } + } + + if (event.oldVersion == 0) { + const ctx = make_context(transaction, initial_data.file); + await _save_items(initial_data.resource, initial_data.mapping, + initial_data.repo || [], ctx); + } else { + await new Promise( + (...cbs) => [transaction.onsuccess, transaction.onerror] = cbs + ); + } return opened_db; } @@ -125,7 +146,7 @@ async function get_db() { let resolve, reject; const waiter = new Promise((...cbs) => [resolve, reject] = cbs); - const request = indexedDB.open("haketilo", version_nr(db_version)); + const request = indexedDB.open("haketilo", db_version_nr); request.onsuccess = ev => resolve(ev.target.result); request.onerror = ev => reject("db error: " + ev.target.errorCode); request.onupgradeneeded = ev => perform_upgrade(ev).then(resolve, reject); diff --git a/default_settings.json b/default_settings.json index 647b0a7..a9a09dc 100644 --- a/default_settings.json +++ b/default_settings.json @@ -74,5 +74,5 @@ "f1d9dc9f2f4edaaebd9167eb8b79a6da6434313df47921aa4ea8ae278f7739e3": "/**\n * Haketilo demo script.\n *\n * Copyright (C) 2021 Wojtek Kosior\n * Available under the terms of Creative Commons Zero\n * <https://creativecommons.org/publicdomain/zero/1.0/legalcode>\n */\n\n{\n const banner = document.createElement(\"h2\");\n \n banner.textContent = \"Hoooray! Haketilo works :D\";\n \n banner.setAttribute(\"style\", `\\\n margin: 1em; \\\n border-radius: 1em 0px; \\\n background-color: #474; \\\n padding: 10px 20px; \\\n color: #eee; \\\n box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); \\\n display: inline-block;\\\n `);\n \n document.body.prepend(banner);\n}\n" } }, - "repo": ["https://hydrilla.koszko.org/api_v1/"] + "repo": ["https://hydrilla.koszko.org/api_v2/"] } diff --git a/test/haketilo_test/test_integration.py b/test/haketilo_test/test_integration.py index b77afbd..88fef3c 100644 --- a/test/haketilo_test/test_integration.py +++ b/test/haketilo_test/test_integration.py @@ -48,7 +48,7 @@ def test_integration(driver): driver.find_element_by_id('repos_head').click() lst = driver.find_element_by_css_selector('.active_tab .text_entries') - assert 'https://hydrilla.koszko.org/api_v1' in lst.text + assert 'https://hydrilla.koszko.org/api_v2' in lst.text # TODO: do some more tests, including popup interaction and repository # querying diff --git a/test/haketilo_test/unit/test_indexeddb.py b/test/haketilo_test/unit/test_indexeddb.py index 773f5c8..ff1b265 100644 --- a/test/haketilo_test/unit/test_indexeddb.py +++ b/test/haketilo_test/unit/test_indexeddb.py @@ -51,6 +51,50 @@ def make_sample_mapping(): } @pytest.mark.get_page('https://gotmyowndoma.in') +def test_haketilodb_update_1_0_1(driver, execute_in_page): + """ + indexeddb.js modifies data when updating to database version 1.0.1. Verify + the update procedure works properly. + """ + execute_in_page(load_script('common/indexeddb.js')) + execute_in_page('db_version_nr = version_nr([1, 0, 0]);') + mock_broadcast(execute_in_page) + + # Start with no database. + clear_indexeddb(execute_in_page) + + v1_url = 'https://hydrilla.koszko.org/api_v1/' + v2_url = 'https://hydrilla.koszko.org/api_v2/' + urls_v1 = {'https://sample.url/abc/', v1_url} + urls_v2 = {'https://sample.url/abc/', v2_url} + + for url in urls_v1: + execute_in_page('returnval(set_repo(arguments[0]));', url) + + assert urls_v1 == set(execute_in_page('returnval(get_repos());')) + + # Verify that url gets updated to v2 upon database update. + driver.get(driver.execute_script('return window.location.href;')) + execute_in_page(load_script('common/indexeddb.js')) + mock_broadcast(execute_in_page) + + database_contents = get_db_contents(execute_in_page) + + assert set(execute_in_page('returnval(get_repos());')) == urls_v2 + + # Verify that url does not get updated when there is no database update. + execute_in_page('returnval(del_repo(arguments[0]));', v2_url) + execute_in_page('returnval(set_repo(arguments[0]));', v1_url) + + driver.get(driver.execute_script('return window.location.href;')) + execute_in_page(load_script('common/indexeddb.js')) + mock_broadcast(execute_in_page) + + database_contents = get_db_contents(execute_in_page) + + assert set(execute_in_page('returnval(get_repos());')) == urls_v1 + +@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. |