From 42fe44050661ed59198fb166672bfdaa119d4333 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Wed, 26 Jan 2022 11:38:21 +0100 Subject: add new extension's popup page --- test/extension_crafting.py | 4 + test/unit/conftest.py | 1 + test/unit/test_popup.py | 215 +++++++++++++++++++++++++++++++++++++++++++ test/unit/test_repo_query.py | 10 +- 4 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 test/unit/test_popup.py (limited to 'test') diff --git a/test/extension_crafting.py b/test/extension_crafting.py index efb2687..ed5792f 100644 --- a/test/extension_crafting.py +++ b/test/extension_crafting.py @@ -63,6 +63,10 @@ def manifest_template(): ], 'content_security_policy': "object-src 'none'; script-src 'self' https://serve.scrip.ts;", 'web_accessible_resources': ['testpage.html'], + 'options_ui': { + 'page': 'testpage.html', + 'open_in_tab': True + }, 'background': { 'persistent': True, 'scripts': ['__open_test_page.js', 'background.js'] diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 9318f6e..a3064f1 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -59,6 +59,7 @@ def driver(_driver, request): nav_target = request.node.get_closest_marker('get_page') close_all_but_one_window(_driver) _driver.get(nav_target.args[0] if nav_target else 'about:blank') + _driver.implicitly_wait(0) yield _driver @pytest.fixture() diff --git a/test/unit/test_popup.py b/test/unit/test_popup.py new file mode 100644 index 0000000..5319d72 --- /dev/null +++ b/test/unit/test_popup.py @@ -0,0 +1,215 @@ +# SPDX-License-Identifier: CC0-1.0 + +""" +Haketilo unit tests - repository querying +""" + +# This file is part of Haketilo +# +# Copyright (C) 2022 Wojtek Kosior +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the CC0 1.0 Universal License as published by +# the Creative Commons Corporation. +# +# 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 +# CC0 1.0 Universal License for more details. + +import pytest +import json +from selenium.webdriver.support.ui import WebDriverWait + +from ..extension_crafting import ExtraHTML +from ..script_loader import load_script +from .utils import * + +def reload_with_target(driver, target): + current_url = driver.execute_script('return location.href') + driver.execute_script( + ''' + window.location.href = arguments[0]; + window.location.reload(); + ''', + f'{current_url}#{target}') + +unprivileged_page_info = { + 'url': 'https://example_a.com/something', + 'allow': False +} + +mocked_page_infos = { + 'privileged': { + 'url': 'moz-extension:///file.html', + 'privileged': True + }, + 'blocked_default': unprivileged_page_info, + 'allowed_default': { + **unprivileged_page_info, + 'allow': True + }, + 'blocked_rule': { + **unprivileged_page_info, + 'mapping': '~allow' + }, + 'allowed_rule': { + **unprivileged_page_info, + 'allow': True, + 'mapping': '~allow' + }, + 'mapping': { + **unprivileged_page_info, + 'mapping': 'm1', + 'payload': {'identifier': 'res1'} + } +} + +tab_mock_js = ''' +; +const mocked_page_info = (%s)[/#mock_page_info-(.*)$/.exec(document.URL)[1]]; +browser.tabs.sendMessage = async function(tab_id, msg) { + const this_tab_id = (await browser.tabs.getCurrent()).id; + if (tab_id !== this_tab_id) + throw `not current tab id (${tab_id} instead of ${this_tab_id})`; + + if (msg[0] === "page_info") { + return mocked_page_info; + } else if (msg[0] === "repo_query") { + const response = await fetch(msg[1]); + if (!response) + return {error: "Something happened :o"}; + + const result = {ok: response.ok, status: response.status}; + try { + result.json = await response.json(); + } catch(e) { + result.error_json = "" + e; + } + return result; + } else { + throw `bad sendMessage message type: '${msg[0]}'`; + } +} + +const old_tabs_query = browser.tabs.query; +browser.tabs.query = async function(query) { + const tabs = await old_tabs_query(query); + tabs.forEach(t => t.url = mocked_page_info.url); + return tabs; +} +''' % json.dumps(mocked_page_infos) + +popup_ext_data = { + 'background_script': broker_js, + 'extra_html': ExtraHTML( + 'html/popup.html', + { + 'common/browser.js': tab_mock_js, + 'common/indexeddb.js': '; set_repo("https://hydril.la/");' + }, + wrap_into_htmldoc=False + ), + 'navigate_to': 'html/popup.html' +} + +@pytest.mark.ext_data(popup_ext_data) +@pytest.mark.usefixtures('webextension') +@pytest.mark.parametrize('page_info_key', ['', *mocked_page_infos.keys()]) +def test_popup_display(driver, execute_in_page, page_info_key): + """ + Test popup viewing while on a page. Test parametrized with different + possible values of page_info object passed in message from the content + script. + """ + reload_with_target(driver, f'mock_page_info-{page_info_key}') + + by_id = driver.execute_script(''' + const nodes = [...document.querySelectorAll("[id]")]; + return nodes.reduce((ob, node) => Object.assign(ob, {[node.id]: node}), {}); + '''); + + if page_info_key == '': + error_msg = 'Page info not avaialable. Try reloading the page.' + error_msg_shown = lambda d: by_id['loading_info'].text == error_msg + WebDriverWait(driver, 10).until(error_msg_shown) + return + + WebDriverWait(driver, 10).until(lambda d: by_id['info_form'].is_displayed()) + assert (page_info_key == 'privileged') == \ + by_id['privileged_page_info'].is_displayed() + assert (page_info_key == 'privileged') ^ \ + by_id['unprivileged_page_info'].is_displayed() + assert by_id['page_url'].text == mocked_page_infos[page_info_key]['url'] + assert not by_id['repo_query_container'].is_displayed() + + if 'blocked' in page_info_key or page_info_key == 'mapping': + assert by_id['scripts_blocked'].text.lower() == 'yes' + elif 'allowed' in page_info_key: + assert by_id['scripts_blocked'].text.lower() == 'no' + + if page_info_key == 'mapping': + assert by_id['injected_payload'].text == 'res1' + elif page_info_key != 'privileged': + assert by_id['injected_payload'].text == 'None' + + mapping_text = by_id['mapping_used'].text + if page_info_key == 'mapping': + assert mapping_text == 'm1' + + if 'allowed' in page_info_key: + 'None (scripts allowed by' in mapping_text + elif 'blocked' in page_info_key: + 'None (scripts blocked by' in mapping_text + + if 'rule' in page_info_key: + 'by a rule)' in mapping_text + elif 'default' in page_info_key: + 'by default_policy)' in mapping_text + +@pytest.mark.ext_data(popup_ext_data) +@pytest.mark.usefixtures('webextension') +def test_popup_repo_query(driver, execute_in_page): + """ + Test opening and closing the repo query view in popup. + """ + reload_with_target(driver, f'mock_page_info-blocked_rule') + + search_but = driver.find_element_by_id("search_resources_but") + WebDriverWait(driver, 10).until(lambda d: search_but.is_displayed()) + search_but.click() + containers = dict([(name, driver.find_element_by_id(f'{name}_container')) + for name in ('page_info', 'repo_query')]) + assert not containers['page_info'].is_displayed() + assert containers['repo_query'].is_displayed() + shown = lambda d: 'https://hydril.la/' in containers['repo_query'].text + WebDriverWait(driver, 10).until(shown) + + # Click the "Show results" button. + selector = '.repo_query_buttons > button:first-child' + driver.find_element_by_css_selector(selector).click() + shown = lambda d: 'MAPPING_A' in containers['repo_query'].text + WebDriverWait(driver, 10).until(shown) + + # Click the "Cancel" button + selector = '.repo_query_bottom_buttons > button' + driver.find_element_by_css_selector(selector).click() + assert containers['page_info'].is_displayed() + assert not containers['repo_query'].is_displayed() + +@pytest.mark.ext_data(popup_ext_data) +@pytest.mark.usefixtures('webextension') +def test_popup_settings_opening(driver, execute_in_page): + """ + Test opening the settings page from popup through button click. + """ + driver.find_element_by_id("settings_but").click() + + first_handle = driver.current_window_handle + WebDriverWait(driver, 10).until(lambda d: len(d.window_handles) == 2) + new_handle = [h for h in driver.window_handles if h != first_handle][0] + + driver.switch_to.window(new_handle) + driver.implicitly_wait(10) + assert "Extension's options page for testing" in \ + driver.find_element_by_tag_name("h1").text diff --git a/test/unit/test_repo_query.py b/test/unit/test_repo_query.py index dd57452..77c5e75 100644 --- a/test/unit/test_repo_query.py +++ b/test/unit/test_repo_query.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 """ -Haketilo unit tests - ............. +Haketilo unit tests - repository querying """ # This file is part of Haketilo @@ -18,12 +18,8 @@ Haketilo unit tests - ............. # CC0 1.0 Universal License for more details. import pytest -import json from selenium.webdriver.support.ui import WebDriverWait -from ..extension_crafting import ExtraHTML -from ..script_loader import load_script - from ..extension_crafting import ExtraHTML from ..script_loader import load_script from .utils import * @@ -172,7 +168,7 @@ def test_repo_query_messages(driver, execute_in_page, message): show_and_wait_for_repo_entry() elem = execute_in_page('returnval(view.url_span.parentNode);') - assert has_msg(f'Browsing custom resources for {queried_url}.', elem)(0) + assert has_msg(f'Browsing custom resources for: {queried_url}', elem)(0) elif message == 'no_repos': setup_view(execute_in_page, []) show_and_wait_for_repo_entry() @@ -272,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].results_list);') + elem = execute_in_page('returnval(view.repo_entries[0].info_span);') WebDriverWait(driver, 10).until(has_msg('No results :(', elem)) else: raise Exception('made a typo in test function params?') -- cgit v1.2.3