forked from openlp/openlp
Add cetralised proxy support
bzr-revno: 2823
This commit is contained in:
commit
6a8bf83d27
@ -32,6 +32,7 @@ import requests
|
||||
|
||||
from openlp.core.common import trace_error_handler
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import ProxyMode, Settings
|
||||
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
@ -64,6 +65,39 @@ CONNECTION_TIMEOUT = 30
|
||||
CONNECTION_RETRIES = 2
|
||||
|
||||
|
||||
def get_proxy_settings(mode=None):
|
||||
"""
|
||||
Create a dictionary containing the proxy settings.
|
||||
|
||||
:param ProxyMode | None mode: Specify the source of the proxy settings
|
||||
:return: A dict using the format expected by the requests library.
|
||||
:rtype: dict | None
|
||||
"""
|
||||
settings = Settings()
|
||||
if mode is None:
|
||||
mode = settings.value('advanced/proxy mode')
|
||||
if mode == ProxyMode.NO_PROXY:
|
||||
return {'http': None, 'https': None}
|
||||
elif mode == ProxyMode.SYSTEM_PROXY:
|
||||
# The requests library defaults to using the proxy settings in the environment variables
|
||||
return
|
||||
elif mode == ProxyMode.MANUAL_PROXY:
|
||||
http_addr = settings.value('advanced/proxy http')
|
||||
https_addr = settings.value('advanced/proxy https')
|
||||
username = settings.value('advanced/proxy username')
|
||||
password = settings.value('advanced/proxy password')
|
||||
basic_auth = ''
|
||||
if username:
|
||||
basic_auth = '{username}:{password}@'.format(username=username, password=password)
|
||||
http_value = None
|
||||
https_value = None
|
||||
if http_addr:
|
||||
http_value = 'http://{basic_auth}{http_addr}'.format(basic_auth=basic_auth, http_addr=http_addr)
|
||||
if https_addr:
|
||||
https_value = 'https://{basic_auth}{https_addr}'.format(basic_auth=basic_auth, https_addr=https_addr)
|
||||
return {'http': http_value, 'https': https_value}
|
||||
|
||||
|
||||
def get_user_agent():
|
||||
"""
|
||||
Return a user agent customised for the platform the user is on.
|
||||
@ -75,14 +109,15 @@ def get_user_agent():
|
||||
return browser_list[random_index]
|
||||
|
||||
|
||||
def get_web_page(url, headers=None, update_openlp=False, proxies=None):
|
||||
def get_web_page(url, headers=None, update_openlp=False, proxy=None):
|
||||
"""
|
||||
Attempts to download the webpage at url and returns that page or None.
|
||||
|
||||
:param url: The URL to be downloaded.
|
||||
:param header: An optional HTTP header to pass in the request to the web server.
|
||||
:param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded.
|
||||
Defaults to False.
|
||||
:param dict | None headers: An optional HTTP header to pass in the request to the web server.
|
||||
:param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded. Defaults to False.
|
||||
:param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
|
||||
as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
|
||||
"""
|
||||
if not url:
|
||||
return None
|
||||
@ -90,11 +125,13 @@ def get_web_page(url, headers=None, update_openlp=False, proxies=None):
|
||||
headers = {}
|
||||
if 'user-agent' not in [key.lower() for key in headers.keys()]:
|
||||
headers['User-Agent'] = get_user_agent()
|
||||
if not isinstance(proxy, dict):
|
||||
proxy = get_proxy_settings(mode=proxy)
|
||||
log.debug('Downloading URL = %s' % url)
|
||||
retries = 0
|
||||
while retries < CONNECTION_RETRIES:
|
||||
try:
|
||||
response = requests.get(url, headers=headers, proxies=proxies, timeout=float(CONNECTION_TIMEOUT))
|
||||
response = requests.get(url, headers=headers, proxies=proxy, timeout=float(CONNECTION_TIMEOUT))
|
||||
log.debug('Downloaded page {url}'.format(url=response.url))
|
||||
break
|
||||
except OSError:
|
||||
|
@ -26,6 +26,7 @@ import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from enum import IntEnum
|
||||
from tempfile import gettempdir
|
||||
|
||||
from PyQt5 import QtCore, QtGui
|
||||
@ -38,6 +39,13 @@ log = logging.getLogger(__name__)
|
||||
|
||||
__version__ = 2
|
||||
|
||||
|
||||
class ProxyMode(IntEnum):
|
||||
NO_PROXY = 1
|
||||
SYSTEM_PROXY = 2
|
||||
MANUAL_PROXY = 3
|
||||
|
||||
|
||||
# Fix for bug #1014422.
|
||||
X11_BYPASS_DEFAULT = True
|
||||
if is_linux(): # pragma: no cover
|
||||
@ -116,6 +124,11 @@ class Settings(QtCore.QSettings):
|
||||
'advanced/print file meta data': False,
|
||||
'advanced/print notes': False,
|
||||
'advanced/print slide text': False,
|
||||
'advanced/proxy mode': ProxyMode.SYSTEM_PROXY,
|
||||
'advanced/proxy http': '',
|
||||
'advanced/proxy https': '',
|
||||
'advanced/proxy username': '',
|
||||
'advanced/proxy password': '',
|
||||
'advanced/recent file count': 4,
|
||||
'advanced/save current plugin': False,
|
||||
'advanced/slide limits': SlideLimits.End,
|
||||
|
@ -35,6 +35,7 @@ from openlp.core.lib import SettingsTab, build_icon
|
||||
from openlp.core.ui.style import HAS_DARK_STYLE
|
||||
from openlp.core.widgets.edits import PathEdit
|
||||
from openlp.core.widgets.enums import PathEditType
|
||||
from openlp.core.widgets.widgets import ProxyWidget
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -76,6 +77,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.media_plugin_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.media_plugin_check_box.setObjectName('media_plugin_check_box')
|
||||
self.ui_layout.addRow(self.media_plugin_check_box)
|
||||
self.hide_mouse_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.hide_mouse_check_box.setObjectName('hide_mouse_check_box')
|
||||
self.ui_layout.addWidget(self.hide_mouse_check_box)
|
||||
self.double_click_live_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.double_click_live_check_box.setObjectName('double_click_live_check_box')
|
||||
self.ui_layout.addRow(self.double_click_live_check_box)
|
||||
@ -116,6 +120,24 @@ class AdvancedTab(SettingsTab):
|
||||
self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox')
|
||||
self.ui_layout.addRow(self.use_dark_style_checkbox)
|
||||
# Service Item Slide Limits
|
||||
self.slide_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.slide_group_box.setObjectName('slide_group_box')
|
||||
self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box)
|
||||
self.slide_layout.setObjectName('slide_layout')
|
||||
self.slide_label = QtWidgets.QLabel(self.slide_group_box)
|
||||
self.slide_label.setWordWrap(True)
|
||||
self.slide_layout.addWidget(self.slide_label)
|
||||
self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.end_slide_radio_button.setObjectName('end_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.end_slide_radio_button)
|
||||
self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.wrap_slide_radio_button)
|
||||
self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.next_item_radio_button.setObjectName('next_item_radio_button')
|
||||
self.slide_layout.addWidget(self.next_item_radio_button)
|
||||
self.left_layout.addWidget(self.slide_group_box)
|
||||
# Data Directory
|
||||
self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.data_directory_group_box.setObjectName('data_directory_group_box')
|
||||
@ -142,33 +164,6 @@ class AdvancedTab(SettingsTab):
|
||||
self.data_directory_layout.addRow(self.data_directory_copy_check_layout)
|
||||
self.data_directory_layout.addRow(self.new_data_directory_has_files_label)
|
||||
self.left_layout.addWidget(self.data_directory_group_box)
|
||||
# Hide mouse
|
||||
self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.hide_mouse_group_box.setObjectName('hide_mouse_group_box')
|
||||
self.hide_mouse_layout = QtWidgets.QVBoxLayout(self.hide_mouse_group_box)
|
||||
self.hide_mouse_layout.setObjectName('hide_mouse_layout')
|
||||
self.hide_mouse_check_box = QtWidgets.QCheckBox(self.hide_mouse_group_box)
|
||||
self.hide_mouse_check_box.setObjectName('hide_mouse_check_box')
|
||||
self.hide_mouse_layout.addWidget(self.hide_mouse_check_box)
|
||||
self.right_layout.addWidget(self.hide_mouse_group_box)
|
||||
# Service Item Slide Limits
|
||||
self.slide_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.slide_group_box.setObjectName('slide_group_box')
|
||||
self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box)
|
||||
self.slide_layout.setObjectName('slide_layout')
|
||||
self.slide_label = QtWidgets.QLabel(self.slide_group_box)
|
||||
self.slide_label.setWordWrap(True)
|
||||
self.slide_layout.addWidget(self.slide_label)
|
||||
self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.end_slide_radio_button.setObjectName('end_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.end_slide_radio_button)
|
||||
self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.wrap_slide_radio_button)
|
||||
self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.next_item_radio_button.setObjectName('next_item_radio_button')
|
||||
self.slide_layout.addWidget(self.next_item_radio_button)
|
||||
self.right_layout.addWidget(self.slide_group_box)
|
||||
# Display Workarounds
|
||||
self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.display_workaround_group_box.setObjectName('display_workaround_group_box')
|
||||
@ -223,6 +218,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.service_name_example.setObjectName('service_name_example')
|
||||
self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example)
|
||||
self.right_layout.addWidget(self.service_name_group_box)
|
||||
# Proxies
|
||||
self.proxy_widget = ProxyWidget(self.right_column)
|
||||
self.right_layout.addWidget(self.proxy_widget)
|
||||
# After the last item on each side, add some spacing
|
||||
self.left_layout.addStretch()
|
||||
self.right_layout.addStretch()
|
||||
@ -311,7 +309,6 @@ class AdvancedTab(SettingsTab):
|
||||
translate('OpenLP.AdvancedTab',
|
||||
'Revert to the default service name "{name}".').format(name=UiStrings().DefaultServiceName))
|
||||
self.service_name_example_label.setText(translate('OpenLP.AdvancedTab', 'Example:'))
|
||||
self.hide_mouse_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Mouse Cursor'))
|
||||
self.hide_mouse_check_box.setText(translate('OpenLP.AdvancedTab', 'Hide mouse cursor when over display window'))
|
||||
self.data_directory_new_label.setText(translate('OpenLP.AdvancedTab', 'Path:'))
|
||||
self.data_directory_cancel_button.setText(translate('OpenLP.AdvancedTab', 'Cancel'))
|
||||
@ -334,6 +331,7 @@ class AdvancedTab(SettingsTab):
|
||||
self.wrap_slide_radio_button.setText(translate('OpenLP.GeneralTab', '&Wrap around'))
|
||||
self.next_item_radio_button.setText(translate('OpenLP.GeneralTab', '&Move to next/previous service item'))
|
||||
self.search_as_type_check_box.setText(translate('SongsPlugin.GeneralTab', 'Enable search as you type'))
|
||||
self.proxy_widget.retranslate_ui()
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
@ -436,6 +434,7 @@ class AdvancedTab(SettingsTab):
|
||||
if HAS_DARK_STYLE:
|
||||
settings.setValue('use_dark_style', self.use_dark_style_checkbox.isChecked())
|
||||
settings.endGroup()
|
||||
self.proxy_widget.save()
|
||||
|
||||
def on_search_as_type_check_box_changed(self, check_state):
|
||||
self.is_search_as_you_type_enabled = (check_state == QtCore.Qt.Checked)
|
||||
|
132
openlp/core/widgets/widgets.py
Normal file
132
openlp/core/widgets/widgets.py
Normal file
@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2018 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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; version 2 of the License. #
|
||||
# #
|
||||
# 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, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.widgets.widgets` module contains custom widgets used in OpenLP
|
||||
"""
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.settings import ProxyMode, Settings
|
||||
|
||||
|
||||
class ProxyWidget(QtWidgets.QGroupBox):
|
||||
"""
|
||||
A proxy settings widget that implements loading and saving its settings.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Initialise the widget.
|
||||
|
||||
:param QtWidgets.QWidget | None parent: The widgets parent
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self._setup()
|
||||
|
||||
def _setup(self):
|
||||
"""
|
||||
A setup method seperate from __init__ to allow easier testing
|
||||
"""
|
||||
self.setup_ui()
|
||||
self.load()
|
||||
|
||||
def setup_ui(self):
|
||||
"""
|
||||
Create the widget layout and sub widgets
|
||||
"""
|
||||
self.layout = QtWidgets.QFormLayout(self)
|
||||
self.radio_group = QtWidgets.QButtonGroup(self)
|
||||
self.no_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.no_proxy_radio, ProxyMode.NO_PROXY)
|
||||
self.layout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.no_proxy_radio)
|
||||
self.use_sysem_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.use_sysem_proxy_radio, ProxyMode.SYSTEM_PROXY)
|
||||
self.layout.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.use_sysem_proxy_radio)
|
||||
self.manual_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.manual_proxy_radio, ProxyMode.MANUAL_PROXY)
|
||||
self.layout.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.manual_proxy_radio)
|
||||
self.http_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('HTTP:', self.http_edit)
|
||||
self.https_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('HTTPS:', self.https_edit)
|
||||
self.username_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('Username:', self.username_edit)
|
||||
self.password_edit = QtWidgets.QLineEdit(self)
|
||||
self.password_edit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||
self.layout.addRow('Password:', self.password_edit)
|
||||
# Signal / Slots
|
||||
self.radio_group.buttonToggled.connect(self.on_radio_group_button_toggled)
|
||||
|
||||
def on_radio_group_button_toggled(self, button, checked):
|
||||
"""
|
||||
Handles the toggled signal on the radio buttons. The signal is emitted twice if a radio butting being toggled on
|
||||
causes another radio button in the group to be toggled off.
|
||||
|
||||
En/Disables the `Manual Proxy` line edits depending on the currently selected radio button
|
||||
|
||||
:param QtWidgets.QRadioButton button: The button that has toggled
|
||||
:param bool checked: The buttons new state
|
||||
"""
|
||||
id = self.radio_group.id(button) # The work around (see above comment)
|
||||
enable_manual_edits = id == ProxyMode.MANUAL_PROXY and checked
|
||||
self.http_edit.setEnabled(enable_manual_edits)
|
||||
self.https_edit.setEnabled(enable_manual_edits)
|
||||
self.username_edit.setEnabled(enable_manual_edits)
|
||||
self.password_edit.setEnabled(enable_manual_edits)
|
||||
|
||||
def retranslate_ui(self):
|
||||
"""
|
||||
Translate the Ui
|
||||
"""
|
||||
self.setTitle(translate('OpenLP.ProxyWidget', 'Proxy Server Settings'))
|
||||
self.no_proxy_radio.setText(translate('OpenLP.ProxyWidget', 'No prox&y'))
|
||||
self.use_sysem_proxy_radio.setText(translate('OpenLP.ProxyWidget', '&Use system proxy'))
|
||||
self.manual_proxy_radio.setText(translate('OpenLP.ProxyWidget', '&Manual proxy configuration'))
|
||||
proxy_example = translate('OpenLP.ProxyWidget', 'e.g. proxy_server_address:port_no')
|
||||
self.layout.labelForField(self.http_edit).setText(translate('OpenLP.ProxyWidget', 'HTTP:'))
|
||||
self.http_edit.setPlaceholderText(proxy_example)
|
||||
self.layout.labelForField(self.https_edit).setText(translate('OpenLP.ProxyWidget', 'HTTPS:'))
|
||||
self.https_edit.setPlaceholderText(proxy_example)
|
||||
self.layout.labelForField(self.username_edit).setText(translate('OpenLP.ProxyWidget', 'Username:'))
|
||||
self.layout.labelForField(self.password_edit).setText(translate('OpenLP.ProxyWidget', 'Password:'))
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load the data from the settings to the widget.
|
||||
"""
|
||||
settings = Settings()
|
||||
checked_radio = self.radio_group.button(settings.value('advanced/proxy mode'))
|
||||
checked_radio.setChecked(True)
|
||||
self.http_edit.setText(settings.value('advanced/proxy http'))
|
||||
self.https_edit.setText(settings.value('advanced/proxy https'))
|
||||
self.username_edit.setText(settings.value('advanced/proxy username'))
|
||||
self.password_edit.setText(settings.value('advanced/proxy password'))
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the widget data to the settings
|
||||
"""
|
||||
settings = Settings() # TODO: Migrate from old system
|
||||
settings.setValue('advanced/proxy mode', self.radio_group.checkedId())
|
||||
settings.setValue('advanced/proxy http', self.http_edit.text())
|
||||
settings.setValue('advanced/proxy https', self.https_edit.text())
|
||||
settings.setValue('advanced/proxy username', self.username_edit.text())
|
||||
settings.setValue('advanced/proxy password', self.password_edit.text())
|
@ -27,13 +27,14 @@ import tempfile
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common.httputils import get_user_agent, get_web_page, get_url_file_size, download_file
|
||||
from openlp.core.common.httputils import ProxyMode, download_file, get_proxy_settings, get_url_file_size, \
|
||||
get_user_agent, get_web_page
|
||||
from openlp.core.common.path import Path
|
||||
from openlp.core.common.settings import Settings
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
|
||||
class TestHttpUtils(TestCase, TestMixin):
|
||||
|
||||
"""
|
||||
A test suite to test out various http helper functions.
|
||||
"""
|
||||
@ -240,3 +241,119 @@ class TestHttpUtils(TestCase, TestMixin):
|
||||
# THEN: socket.timeout should have been caught
|
||||
# NOTE: Test is if $tmpdir/tempfile is still there, then test fails since ftw deletes bad downloaded files
|
||||
assert os.path.exists(self.tempfile) is False, 'tempfile should have been deleted'
|
||||
|
||||
|
||||
class TestGetProxySettings(TestCase, TestMixin):
|
||||
def setUp(self):
|
||||
self.build_settings()
|
||||
self.addCleanup(self.destroy_settings)
|
||||
|
||||
@patch('openlp.core.common.httputils.Settings')
|
||||
def test_mode_arg_specified(self, MockSettings):
|
||||
"""
|
||||
Test that the argument is used rather than reading the 'advanced/proxy mode' setting
|
||||
"""
|
||||
# GIVEN: Mocked settings
|
||||
mocked_settings = MagicMock()
|
||||
MockSettings.return_value = mocked_settings
|
||||
|
||||
# WHEN: Calling `get_proxy_settings` with the mode arg specified
|
||||
get_proxy_settings(mode=ProxyMode.NO_PROXY)
|
||||
|
||||
# THEN: The mode arg should have been used rather than looking it up in the settings
|
||||
mocked_settings.value.assert_not_called()
|
||||
|
||||
@patch('openlp.core.common.httputils.Settings')
|
||||
def test_mode_incorrect_arg_specified(self, MockSettings):
|
||||
"""
|
||||
Test that the system settings are used when the mode arg specieied is invalid
|
||||
"""
|
||||
# GIVEN: Mocked settings
|
||||
mocked_settings = MagicMock()
|
||||
MockSettings.return_value = mocked_settings
|
||||
|
||||
# WHEN: Calling `get_proxy_settings` with an invalid mode arg specified
|
||||
result = get_proxy_settings(mode='qwerty')
|
||||
|
||||
# THEN: An None should be returned
|
||||
mocked_settings.value.assert_not_called()
|
||||
assert result is None
|
||||
|
||||
def test_no_proxy_mode(self):
|
||||
"""
|
||||
Test that a dictionary with http and https values are set to None is returned, when `NO_PROXY` mode is specified
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of NO_PROXY
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.NO_PROXY)
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be a dictionary with http and https values set to None
|
||||
assert result == {'http': None, 'https': None}
|
||||
|
||||
def test_system_proxy_mode(self):
|
||||
"""
|
||||
Test that None is returned, when `SYSTEM_PROXY` mode is specified
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of SYSTEM_PROXY
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.SYSTEM_PROXY)
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be None
|
||||
assert result is None
|
||||
|
||||
def test_manual_proxy_mode_no_auth(self):
|
||||
"""
|
||||
Test that the correct proxy addresses are returned when basic authentication is not used
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with proxy servers, but no auth credentials are supplied
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', 'testhttp.server:port')
|
||||
Settings().setValue('advanced/proxy https', 'testhttps.server:port')
|
||||
Settings().setValue('advanced/proxy username', '')
|
||||
Settings().setValue('advanced/proxy password', '')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers without authentication
|
||||
assert result == {'http': 'http://testhttp.server:port', 'https': 'https://testhttps.server:port'}
|
||||
|
||||
def test_manual_proxy_mode_auth(self):
|
||||
"""
|
||||
Test that the correct proxy addresses are returned when basic authentication is used
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with proxy servers and auth credentials supplied
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', 'testhttp.server:port')
|
||||
Settings().setValue('advanced/proxy https', 'testhttps.server:port')
|
||||
Settings().setValue('advanced/proxy username', 'user')
|
||||
Settings().setValue('advanced/proxy password', 'pass')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers with the authentication credentials
|
||||
assert result == {'http': 'http://user:pass@testhttp.server:port',
|
||||
'https': 'https://user:pass@testhttps.server:port'}
|
||||
|
||||
def test_manual_proxy_mode_no_servers(self):
|
||||
"""
|
||||
Test that the system proxies are overidden when the MANUAL_PROXY mode is specified, but no server addresses are
|
||||
supplied
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with no servers specified
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', '')
|
||||
Settings().setValue('advanced/proxy https', '')
|
||||
Settings().setValue('advanced/proxy username', 'user')
|
||||
Settings().setValue('advanced/proxy password', 'pass')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers set to None
|
||||
assert result == {'http': None, 'https': None}
|
||||
|
174
tests/interfaces/openlp_core/widgets/test_widgets.py
Normal file
174
tests/interfaces/openlp_core/widgets/test_widgets.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2018 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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; version 2 of the License. #
|
||||
# #
|
||||
# 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, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Module to test the custom widgets.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import ProxyMode
|
||||
from openlp.core.widgets.widgets import ProxyWidget
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
|
||||
class TestProxyWidget(TestCase, TestMixin):
|
||||
"""
|
||||
Test the EditCustomForm.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Create the UI
|
||||
"""
|
||||
Registry.create()
|
||||
self.setup_application()
|
||||
|
||||
def test_radio_button_exclusivity_no_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `no_proxy_radio` button
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should not be enabled
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.manual_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is False
|
||||
assert proxy_widget.https_edit.isEnabled() is False
|
||||
assert proxy_widget.username_edit.isEnabled() is False
|
||||
assert proxy_widget.password_edit.isEnabled() is False
|
||||
|
||||
def test_radio_button_exclusivity_system_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `use_sysem_proxy_radio` button
|
||||
proxy_widget.use_sysem_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should not be enabled
|
||||
assert proxy_widget.no_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.manual_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is False
|
||||
assert proxy_widget.https_edit.isEnabled() is False
|
||||
assert proxy_widget.username_edit.isEnabled() is False
|
||||
assert proxy_widget.password_edit.isEnabled() is False
|
||||
|
||||
def test_radio_button_exclusivity_manual_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `manual_proxy_radio` button
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should be enabled
|
||||
assert proxy_widget.no_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is True
|
||||
assert proxy_widget.https_edit.isEnabled() is True
|
||||
assert proxy_widget.username_edit.isEnabled() is True
|
||||
assert proxy_widget.password_edit.isEnabled() is True
|
||||
|
||||
def test_proxy_widget_load_default_settings(self):
|
||||
"""
|
||||
Test that the default settings are loaded from the config correctly
|
||||
"""
|
||||
# GIVEN: And instance of the widget with default settings
|
||||
proxy_widget = ProxyWidget()
|
||||
|
||||
# WHEN: Calling the `load` method
|
||||
proxy_widget.load()
|
||||
|
||||
# THEN: The widget should be in its default state
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is True
|
||||
assert proxy_widget.http_edit.text() == ''
|
||||
assert proxy_widget.https_edit.text() == ''
|
||||
assert proxy_widget.username_edit.text() == ''
|
||||
assert proxy_widget.password_edit.text() == ''
|
||||
|
||||
@patch.object(ProxyWidget, 'load')
|
||||
@patch('openlp.core.widgets.widgets.Settings')
|
||||
def test_proxy_widget_save_no_proxy_settings(self, settings_patcher, proxy_widget_load_patcher):
|
||||
"""
|
||||
Test that the settings are saved correctly
|
||||
"""
|
||||
# GIVEN: A Mocked settings instance of the proxy widget with some known values set
|
||||
settings_instance = MagicMock()
|
||||
settings_patcher.return_value = settings_instance
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
proxy_widget.http_edit.setText('')
|
||||
proxy_widget.https_edit.setText('')
|
||||
proxy_widget.username_edit.setText('')
|
||||
proxy_widget.password_edit.setText('')
|
||||
|
||||
# WHEN: Calling save
|
||||
proxy_widget.save()
|
||||
|
||||
# THEN: The settings should be set as expected
|
||||
settings_instance.setValue.assert_has_calls(
|
||||
[call('advanced/proxy mode', ProxyMode.NO_PROXY),
|
||||
call('advanced/proxy http', ''),
|
||||
call('advanced/proxy https', ''),
|
||||
call('advanced/proxy username', ''),
|
||||
call('advanced/proxy password', '')])
|
||||
|
||||
@patch.object(ProxyWidget, 'load')
|
||||
@patch('openlp.core.widgets.widgets.Settings')
|
||||
def test_proxy_widget_save_manual_settings(self, settings_patcher, proxy_widget_load_patcher):
|
||||
"""
|
||||
Test that the settings are saved correctly
|
||||
"""
|
||||
# GIVEN: A Mocked and instance of the proxy widget with some known values set
|
||||
settings_instance = MagicMock()
|
||||
settings_patcher.return_value = settings_instance
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
proxy_widget.http_edit.setText('http_proxy_server:port')
|
||||
proxy_widget.https_edit.setText('https_proxy_server:port')
|
||||
proxy_widget.username_edit.setText('username')
|
||||
proxy_widget.password_edit.setText('password')
|
||||
|
||||
# WHEN: Calling save
|
||||
proxy_widget.save()
|
||||
|
||||
# THEN: The settings should be set as expected
|
||||
settings_instance.setValue.assert_has_calls(
|
||||
[call('advanced/proxy mode', ProxyMode.MANUAL_PROXY),
|
||||
call('advanced/proxy http', 'http_proxy_server:port'),
|
||||
call('advanced/proxy https', 'https_proxy_server:port'),
|
||||
call('advanced/proxy username', 'username'),
|
||||
call('advanced/proxy password', 'password')])
|
Loading…
Reference in New Issue
Block a user