From dd8de100acda322f2124c58163ecde6f1b37d61d Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 11 Jan 2022 15:43:40 +0100 Subject: add missing payload_create test and styling --- test/unit/test_payload_create.py | 211 +++++++++++++++++++++++++++++++-------- test/unit/utils.py | 5 +- 2 files changed, 175 insertions(+), 41 deletions(-) (limited to 'test') diff --git a/test/unit/test_payload_create.py b/test/unit/test_payload_create.py index cd08d43..bda3293 100644 --- a/test/unit/test_payload_create.py +++ b/test/unit/test_payload_create.py @@ -23,7 +23,7 @@ from selenium.webdriver.support.ui import WebDriverWait from ..extension_crafting import ExtraHTML from ..script_loader import load_script -from .utils import clear_indexeddb, get_db_contents, sample_files +from .utils import * broker_js = lambda: load_script('background/broadcast_broker.js') + ';start();' @@ -55,6 +55,23 @@ def fill_form_with_sample_data(execute_in_page, sample_data_override={}, {form_ctx}[key].value = value; ''', form_data) + return form_data + +cleared_form_inputs = { + 'identifier': '', + 'long_name': '', + 'description': '', + 'patterns': 'https://example.com/***', + 'script': 'console.log("Hello, World!");' +} +def assert_form_contents(execute_in_page, inputs=cleared_form_inputs): + inputs_keys = [*inputs.keys()] + values = execute_in_page( + 'returnval(arguments[0].map(i => form_ctx[i].value));', + inputs_keys + ) + for key, value in zip(inputs_keys, values): + assert inputs[key] == value @pytest.mark.ext_data({ 'background_script': broker_js, @@ -62,60 +79,174 @@ def fill_form_with_sample_data(execute_in_page, sample_data_override={}, 'navigate_to': 'html/payload_create.html' }) @pytest.mark.usefixtures('webextension') -def test_payload_create(driver, execute_in_page): +def test_payload_create_normal_usage(driver, execute_in_page): """ - A test case of creating a simple payload using a form. + A test case of normal usage of simple payload creation form. """ clear_indexeddb(execute_in_page) execute_in_page(load_script('html/payload_create.js')) - create_but, main_div = execute_in_page( + create_but, form_container, dialog_container = execute_in_page( ''' const form_ctx = payload_create_form(); document.body.append(form_ctx.main_div); - returnval([form_ctx.create_but, form_ctx.main_div]); + returnval([form_ctx.create_but, form_ctx.form_container, + form_ctx.dialog_container]); ''') - fill_form_with_sample_data(execute_in_page) + assert doc_url == \ + driver.find_element_by_link_text('URL patterns').get_attribute('href') + + assert form_container.is_displayed() + assert not dialog_container.is_displayed() + + assert_form_contents(execute_in_page) + + form_data = fill_form_with_sample_data(execute_in_page) create_but.click() + assert not form_container.is_displayed() + assert dialog_container.is_displayed() + def success_reported(driver): - return 'Successfully saved payload' in main_div.text + return 'Successfully saved payload' in dialog_container.text WebDriverWait(driver, 10).until(success_reported) + execute_in_page('form_ctx.dialog_ctx.ok_but.click();') + + assert form_container.is_displayed() + assert not dialog_container.is_displayed() + + def assert_db_contents(): + db_contents = get_db_contents(execute_in_page) + + assert uuidv4_re.match(db_contents['resources'][0]['uuid']) + + localid = f'local-{form_data["identifier"]}' + long_name = form_data['long_name'] or form_data['identifier'] + payloads = dict([(pat, {'identifier': localid}) + for pat in form_data['patterns'].split('\n') if pat]) + + assert db_contents['resources'] == [{ + 'source_name': localid, + 'source_copyright': [], + 'type': 'resource', + 'identifier': localid, + 'uuid': db_contents['resources'][0]['uuid'], + 'version': [1], + 'description': form_data['description'], + 'dependencies': [], + 'long_name': long_name, + 'scripts': [{ + 'file': 'payload.js', + 'hash_key': make_hash_key(form_data['script']) + }] + }] - db_contents = get_db_contents(execute_in_page) - - assert uuidv4_re.match(db_contents['resources'][0]['uuid']) - assert db_contents['resources'] == [{ - 'source_name': 'local-someid', - 'source_copyright': [], - 'type': 'resource', - 'identifier': 'local-someid', - 'long_name': 'Some Name', - 'uuid': db_contents['resources'][0]['uuid'], - 'version': [1], - 'description': 'blah blah blah', - 'dependencies': [], - 'scripts': [{ - 'file': 'payload.js', - 'hash_key': sample_files['hello.js']['hash_key'] + assert uuidv4_re.match(db_contents['mappings'][0]['uuid']) + assert db_contents['mappings'] == [{ + 'source_name': localid, + 'source_copyright': [], + 'type': 'mapping', + 'identifier': localid, + 'uuid': db_contents['mappings'][0]['uuid'], + 'version': [1], + 'description': form_data['description'], + 'long_name': long_name, + 'payloads': payloads }] - }] - - assert uuidv4_re.match(db_contents['mappings'][0]['uuid']) - assert db_contents['mappings'] == [{ - 'source_name': 'local-someid', - 'source_copyright': [], - 'type': 'mapping', - 'identifier': 'local-someid', - 'long_name': 'Some Name', - 'uuid': db_contents['mappings'][0]['uuid'], - 'version': [1], - 'description': 'blah blah blah', - 'payloads': { - 'http://example.com/***': {'identifier': 'local-someid'}, - 'https://*.example.org/**': {'identifier': 'local-someid'} - } - }] + + assert_db_contents() + + form_data = fill_form_with_sample_data(execute_in_page, { + 'long_name': '', + 'description': 'bam bam bam', + 'patterns': 'https://new.example.com/***', + 'script': sample_files['bye.js']['contents'] + }) + + create_but.click() + + for type in ('Resource', 'Mapping'): + def override_asked(driver): + return f"{type} 'local-someid' already exists. Override?" \ + in dialog_container.text + WebDriverWait(driver, 10).until(override_asked) + execute_in_page('form_ctx.dialog_ctx.yes_but.click();') + + assert_db_contents() + +doc_url = 'https://hydrillabugs.koszko.org/projects/haketilo/wiki/URL_patterns' + +@pytest.mark.ext_data({ + 'background_script': broker_js, + 'extra_html': ExtraHTML('html/payload_create.html', {}), + 'navigate_to': 'html/payload_create.html' +}) +@pytest.mark.usefixtures('webextension') +def test_payload_create_errors(driver, execute_in_page): + """ + A test case of various error the simple payload form might show. + """ + clear_indexeddb(execute_in_page) + execute_in_page(load_script('html/payload_create.js')) + + create_but, dialog_container = execute_in_page( + ''' + const form_ctx = payload_create_form(); + document.body.append(form_ctx.main_div); + returnval([form_ctx.create_but, form_ctx.dialog_container]); + ''') + + for data_override, expected_msg in [ + ({'identifier': ''}, "The 'identifier' field is required!"), + ({'identifier': ':('}, 'Identifier may only contain '), + ({'script': ''}, "The 'script' field is required!"), + ({'patterns': ''}, "The 'URL patterns' field is required!"), + ({'patterns': ':d'}, "':d' is not a valid URL pattern. See here for more details."), + ({'patterns': '\n'.join(['http://example.com'] * 2)}, + "Pattern 'http://example.com' specified multiple times!") + ]: + # Attempt creating the payload + form_data = fill_form_with_sample_data(execute_in_page, data_override) + create_but.click() + # Verify the error message + assert expected_msg in dialog_container.text + + # Verify patterns documentation link. + if expected_msg == {'patterns': ':d'}: + doc_link_elem = driver.find_element_by_link_text('here') + assert doc_link.get_attribute('href') == doc_url + + # Verify the form was NOT cleared upon failed saving. + execute_in_page('form_ctx.dialog_ctx.ok_but.click();') + assert_form_contents(execute_in_page, form_data) + + # Add a sample item and attempt overriding it. + fill_form_with_sample_data(execute_in_page) + create_but.click() + WebDriverWait(driver, 10).until(lambda _: 'Succes' in dialog_container.text) + execute_in_page('form_ctx.dialog_ctx.ok_but.click();') + + # Verify that denying override leads to saving failure. + form_data = fill_form_with_sample_data(execute_in_page) + create_but.click() + WebDriverWait(driver, 10).until(lambda _: 'Overri' in dialog_container.text) + execute_in_page('form_ctx.dialog_ctx.no_but.click();') + assert 'Failed to save payload :(' in dialog_container.text + execute_in_page('form_ctx.dialog_ctx.ok_but.click();') + assert_form_contents(execute_in_page, form_data) + + # Verify that IndexedDB errors get caught and reported as saving failures. + execute_in_page('haketilodb.get = async () => {throw "someerror";}') + form_data = fill_form_with_sample_data(execute_in_page, {'identifier': 'o'}) + create_but.click() + WebDriverWait(driver, 10).until(lambda _: 'Failed' in dialog_container.text) + execute_in_page('form_ctx.dialog_ctx.ok_but.click();') + assert_form_contents(execute_in_page, form_data) + + # Verify that the loading message gets shown during IndexedDB operations. + execute_in_page('haketilodb.get = () => new Promise(cb => null);') + create_but.click() + assert 'Saving payload...' in dialog_container.text diff --git a/test/unit/utils.py b/test/unit/utils.py index a61e215..255f89d 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -27,9 +27,12 @@ Various functions and objects that can be reused between unit tests from hashlib import sha256 +def make_hash_key(file_contents): + return f'sha256-{sha256(file_contents.encode()).digest().hex()}' + def sample_file(contents): return { - 'hash_key': f'sha256-{sha256(contents.encode()).digest().hex()}', + 'hash_key': make_hash_key(contents), 'contents': contents } -- cgit v1.2.3