aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-02-16 00:55:04 +0100
committerWojtek Kosior <koszko@koszko.org>2022-02-16 10:12:51 +0100
commit72553a2d8b5fa094a5edd5e6ec15b5125a052016 (patch)
treecfbca085fd54ce482561e65726f825c00b2ac795
parentb47de554fb01b478b09d9d65b5eac4b05fd903fc (diff)
downloadbrowser-extension-72553a2d8b5fa094a5edd5e6ec15b5125a052016.tar.gz
browser-extension-72553a2d8b5fa094a5edd5e6ec15b5125a052016.zip
assume and use "$schema" properties in item definitions
-rw-r--r--common/entities.js11
-rw-r--r--default_settings.json2
-rw-r--r--html/install.js37
-rw-r--r--html/item_preview.html4
-rw-r--r--html/item_preview.js12
-rw-r--r--html/repo_query.html8
-rw-r--r--html/repo_query.js28
-rw-r--r--test/unit/test_install.py14
-rw-r--r--test/unit/test_repo_query.py30
-rw-r--r--test/unit/utils.py10
-rw-r--r--test/world_wide_library.py13
11 files changed, 96 insertions, 73 deletions
diff --git a/common/entities.js b/common/entities.js
index 96de5cb..74cad20 100644
--- a/common/entities.js
+++ b/common/entities.js
@@ -101,17 +101,6 @@ function get_newest_version(versioned_item)
#EXPORT get_newest_version AS get_newest
/*
- * Returns true if the argument is a nonempty array of numbers without trailing
- * zeros.
- */
-function is_valid_version(version) {
- return Array.isArray(version) && version.length > 0 &&
- version.every(n => typeof n === "number") &&
- version[version.length - 1] !== 0;
-}
-#EXPORT is_valid_version
-
-/*
* item is a definition of a resource or mapping. Yield all file references
* (objects with `file` and `sha256` properties) this definition has.
*/
diff --git a/default_settings.json b/default_settings.json
index a187c46..647b0a7 100644
--- a/default_settings.json
+++ b/default_settings.json
@@ -24,6 +24,7 @@
"resource": {
"haketilo-demo-script": {
"2022.1.28": {
+ "$schema": "https://hydrilla.koszko.org/schemas/api_resource_description-1.schema.json",
"source_name": "haketilo-default-settings",
"source_copyright": [{
"file": "CC0-1.0.txt",
@@ -47,6 +48,7 @@
"mapping": {
"haketilo-demo-message": {
"2022.1.28": {
+ "$schema": "https://hydrilla.koszko.org/schemas/api_mapping_description-1.schema.json",
"source_name": "haketilo-default-settings",
"source_copyright": [{
"file": "CC0-1.0.txt",
diff --git a/html/install.js b/html/install.js
index 2a72662..7b3f3fe 100644
--- a/html/install.js
+++ b/html/install.js
@@ -47,8 +47,7 @@
#FROM common/browser.js IMPORT browser
#FROM html/DOM_helpers.js IMPORT clone_template, Showable
-#FROM common/entities.js IMPORT item_id_string, version_string, get_files, \
- is_valid_version
+#FROM common/entities.js IMPORT item_id_string, version_string, get_files
#FROM common/misc.js IMPORT sha256_async AS compute_sha256
const coll = new Intl.Collator();
@@ -114,6 +113,19 @@ async function init_work() {
new Promise((...cbs) => [work.resolve_cb, work.reject_cb] = cbs)];
}
+function _make_url_reg(item_type) {
+ return new RegExp(
+ `^https://hydrilla\\.koszko\\.org/schemas/api_${item_type}_description-1\\.([1-9][0-9]*\\.)*schema\\.json$`
+ );
+}
+
+const _regexes = {};
+
+function item_schema_url_regex(item_type) {
+ _regexes[item_type] = _regexes[item_type] || _make_url_reg(item_type);
+ return _regexes[item_type];
+}
+
function InstallView(tab_id, on_view_show, on_view_hide) {
Showable.call(this, on_view_show, on_view_hide);
@@ -191,26 +203,19 @@ function InstallView(tab_id, on_view_show, on_view_hide) {
"Repository's response is not valid JSON :(");
}
- if (!is_valid_version(response.json.api_schema_version)) {
- var bad_api_ver = "";
- } else if (response.json.api_schema_version > [1]) {
- var bad_api_ver =
- ` (${version_string(response.json.api_schema_version)})`;
- } else {
- var bad_api_ver = false;
- }
+ const captype = item_type[0].toUpperCase() + item_type.substring(1);
+ const reg = item_schema_url_regex(item_type);
- if (bad_api_ver !== false) {
- const captype = item_type[0].toUpperCase() + item_type.substring(1);
- const msg = `${captype} ${item_id_string(id, ver)} was served using unsupported Hydrilla API version${bad_api_ver}. You might need to update Haketilo.`;
+ if (!response.json["$schema"]) {
+ const msg = `${captype} ${item_id_string(id, ver)} was served using a nonconforming response format.`;
+ return work.err(null, msg);
+ } else if (!reg.test(response.json["$schema"])) {
+ const msg = `${captype} ${item_id_string(id, ver)} was served using unsupported Hydrilla API version. You might need to update Haketilo.`;
return work.err(null, msg);
}
/* TODO: JSON schema validation should be added here. */
- delete response.json.api_schema_version;
- delete response.json.api_schema_revision;
-
const scripts = item_type === "resource" && response.json.scripts;
const files = response.json.source_copyright.concat(scripts || []);
diff --git a/html/item_preview.html b/html/item_preview.html
index 34ce6e1..356ee62 100644
--- a/html/item_preview.html
+++ b/html/item_preview.html
@@ -46,6 +46,8 @@
<div id="resource_preview" data-template="main_div"
class="grid_2 grid_form item_preview_main_div">
<h3 class="grid_col_both">resource preview</h3>
+ <label class="grid_col_1">conforms to:</label>
+ <span data-template="conforms_to" class="grid_col_2">...</span>
<label class="grid_col_1">identifier:</label>
<span data-template="identifier" class="grid_col_2">...</span>
<label class="grid_col_1">long name:</label>
@@ -68,6 +70,8 @@
<div id="mapping_preview" data-template="main_div"
class="grid_2 grid_form">
<h3 class="grid_col_both">mapping preview</h3>
+ <label class="grid_col_1">conforms to:</label>
+ <span data-template="conforms_to" class="grid_col_2">...</span>
<label class="grid_col_1">identifier:</label>
<span data-template="identifier" class="grid_col_2">...</span>
<label class="grid_col_1">long name:</label>
diff --git a/html/item_preview.js b/html/item_preview.js
index 1da9492..b67455a 100644
--- a/html/item_preview.js
+++ b/html/item_preview.js
@@ -73,6 +73,12 @@ function resource_preview(resource, preview_object, link_cb=make_file_link) {
if (preview_object === undefined)
preview_object = clone_template("resource_preview");
+ preview_object.conforms_to.innerHTML = "";
+ const schema_link = document.createElement("a");
+ schema_link.href = resource.$schema;
+ schema_link.innerText = resource.$schema;
+ preview_object.conforms_to.append(schema_link);
+
preview_object.identifier.innerText = resource.identifier;
preview_object.long_name.innerText = resource.long_name;
preview_object.uuid.innerText = resource.uuid;
@@ -104,6 +110,12 @@ function mapping_preview(mapping, preview_object, link_cb=make_file_link) {
if (preview_object === undefined)
preview_object = clone_template("mapping_preview");
+ preview_object.conforms_to.innerHTML = "";
+ const schema_link = document.createElement("a");
+ schema_link.href = mapping.$schema;
+ schema_link.innerText = mapping.$schema;
+ preview_object.conforms_to.append(schema_link);
+
preview_object.identifier.innerText = mapping.identifier;
preview_object.long_name.innerText = mapping.long_name;
preview_object.uuid.innerText = mapping.uuid;
diff --git a/html/repo_query.html b/html/repo_query.html
index b9c9269..67158cc 100644
--- a/html/repo_query.html
+++ b/html/repo_query.html
@@ -61,6 +61,10 @@
background-color: #f0f0f0;
}
+ .repo_query_info_div {
+ margin: 0.5em;
+ }
+
.repo_query_result_li {
margin: 0;
padding: 0.2em;
@@ -134,7 +138,9 @@
</span>
</div>
<div data-template="list_container" class="hide repo_query_results_list">
- <span data-template="info_span">Querying repository...</span>
+ <div data-template="info_div" class="repo_query_info_div">
+ Querying repository...
+ </div>
<ul data-template="results_list" class="hide"></ul>
</div>
</li>
diff --git a/html/repo_query.js b/html/repo_query.js
index a4b8890..d2f0e9b 100644
--- a/html/repo_query.js
+++ b/html/repo_query.js
@@ -45,8 +45,7 @@
#FROM common/browser.js IMPORT browser
#FROM html/DOM_helpers.js IMPORT clone_template, Showable
-#FROM common/entities.js IMPORT item_id_string, version_string, \
- is_valid_version
+#FROM common/entities.js IMPORT item_id_string, version_string
#FROM html/install.js IMPORT InstallView
const coll = new Intl.Collator();
@@ -69,6 +68,10 @@ function ResultEntry(repo_entry, mapping_ref) {
this.install_but.addEventListener("click", cb);
}
+const query_schema_url_regex = new RegExp(
+ "^https://hydrilla\\.koszko\\.org/schemas/api_query_result-1\\.([1-9][0-9]*\\.)*schema\\.json$"
+);
+
function RepoEntry(query_view, repo_url) {
Object.assign(this, clone_template("repo_query_single_repo"));
Object.assign(this, {query_view, repo_url});
@@ -91,17 +94,10 @@ function RepoEntry(query_view, repo_url) {
if ("error_json" in response)
throw "Repository's response is not valid JSON :(";
- if (!is_valid_version(response.json.api_schema_version)) {
- var bad_api_ver = "";
- } else if (response.json.api_schema_version > [1]) {
- var bad_api_ver =
- ` (${version_string(response.json.api_schema_version)})`;
- } else {
- var bad_api_ver = false;
- }
-
- if (bad_api_ver !== false)
- throw `Results were served using unsupported Hydrilla API version${bad_api_ver}. You might need to update Haketilo.`;
+ if (!response.json["$schema"])
+ throw "Results were served using a nonconforming response format.";
+ if (!query_schema_url_regex.test(response.json["$schema"]))
+ throw "Results were served using unsupported Hydrilla API version. You might need to update Haketilo.";
/* TODO: here we should perform JSON schema validation! */
@@ -114,7 +110,7 @@ function RepoEntry(query_view, repo_url) {
try {
var results = await query_results();
} catch(e) {
- this.info_span.innerText = e;
+ this.info_div.innerText = e;
return;
}
@@ -122,12 +118,12 @@ function RepoEntry(query_view, repo_url) {
if (this.result_entries.length > 0) {
this.results_list.classList.remove("hide");
- this.info_span.remove();
+ this.info_div.remove();
const to_append = this.result_entries.map(re => re.main_li);
this.results_list.append(...to_append);
} else {
- this.info_span.innerText = "No results :(";
+ this.info_div.innerText = "No results :(";
}
}
diff --git a/test/unit/test_install.py b/test/unit/test_install.py
index cef2aa6..f4bc483 100644
--- a/test/unit/test_install.py
+++ b/test/unit/test_install.py
@@ -197,7 +197,7 @@ def test_install_normal_usage(driver, execute_in_page, complex_variant):
'HTTP_code_item',
'invalid_JSON',
'newer_API_version',
- 'invalid_API_version',
+ 'invalid_response_format',
'indexeddb_error_item',
'installing',
'indexeddb_error_file_uses',
@@ -285,7 +285,7 @@ def test_install_dialogs(driver, execute_in_page, message):
const response = {
ok: true,
status: 200,
- json: {api_schema_version: [99, 99]}
+ json: {$schema: "https://hydrilla.koszko.org/schemas/api_mapping_description-2.1.schema.json"}
};
browser.tabs.sendMessage = () => Promise.resolve(response);
install_view.show(...arguments);
@@ -293,15 +293,15 @@ def test_install_dialogs(driver, execute_in_page, message):
'https://hydril.la/', 'mapping', 'somemapping', [2, 1])
assert_dlg(['conf_buts'],
- 'Mapping somemapping-2.1 was served using unsupported Hydrilla API version (99.99). You might need to update Haketilo.')
- elif message == 'invalid_API_version':
+ 'Mapping somemapping-2.1 was served using unsupported Hydrilla API version. You might need to update Haketilo.')
+ elif message == 'invalid_response_format':
execute_in_page(
'''
const response = {
ok: true,
status: 200,
- /* API version here is not an array as it should be. */
- json: {api_schema_version: 123}
+ /* $schema is not a string as it should be. */
+ json: {$schema: null}
};
browser.tabs.sendMessage = () => Promise.resolve(response);
install_view.show(...arguments);
@@ -309,7 +309,7 @@ def test_install_dialogs(driver, execute_in_page, message):
'https://hydril.la/', 'resource', 'someresource')
assert_dlg(['conf_buts'],
- 'Resource someresource was served using unsupported Hydrilla API version. You might need to update Haketilo.')
+ 'Resource someresource was served using a nonconforming response format.')
elif message == 'indexeddb_error_item':
execute_in_page(
'''
diff --git a/test/unit/test_repo_query.py b/test/unit/test_repo_query.py
index 77c5e75..c8c4875 100644
--- a/test/unit/test_repo_query.py
+++ b/test/unit/test_repo_query.py
@@ -137,7 +137,7 @@ def test_repo_query_normal_usage(driver, execute_in_page):
'HTTP_code',
'invalid_JSON',
'newer_API_version',
- 'invalid_API_version',
+ 'invalid_response_format',
'querying_repo',
'no_results'
])
@@ -183,7 +183,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
)
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
done = has_msg('Failure to communicate with repository :(', elem)
WebDriverWait(driver, 10).until(done)
elif message == 'HTTP_code':
@@ -195,7 +195,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
''')
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
done = has_msg('Repository sent HTTP code 405 :(', elem)
WebDriverWait(driver, 10).until(done)
elif message == 'invalid_JSON':
@@ -207,7 +207,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
''')
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
done = has_msg("Repository's response is not valid JSON :(", elem)
WebDriverWait(driver, 10).until(done)
elif message == 'newer_API_version':
@@ -217,30 +217,31 @@ def test_repo_query_messages(driver, execute_in_page, message):
const response = {
ok: true,
status: 200,
- json: {api_schema_version: [1234]}
+ json: {$schema: "https://hydrilla.koszko.org/schemas/api_query_result-3.2.1.schema.json"}
};
browser.tabs.sendMessage = () => Promise.resolve(response);
''')
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
- msg = 'Results were served using unsupported Hydrilla API version (1234). You might need to update Haketilo.'
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
+ msg = 'Results were served using unsupported Hydrilla API version. You might need to update Haketilo.'
WebDriverWait(driver, 10).until(has_msg(msg, elem))
- elif message == 'invalid_API_version':
+ elif message == 'invalid_response_format':
setup_view(execute_in_page, repo_urls)
execute_in_page(
'''
const response = {
ok: true,
status: 200,
- json: {api_schema_version: null}
+ /* $schema is not a string as it should be. */
+ json: {$schema: null}
};
browser.tabs.sendMessage = () => Promise.resolve(response);
''')
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
- msg = 'Results were served using unsupported Hydrilla API version. You might need to update Haketilo.'
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
+ msg = 'Results were served using a nonconforming response format.'
WebDriverWait(driver, 10).until(has_msg(msg, elem))
elif message == 'querying_repo':
setup_view(execute_in_page, repo_urls)
@@ -249,7 +250,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
)
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
assert has_msg('Querying repository...', elem)(0)
elif message == 'no_results':
setup_view(execute_in_page, repo_urls)
@@ -259,8 +260,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
ok: true,
status: 200,
json: {
- api_schema_version: [1],
- api_schema_revision: 1,
+ $schema: "https://hydrilla.koszko.org/schemas/api_query_result-1.schema.json",
mappings: []
}
};
@@ -268,7 +268,7 @@ def test_repo_query_messages(driver, execute_in_page, message):
''')
show_and_wait_for_repo_entry()
- elem = execute_in_page('returnval(view.repo_entries[0].info_span);')
+ elem = execute_in_page('returnval(view.repo_entries[0].info_div);')
WebDriverWait(driver, 10).until(has_msg('No results :(', elem))
else:
raise Exception('made a typo in test function params?')
diff --git a/test/unit/utils.py b/test/unit/utils.py
index 6ff04ed..b27a209 100644
--- a/test/unit/utils.py
+++ b/test/unit/utils.py
@@ -79,6 +79,11 @@ def make_sample_mapping(with_files=True):
Haketilo's IndexedDB.
"""
return {
+ '$schema': 'https://hydrilla.koszko.org/schemas/api_mapping_description-1.schema.json',
+ 'generated_by': {
+ 'name': 'human',
+ 'version': 'sapiens-0.8.14'
+ },
'source_name': 'example-org-fixes-new',
'source_copyright': [
sample_file_ref('report.spdx'),
@@ -106,6 +111,11 @@ def make_sample_resource(with_files=True):
Haketilo's IndexedDB.
"""
return {
+ '$schema': 'https://hydrilla.koszko.org/schemas/api_resource_description-1.schema.json',
+ 'generated_by': {
+ 'name': 'human',
+ 'version': 'sapiens-0.8.14'
+ },
'source_name': 'hello',
'source_copyright': [
sample_file_ref('report.spdx'),
diff --git a/test/world_wide_library.py b/test/world_wide_library.py
index 56af35f..1e802ab 100644
--- a/test/world_wide_library.py
+++ b/test/world_wide_library.py
@@ -150,8 +150,6 @@ sample_queries = {}
for srt in sample_resource_templates:
resource = make_sample_resource()
- resource['api_schema_version'] = [1]
- resource['api_schema_revision'] = 1
resource['identifier'] = f'resource_{srt["id_suffix"]}'
resource['long_name'] = resource['identifier'].upper()
resource['uuid'] = str(uuid4())
@@ -166,8 +164,6 @@ for srt in sample_resource_templates:
resource_versions[1][-1] += 1
mapping = make_sample_mapping()
- mapping['api_schema_version'] = [1]
- mapping['api_schema_revision'] = 1
mapping['identifier'] = f'mapping_{srt["id_suffix"]}'
mapping['long_name'] = mapping['identifier'].upper()
mapping['uuid'] = str(uuid4())
@@ -208,9 +204,12 @@ for srt in sample_resource_templates:
def serve_query(command, get_params, post_params):
response = {
- 'api_schema_version': [1],
- 'api_schema_revision': 1,
- 'mappings': sample_queries[get_params['url'][0]]
+ '$schema': 'https://hydrilla.koszko.org/schemas/api_query_result-1.schema.json',
+ 'generated_by': {
+ 'name': 'human',
+ 'version': 'sapiens-0.8.15'
+ },
+ 'mappings': sample_queries[get_params['url'][0]]
}
return (200, {}, json.dumps(response))