summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-01-14 22:48:01 +0100
committerWojtek Kosior <koszko@koszko.org>2022-01-14 22:48:01 +0100
commite7d11c7c1173d07db741301053db78b835a73ab3 (patch)
tree2f7e5b3e494f896855a2417694df7338745f0770
parent299864ee0901df8db2314cc7c07d6c481927c8aa (diff)
downloadbrowser-extension-e7d11c7c1173d07db741301053db78b835a73ab3.tar.gz
browser-extension-e7d11c7c1173d07db741301053db78b835a73ab3.zip
add settings page with styling
-rw-r--r--html/base.css18
-rw-r--r--html/item_list.html12
-rw-r--r--html/item_list.js6
-rw-r--r--html/item_preview.html4
-rw-r--r--html/payload_create.html8
-rw-r--r--html/settings.html152
-rw-r--r--html/settings.js125
-rw-r--r--html/text_entry_list.html37
-rw-r--r--test/unit/test_broadcast.py7
-rw-r--r--test/unit/test_default_policy_dialog.py3
-rw-r--r--test/unit/test_indexeddb.py13
-rw-r--r--test/unit/test_item_list.py2
-rw-r--r--test/unit/test_item_preview.py55
-rw-r--r--test/unit/test_payload_create.py2
-rw-r--r--test/unit/test_text_entry_list.py2
-rw-r--r--test/unit/utils.py59
16 files changed, 415 insertions, 90 deletions
diff --git a/html/base.css b/html/base.css
index e5e4660..4575b10 100644
--- a/html/base.css
+++ b/html/base.css
@@ -41,6 +41,7 @@ body {
h1, h2, h3 {
margin: 0.3em;
text-shadow: 0 0 0 #454;
+ text-align: center;
}
h2 {
@@ -61,7 +62,7 @@ li:first-child {
}
.hide {
- display: none;
+ display: none !important;
}
button {
@@ -79,6 +80,19 @@ button {
font: 400 0.9em sans-serif;
}
-button:hover, .button:hover {
+button:hover {
box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
}
+
+body {
+ --line-height: 0.4em;
+}
+
+div.bottom_line {
+ height: var(--line-height);
+ background: linear-gradient(#555, transparent);
+}
+div.top_line {
+ height: var(--line-height);
+ background: linear-gradient(transparent, #555);
+}
diff --git a/html/item_list.html b/html/item_list.html
index 4e23868..cae783a 100644
--- a/html/item_list.html
+++ b/html/item_list.html
@@ -41,9 +41,16 @@
#LOADCSS html/base.css
#LOADCSS html/grid.css
<style>
+ .item_list, .preview_scroll_box {
+ overflow-y: auto;
+ padding-top: 0.4em;
+ height: calc(var(--content-height) - 0.4em);
+ }
.item_list {
overflow-y: scroll;
+ min-width: 7em;
}
+
.item_list>li {
cursor: pointer;
padding: 0.15em 0.3em;
@@ -73,8 +80,9 @@
<template>
<div id="item_list" data-template="main_div" class="grid_2 list_main_view">
<ul data-template="ul" class="item_list"></ul>
- <div>
- <div data-template="preview_container" class="hide">
+ <div class="preview_scroll_box">
+ <div data-template="preview_container"
+ class="hide item_preview_container">
<!-- preview div will be dynamically inserted here -->
<div class="list_buttons">
<button data-template="remove_but">Remove</button>
diff --git a/html/item_list.js b/html/item_list.js
index 198e0f9..51950d5 100644
--- a/html/item_list.js
+++ b/html/item_list.js
@@ -94,7 +94,7 @@ function item_cmp(def1, def2)
coll.compare(def1.identifier, def2.identifier);
}
-function find_item_idx(definition)
+function find_item_idx(list_ctx, definition)
{
/* Perform a binary search of item's (new or not) index in sorted array. */
let left = 0, right = list_ctx.items.length;
@@ -115,7 +115,7 @@ function item_changed(list_ctx, change)
/* Remove item. */
const old_item = list_ctx.by_identifier.get(change.key);
if (old_item !== undefined) {
- list_ctx.items.splice(find_item_idx(old_item.definition), 1);
+ list_ctx.items.splice(find_item_idx(list_ctx, old_item.definition), 1);
list_ctx.by_identifier.delete(change.key);
old_item.li.remove();
@@ -129,7 +129,7 @@ function item_changed(list_ctx, change)
return;
const new_item = insert_item(list_ctx, change.new_val,
- find_item_idx(change.new_val));
+ find_item_idx(list_ctx, change.new_val));
if (list_ctx.previewed_item === old_item)
preview_item(list_ctx, new_item, true);
}
diff --git a/html/item_preview.html b/html/item_preview.html
index 160c01d..c631f37 100644
--- a/html/item_preview.html
+++ b/html/item_preview.html
@@ -39,7 +39,7 @@
#LOADCSS html/grid.css
<style>
.preview_main_div {
- margin: 0.8em 0.8em;
+ margin: 1.3em 0.8em 1em 0.8em;
}
</style>
<template>
@@ -78,7 +78,7 @@
<span data-template="version" class="grid_col_2">...</span>
<label class="grid_col_1">description:</label>
<span data-template="description" class="grid_col_2">...</span>
- <label class="grid_col_both">payloads:</label>
+ <label class="grid_col_1">payloads:</label>
<div data-template="payloads" class="grid_col_both grid_2"></div>
<label class="grid_col_1">source name:</label>
<span data-template="source_name" class="grid_col_2">...</span>
diff --git a/html/payload_create.html b/html/payload_create.html
index 44fa4e2..0a5577e 100644
--- a/html/payload_create.html
+++ b/html/payload_create.html
@@ -40,8 +40,13 @@
#LOADCSS html/base.css
#LOADCSS html/grid.css
<style>
+ .payload_create_main_view {
+ overflow-y:auto;
+ height: var(--content-height);
+ }
.payload_create_form {
margin: 0 0.6em;
+ padding-top: 1em;
}
.payload_create_form>* {
margin: 0.3em 0;
@@ -54,7 +59,7 @@
height: 18em;
font-family: monospace;
}
- .payload_create_buts, .payload_create_heading {
+ .payload_create_buts {
text-align: center;
margin: 0.5em 0;
}
@@ -64,7 +69,6 @@
class="payload_create_main_view">
<div data-template="form_container">
<div class="grid_1 payload_create_form">
- <h3 class="payload_create_heading">Create payload</h3>
<span>
<label>identifier*</label>
(may only contain digits 0-9, lowercase letters a-z and hyphens '-';
diff --git a/html/settings.html b/html/settings.html
new file mode 100644
index 0000000..0bba5e3
--- /dev/null
+++ b/html/settings.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<!--
+ SPDX-License-Identifier: GPL-3.0-or-later OR CC-BY-SA-4.0
+
+ Haketilo's settings page
+
+ This file is part of Haketilo.
+
+ Copyright (C) 2022 Wojtek Kosior <koszko@koszko.org>
+
+ File is dual-licensed. You can choose either GPLv3+, CC BY-SA or both.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ 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
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ I, Wojtek Kosior, thereby promise not to sue for violation of this file's
+ licenses. Although I request that you do not make use of this code in a
+ proprietary program, I am not going to enforce this in court.
+ -->
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Haketilo options</title>
+#LOADCSS html/reset.css
+#LOADCSS html/base.css
+#LOADCSS html/table.css
+#LOADCSS html/grid.css
+ <style>
+ /* Style top menu items. */
+ #tab_heads>* {
+ background-color: #70AF70;
+ font-size: 115%;
+ padding: 0.6em;
+ display: inline-block;
+ cursor: pointer;
+ margin: 0.25em 0 0 0;
+ }
+ body {
+ /* 0.25em margin + 1em height + 2*0.6em padding, multiple font size */
+ --heading-height: calc(2.45em * 1.15);
+ --tab-content-height: calc(100vh - var(--heading-height));
+ }
+ #tab_heads>:hover {
+ box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
+ }
+ #tab_heads>.active_head {
+ background-color: #65A065;
+ color: #222;
+ box-shadow: none;
+ cursor: default;
+ }
+
+ /* Style the top menu itself. */
+ #tab_heads {
+ -moz-user-select: none;
+ user-select: none;
+ background-color: #e0e0e0;
+ }
+ #top_menu_line {
+ position: absolute;
+ width: 100vw;
+ z-index: 1;
+ }
+
+ /* Style content */
+ body {
+ --content-max-width: 1000px;
+ height: 100vh;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ }
+ div.tab {
+ display: none;
+ }
+ div.tab.active_tab {
+ display: block;
+ }
+
+ /* Style the Script blocking and Repositories tabs. */
+ #blocking_list_container, #allowing_list_container,
+ #default_policy_dialog, #blocking_dialog_container,
+ #repos_list_container, #repos_dialog_container {
+ padding: 0.8em 0.4em 0.4em 0.4em;
+ }
+ #default_policy_dialog {
+ text-align: center;
+ }
+ #blocking_editable_container, #blocking_dialog_container,
+ #repos_list_container, #repos_dialog_container {
+ max-width: var(--content-max-width);
+ margin: 0 auto;
+ }
+ #blocking_editable_container {
+ /* Leave space for default policy dialog and headings. */
+ --content-height: calc(var(--tab-content-height) - 3em);
+ }
+
+ /* Pass height information to html in all tabs. */
+ .tab {
+ --content-height: var(--tab-content-height);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Those contain just templates, we can include them at the top -->
+#INCLUDE html/dialog.html
+#INCLUDE html/item_list.html
+#INCLUDE html/item_preview.html
+#INCLUDE html/text_entry_list.html
+#INCLUDE html/payload_create.html
+ <ul id="tab_heads" class="has_bottom_line">
+ <li id="blocking_head"> Blocking </li>
+ <li id="mappings_head"> Mappings </li>
+ <li id="resources_head"> Resources </li>
+ <li id="new_payload_head" class="active_head"> New payload </li>
+ <li id="repos_head"> Repositories </li>
+ </ul>
+ <div id="top_menu_line" class="bottom_line"></div>
+ <div id="blocking_tab" class="tab">
+ <div id="blocking_editable_container" class="grid_2">
+ <div id="blocking_list_container">
+ <h3>Block scripts on</h3>
+ </div>
+ <div id="allowing_list_container">
+ <h3>Allow scripts on</h3>
+ </div>
+ <div id="default_policy_dialog" class="grid_col_both">
+#INCLUDE html/default_blocking_policy.html
+ </div>
+ </div>
+ <div id="blocking_dialog_container" class="hide"></div>
+ </div>
+ <div id="mappings_tab" class="tab"></div>
+ <div id="resources_tab" class="tab"></div>
+ <div id="new_payload_tab" class="tab active_tab"></div>
+ <div id="repos_tab" class="tab">
+ <div id="repos_list_container"></div>
+ <div id="repos_dialog_container" class="hide"></div>
+ </div>
+#LOADJS html/settings.js
+ </body>
+</html>
diff --git a/html/settings.js b/html/settings.js
new file mode 100644
index 0000000..36eeb47
--- /dev/null
+++ b/html/settings.js
@@ -0,0 +1,125 @@
+/**
+ * This file is part of Haketilo.
+ *
+ * Function: Driving Haketilo's settings page.
+ *
+ * Copyright (C) 2022 Wojtek Kosior
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ * GNU General Public License for more details.
+ *
+ * As additional permission under GNU GPL version 3 section 7, you
+ * may distribute forms of that code without the copy of the GNU
+ * GPL normally required by section 4, provided you include this
+ * license notice and, in case of non-source distribution, a URL
+ * through which recipients can access the Corresponding Source.
+ * If you modify file(s) with this exception, you may extend this
+ * exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this
+ * exception statement from your version.
+ *
+ * As a special exception to the GPL, any HTML file which merely
+ * makes function calls to this code, and for that purpose
+ * includes it by reference shall be deemed a separate work for
+ * copyright law purposes. If you modify this code, you may extend
+ * this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this
+ * exception statement from your version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * I, Wojtek Kosior, thereby promise not to sue for violation of this file's
+ * license. Although I request that you do not make use of this code in a
+ * proprietary program, I am not going to enforce this in court.
+ */
+
+#IMPORT html/dialog.js
+
+#FROM html/DOM_helpers.js IMPORT by_id
+#FROM html/text_entry_list.js IMPORT blocking_allowing_lists, repo_list
+#FROM html/item_list.js IMPORT mapping_list, resource_list
+#FROM html/payload_create.js IMPORT payload_create_form
+
+let tab_names = ["blocking", "mappings", "resources", "new_payload", "repos"];
+let current_tab_name = "new_payload";
+
+const [tabs, heads] = [{}, {}];
+
+for (const tab_name of tab_names) {
+ tabs[tab_name] = by_id(`${tab_name}_tab`);
+ heads[tab_name] = by_id(`${tab_name}_head`);
+}
+
+function switch_to_tab(target_tab_name) {
+ if (current_tab_name == target_tab_name)
+ return;
+
+ tabs[current_tab_name].classList.remove("active_tab");
+ heads[current_tab_name].classList.remove("active_head");
+
+ current_tab_name = target_tab_name;
+ tabs[current_tab_name].classList.add("active_tab");
+ heads[current_tab_name].classList.add("active_head");
+}
+
+for (const [tab_name, head] of Object.entries(heads))
+ head.addEventListener("click", () => switch_to_tab(tab_name));
+
+async function set_up_blocking_tab() {
+ const containers = ["editable", "dialog"]
+ .map(n => by_id(`blocking_${n}_container`));
+
+ function show_container(idx) {
+ containers[idx].classList.remove("hide");
+ containers[1 - idx].classList.add("hide");
+ }
+
+ const dialog_ctx = dialog.make(...[1, 0].map(n => () => show_container(n)));
+ containers[1].append(dialog_ctx.main_div);
+
+ const [blocking_list, allowing_list] =
+ await blocking_allowing_lists(dialog_ctx);
+
+ by_id("blocking_list_container").append(blocking_list.main_div);
+ by_id("allowing_list_container").append(allowing_list.main_div);
+}
+
+async function set_up_mappings_tab() {
+ tabs["mappings"].append((await mapping_list()).main_div);
+}
+
+async function set_up_resources_tab() {
+ tabs["resources"].append((await resource_list()).main_div);
+}
+
+function set_up_new_payload_tab() {
+ tabs["new_payload"].append(payload_create_form().main_div);
+}
+
+async function set_up_repos_tab() {
+ const containers = ["list", "dialog"]
+ .map(n => by_id(`repos_${n}_container`));
+
+ function show_container(idx) {
+ containers[idx].classList.remove("hide");
+ containers[1 - idx].classList.add("hide");
+ }
+
+ const dialog_ctx = dialog.make(...[1, 0].map(n => () => show_container(n)));
+ containers[1].append(dialog_ctx.main_div);
+ containers[0].append((await repo_list(dialog_ctx)).main_div);
+}
+
+set_up_blocking_tab();
+set_up_mappings_tab();
+set_up_resources_tab();
+set_up_new_payload_tab();
+set_up_repos_tab();
diff --git a/html/text_entry_list.html b/html/text_entry_list.html
index 21e1604..77be5cb 100644
--- a/html/text_entry_list.html
+++ b/html/text_entry_list.html
@@ -40,17 +40,41 @@
#LOADCSS html/grid.css
<style>
.text_entry {
- height: 3em;
- padding: 0 0.5em;
+ padding: 0.1em 0.2em;
+ }
+ .text_entry button {
+ margin: 0.1em 0 0.1em 0.2em;
+ }
+ .text_entry_editable, .text_entry_noneditable {
+ display: grid;
+ grid-template-columns: 1fr auto auto;
+ }
+ .text_entry_noneditable {
+ grid-template-columns: 1fr auto;
+ }
+
+ .text_entries {
+ min-height: 3em;
+ background: #cfcfcf;
+ overflow-y: scroll;
+ min-width: 10em;
+ margin: 0.2em 0;
+ height: calc(var(--content-height) - 5em);
+ }
+ .text_entries>:nth-child(2n) {
+ background-color:#dadada;
+ }
+ .text_entries span {
+ padding: 0.4em;
}
</style>
<template>
- <div id="text_entry" data-template="main_div">
- <div data-template="noneditable_view">
+ <div id="text_entry" data-template="main_div" class="text_entry">
+ <div data-template="noneditable_view" class="text_entry_noneditable">
<span data-template="text"></span>
<button data-template="remove_but">Remove</button>
</div>
- <div data-template="editable_view" class="hide">
+ <div data-template="editable_view" class="hide text_entry_editable">
<input data-template="input">
<button data-template="add_but" class="hide">Add</button>
<button data-template="save_but">Save</button>
@@ -58,7 +82,8 @@
</div>
</div>
<div id="text_entry_list" data-template="main_div" class="grid_1">
- <div data-template="list_div" class="grid_1"></div>
+ <div data-template="list_div" class="text_entries">
+ </div>
<button data-template="new_but">New</button>
</div>
</template>
diff --git a/test/unit/test_broadcast.py b/test/unit/test_broadcast.py
index 1213b17..7de6c80 100644
--- a/test/unit/test_broadcast.py
+++ b/test/unit/test_broadcast.py
@@ -20,10 +20,7 @@ Haketilo unit tests - message broadcasting
import pytest
from ..script_loader import load_script
-
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
-broadcast_js = lambda: load_script('common/broadcast.js')
+from .utils import broker_js
test_page_html = '''
<!DOCTYPE html>
@@ -40,7 +37,7 @@ test_page_html = '''
'background_script': broker_js,
'test_page': test_page_html,
'extra_files': {
- 'testpage.js': broadcast_js
+ 'testpage.js': lambda: load_script('common/broadcast.js')
}
})
@pytest.mark.usefixtures('webextension')
diff --git a/test/unit/test_default_policy_dialog.py b/test/unit/test_default_policy_dialog.py
index 992b487..a1c825f 100644
--- a/test/unit/test_default_policy_dialog.py
+++ b/test/unit/test_default_policy_dialog.py
@@ -21,8 +21,7 @@ import pytest
from ..extension_crafting import ExtraHTML
from ..script_loader import load_script
-
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
+from .utils import broker_js
@pytest.mark.ext_data({
'background_script': broker_js,
diff --git a/test/unit/test_indexeddb.py b/test/unit/test_indexeddb.py
index 0c0e7a0..07b620c 100644
--- a/test/unit/test_indexeddb.py
+++ b/test/unit/test_indexeddb.py
@@ -27,9 +27,6 @@ from selenium.common.exceptions import WebDriverException
from ..script_loader import load_script
from .utils import *
-indexeddb_js = lambda: load_script('common/indexeddb.js')
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
# Sample resource definitions. They'd normally contain more fields but here we
# use simplified versions.
@@ -70,7 +67,7 @@ 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())
+ execute_in_page(load_script('common/indexeddb.js'))
mock_broadcast(execute_in_page)
# Start with no database.
@@ -235,7 +232,7 @@ def test_haketilodb_settings(driver, execute_in_page):
indexeddb.js facilitates operating on Haketilo's internal database.
Verify assigning/retrieving values of simple "settings" item works properly.
"""
- execute_in_page(indexeddb_js())
+ execute_in_page(load_script('common/indexeddb.js'))
mock_broadcast(execute_in_page)
# Start with no database.
@@ -257,7 +254,7 @@ def test_haketilodb_allowing(driver, execute_in_page):
indexeddb.js facilitates operating on Haketilo's internal database.
Verify changing the "blocking" configuration for a URL works properly.
"""
- execute_in_page(indexeddb_js())
+ execute_in_page(load_script('common/indexeddb.js'))
mock_broadcast(execute_in_page)
# Start with no database.
@@ -285,7 +282,7 @@ def test_haketilodb_repos(driver, execute_in_page):
indexeddb.js facilitates operating on Haketilo's internal database.
Verify operations on repositories list work properly.
"""
- execute_in_page(indexeddb_js())
+ execute_in_page(load_script('common/indexeddb.js'))
mock_broadcast(execute_in_page)
# Start with no database.
@@ -317,7 +314,7 @@ test_page_html = '''
'background_script': broker_js,
'test_page': test_page_html,
'extra_files': {
- 'testpage.js': indexeddb_js
+ 'testpage.js': lambda: load_script('common/indexeddb.js')
}
})
@pytest.mark.usefixtures('webextension')
diff --git a/test/unit/test_item_list.py b/test/unit/test_item_list.py
index faef1c0..ff532f8 100644
--- a/test/unit/test_item_list.py
+++ b/test/unit/test_item_list.py
@@ -24,8 +24,6 @@ from ..extension_crafting import ExtraHTML
from ..script_loader import load_script
from .utils import *
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
def make_sample_resource(identifier, long_name):
return {
'source_name': 'hello',
diff --git a/test/unit/test_item_preview.py b/test/unit/test_item_preview.py
index c3aaf1f..6148bc2 100644
--- a/test/unit/test_item_preview.py
+++ b/test/unit/test_item_preview.py
@@ -24,52 +24,6 @@ from ..extension_crafting import ExtraHTML
from ..script_loader import load_script
from .utils import *
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
-def make_sample_mapping():
- return {
- 'source_name': 'example-org-fixes-new',
- 'source_copyright': [
- sample_file_ref('report.spdx'),
- sample_file_ref('LICENSES/CC0-1.0.txt')
- ],
- 'type': 'mapping',
- 'identifier': 'example-org-minimal',
- 'long_name': 'Example.org Minimal',
- 'uuid': '54d23bba-472e-42f5-9194-eaa24c0e3ee7',
- 'version': [2022, 5, 10],
- 'description': 'suckless something something',
- 'payloads': {
- 'https://example.org/a/*': {
- 'identifier': 'some-KISS-resource'
- },
- 'https://example.org/t/*': {
- 'identifier': 'another-KISS-resource'
- }
- }
- }
-
-def make_sample_resource():
- return {
- 'source_name': 'hello',
- 'source_copyright': [
- sample_file_ref('report.spdx'),
- sample_file_ref('LICENSES/CC0-1.0.txt')
- ],
- 'type': 'resource',
- 'identifier': 'helloapple',
- 'long_name': 'Hello Apple',
- 'uuid': 'a6754dcb-58d8-4b7a-a245-24fd7ad4cd68',
- 'version': [2021, 11, 10],
- 'revision': 1,
- 'description': 'greets an apple',
- 'dependencies': ['hello-message'],
- 'scripts': [
- sample_file_ref('hello.js'),
- sample_file_ref('bye.js')
- ]
- }
-
@pytest.mark.ext_data({
'extra_html': ExtraHTML('html/item_preview.html', {}),
'navigate_to': 'html/item_preview.html'
@@ -197,16 +151,13 @@ def test_file_preview_link(driver, execute_in_page):
# Mock dialog
execute_in_page('dialog.error = (...args) => window.error_args = args;')
- sample_resource = make_sample_resource()
- sample_data = {
- 'resources': sample_data_dict([sample_resource]),
- 'mappings': {},
- 'files': sample_files_by_hash
- }
+ sample_data = make_complete_sample_data()
+ sample_data['mappings'] = {}
execute_in_page('returnval(haketilodb.save_items(arguments[0]));',
sample_data)
# Cause the "link" to `bye.js` to be invalid.
+ sample_resource = make_sample_resource()
sample_resource['scripts'][1]['hash_key'] = 'dummy nonexistent key'
execute_in_page(
diff --git a/test/unit/test_payload_create.py b/test/unit/test_payload_create.py
index f07083d..6a6cf2c 100644
--- a/test/unit/test_payload_create.py
+++ b/test/unit/test_payload_create.py
@@ -25,8 +25,6 @@ from ..extension_crafting import ExtraHTML
from ..script_loader import load_script
from .utils import *
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
uuidv4_re = re.compile(
r'^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$',
re.IGNORECASE
diff --git a/test/unit/test_text_entry_list.py b/test/unit/test_text_entry_list.py
index e04f36c..3135a59 100644
--- a/test/unit/test_text_entry_list.py
+++ b/test/unit/test_text_entry_list.py
@@ -26,8 +26,6 @@ from ..extension_crafting import ExtraHTML
from ..script_loader import load_script
from .utils import *
-broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'
-
list_code_template = '(await blocking_allowing_lists(%%s))[%d]'
mode_parameters = [
#add_action del_action instantiate_code
diff --git a/test/unit/utils.py b/test/unit/utils.py
index 6abb879..96ebf60 100644
--- a/test/unit/utils.py
+++ b/test/unit/utils.py
@@ -27,6 +27,8 @@ Various functions and objects that can be reused between unit tests
from hashlib import sha256
+from ..script_loader import load_script
+
patterns_doc_url = \
'https://hydrillabugs.koszko.org/projects/haketilo/wiki/URL_patterns'
@@ -55,6 +57,50 @@ sample_files_by_hash = dict([[file['hash_key'], file['contents']]
def sample_file_ref(file_name):
return {'file': file_name, 'hash_key': sample_files[file_name]['hash_key']}
+def make_sample_mapping():
+ return {
+ 'source_name': 'example-org-fixes-new',
+ 'source_copyright': [
+ sample_file_ref('report.spdx'),
+ sample_file_ref('LICENSES/CC0-1.0.txt')
+ ],
+ 'type': 'mapping',
+ 'identifier': 'example-org-minimal',
+ 'long_name': 'Example.org Minimal',
+ 'uuid': '54d23bba-472e-42f5-9194-eaa24c0e3ee7',
+ 'version': [2022, 5, 10],
+ 'description': 'suckless something something',
+ 'payloads': {
+ 'https://example.org/a/*': {
+ 'identifier': 'some-KISS-resource'
+ },
+ 'https://example.org/t/*': {
+ 'identifier': 'another-KISS-resource'
+ }
+ }
+ }
+
+def make_sample_resource():
+ return {
+ 'source_name': 'hello',
+ 'source_copyright': [
+ sample_file_ref('report.spdx'),
+ sample_file_ref('LICENSES/CC0-1.0.txt')
+ ],
+ 'type': 'resource',
+ 'identifier': 'helloapple',
+ 'long_name': 'Hello Apple',
+ 'uuid': 'a6754dcb-58d8-4b7a-a245-24fd7ad4cd68',
+ 'version': [2021, 11, 10],
+ 'revision': 1,
+ 'description': 'greets an apple',
+ 'dependencies': ['hello-message'],
+ 'scripts': [
+ sample_file_ref('hello.js'),
+ sample_file_ref('bye.js')
+ ]
+ }
+
def item_version_string(definition, include_revision=False):
"""
Given a resource or mapping definition, read its "version" property (and
@@ -73,6 +119,17 @@ def sample_data_dict(items):
return dict([(it['identifier'], {item_version_string(it): it})
for it in items])
+def make_complete_sample_data():
+ """
+ Craft a JSON data item with 1 sample resource and 1 sample mapping that can
+ be used to populate IndexedDB.
+ """
+ return {
+ 'resources': sample_data_dict([make_sample_resource()]),
+ 'mappings': sample_data_dict([make_sample_mapping()]),
+ 'files': sample_files_by_hash
+ }
+
def clear_indexeddb(execute_in_page):
"""
Remove Haketilo data from IndexedDB. If variables from common/indexeddb.js
@@ -128,3 +185,5 @@ def get_db_contents(execute_in_page):
def is_prime(n):
return n > 1 and all([n % i != 0 for i in range(2, n)])
+
+broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();'