Merge branch 'read-remote-version-from-file' into 'master'

Update the remote settings to use the remote's version.js file

See merge request openlp/openlp!421
This commit is contained in:
Tomas Groth 2022-02-18 16:24:22 +00:00
commit 962f36967a
6 changed files with 364 additions and 77 deletions

View File

@ -23,6 +23,7 @@ Download and "install" the remote web client
""" """
import json import json
import logging import logging
import re
from datetime import date from datetime import date
from zipfile import ZipFile from zipfile import ZipFile
@ -34,6 +35,7 @@ from openlp.core.common.registry import Registry
from openlp.core.threading import ThreadWorker, run_thread from openlp.core.threading import ThreadWorker, run_thread
REMOTE_URL = 'https://get.openlp.org/remote/' REMOTE_URL = 'https://get.openlp.org/remote/'
LOCAL_VERSION = re.compile(r'appVersion.*=.*\'(.*?)\';')
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -117,7 +119,7 @@ def get_latest_size():
return version_info['latest']['size'] return version_info['latest']['size']
def download_and_check(callback=None, can_update_range=True): def download_and_install(callback=None, can_update_range=True):
""" """
Download the web site and deploy it. Download the web site and deploy it.
""" """
@ -151,3 +153,18 @@ def check_for_remote_update(main_window):
# TODO: Use this to figure out if there's an Internet connection? # TODO: Use this to figure out if there's an Internet connection?
# worker.no_internet.connect(main_window.on_no_internet) # worker.no_internet.connect(main_window.on_no_internet)
run_thread(worker, 'remote-version') run_thread(worker, 'remote-version')
def get_installed_version():
"""
Get the version of the remote that is installed, or None if there is no remote
"""
version_file = AppLocation.get_section_data_path('remotes') / 'assets' / 'version.js'
if not version_file.exists():
return None
version_read = version_file.read()
print(version_read)
match = LOCAL_VERSION.search(version_read)
if not match:
return None
return match.group(1)

View File

@ -30,7 +30,7 @@ from time import sleep
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.api.deploy import download_and_check, download_version_info from openlp.core.api.deploy import download_and_install, download_version_info, get_installed_version
from openlp.core.common import get_network_interfaces from openlp.core.common import get_network_interfaces
from openlp.core.common.i18n import translate from openlp.core.common.i18n import translate
from openlp.core.common.registry import Registry from openlp.core.common.registry import Registry
@ -50,7 +50,8 @@ class ApiTab(SettingsTab):
def __init__(self, parent): def __init__(self, parent):
self.icon_path = UiIcons().remote self.icon_path = UiIcons().remote
advanced_translated = translate('OpenLP.APITab', 'API') advanced_translated = translate('OpenLP.APITab', 'API')
self._master_version = None self._available_version = None
self._installed_version = None
super(ApiTab, self).__init__(parent, 'api', advanced_translated) super(ApiTab, self).__init__(parent, 'api', advanced_translated)
def setup_ui(self): def setup_ui(self):
@ -138,25 +139,25 @@ class ApiTab(SettingsTab):
self.web_remote_group_box.setObjectName('web_remote_group_box') self.web_remote_group_box.setObjectName('web_remote_group_box')
self.web_remote_layout = QtWidgets.QGridLayout(self.web_remote_group_box) self.web_remote_layout = QtWidgets.QGridLayout(self.web_remote_group_box)
self.web_remote_layout.setObjectName('web_remote_layout') self.web_remote_layout.setObjectName('web_remote_layout')
self.current_version_label = QtWidgets.QLabel(self.web_remote_group_box) self.installed_version_label = QtWidgets.QLabel(self.web_remote_group_box)
self.web_remote_layout.addWidget(self.current_version_label, 0, 0) self.web_remote_layout.addWidget(self.installed_version_label, 0, 0)
self.current_version_label.setObjectName('current_version_label') self.installed_version_label.setObjectName('installed_version_label')
self.current_version_value = QtWidgets.QLabel(self.web_remote_group_box) self.installed_version_value = QtWidgets.QLabel(self.web_remote_group_box)
self.current_version_value.setObjectName('current_version_value') self.installed_version_value.setObjectName('installed_version_value')
self.web_remote_layout.addWidget(self.current_version_value, 0, 1) self.web_remote_layout.addWidget(self.installed_version_value, 0, 1)
self.upgrade_button = QtWidgets.QPushButton(self.web_remote_group_box) self.check_for_updates_button = QtWidgets.QPushButton(self.web_remote_group_box)
self.upgrade_button.setEnabled(False) self.check_for_updates_button.setObjectName('check_for_updates_button')
self.upgrade_button.setObjectName('upgrade_button') self.web_remote_layout.addWidget(self.check_for_updates_button, 0, 2)
self.web_remote_layout.addWidget(self.upgrade_button, 0, 2) self.available_version_label = QtWidgets.QLabel(self.web_remote_group_box)
self.master_version_label = QtWidgets.QLabel(self.web_remote_group_box) self.available_version_label.setObjectName('available_version_label')
self.master_version_label.setObjectName('master_version_label') self.web_remote_layout.addWidget(self.available_version_label, 1, 0)
self.web_remote_layout.addWidget(self.master_version_label, 1, 0) self.available_version_value = QtWidgets.QLabel(self.web_remote_group_box)
self.master_version_value = QtWidgets.QLabel(self.web_remote_group_box) self.available_version_value.setObjectName('available_version_value')
self.master_version_value.setObjectName('master_version_value') self.web_remote_layout.addWidget(self.available_version_value, 1, 1)
self.web_remote_layout.addWidget(self.master_version_value, 1, 1) self.install_button = QtWidgets.QPushButton(self.web_remote_group_box)
self.check_version_button = QtWidgets.QPushButton(self.web_remote_group_box) self.install_button.setEnabled(False)
self.check_version_button.setObjectName('check_version_button') self.install_button.setObjectName('install_button')
self.web_remote_layout.addWidget(self.check_version_button, 1, 2) self.web_remote_layout.addWidget(self.install_button, 1, 2)
self.left_layout.addWidget(self.web_remote_group_box) self.left_layout.addWidget(self.web_remote_group_box)
self.app_group_box = QtWidgets.QGroupBox(self.right_column) self.app_group_box = QtWidgets.QGroupBox(self.right_column)
self.app_group_box.setObjectName('app_group_box') self.app_group_box.setObjectName('app_group_box')
@ -199,8 +200,8 @@ class ApiTab(SettingsTab):
self.twelve_hour_check_box.stateChanged.connect(self.on_twelve_hour_check_box_changed) self.twelve_hour_check_box.stateChanged.connect(self.on_twelve_hour_check_box_changed)
self.thumbnails_check_box.stateChanged.connect(self.on_thumbnails_check_box_changed) self.thumbnails_check_box.stateChanged.connect(self.on_thumbnails_check_box_changed)
self.address_edit.textChanged.connect(self.set_urls) self.address_edit.textChanged.connect(self.set_urls)
self.upgrade_button.clicked.connect(self.on_upgrade_button_clicked) self.install_button.clicked.connect(self.on_install_button_clicked)
self.check_version_button.clicked.connect(self.on_check_version_button_clicked) self.check_for_updates_button.clicked.connect(self.on_check_for_updates_button_clicked)
def retranslate_ui(self): def retranslate_ui(self):
self.tab_title_visible = translate('RemotePlugin.RemoteTab', 'Remote Interface') self.tab_title_visible = translate('RemotePlugin.RemoteTab', 'Remote Interface')
@ -221,12 +222,13 @@ class ApiTab(SettingsTab):
translate('RemotePlugin.RemoteTab', 'Scan the QR code to open the remote view on your mobile device')) translate('RemotePlugin.RemoteTab', 'Scan the QR code to open the remote view on your mobile device'))
self.user_login_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'User Authentication')) self.user_login_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'User Authentication'))
self.web_remote_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Web Remote')) self.web_remote_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Web Remote'))
self.check_version_button.setText(translate('RemotePlugin.RemoteTab', 'Check for Updates')) self.check_for_updates_button.setText(translate('RemotePlugin.RemoteTab', 'Check for Updates'))
self.upgrade_button.setText(translate('RemotePlugin.RemoteTab', 'Upgrade')) self.install_button.setText(translate('RemotePlugin.RemoteTab', 'Install'))
self.user_id_label.setText(translate('RemotePlugin.RemoteTab', 'User id:')) self.user_id_label.setText(translate('RemotePlugin.RemoteTab', 'User id:'))
self.password_label.setText(translate('RemotePlugin.RemoteTab', 'Password:')) self.password_label.setText(translate('RemotePlugin.RemoteTab', 'Password:'))
self.current_version_label.setText(translate('RemotePlugin.RemoteTab', 'Current version:')) self.installed_version_label.setText(translate('RemotePlugin.RemoteTab', 'Installed version:'))
self.master_version_label.setText(translate('RemotePlugin.RemoteTab', 'Latest version:')) self._not_installed_version = translate('RemotePlugin.RemoteTab', '(not installed)')
self.available_version_label.setText(translate('RemotePlugin.RemoteTab', 'Latest version:'))
self._unknown_version = translate('RemotePlugin.RemoteTab', '(unknown)') self._unknown_version = translate('RemotePlugin.RemoteTab', '(unknown)')
self.server_state_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Server Status')) self.server_state_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Server Status'))
self.server_http_state_title.setText(translate('RemotePlugin.RemoteTab', 'HTTP Server:')) self.server_http_state_title.setText(translate('RemotePlugin.RemoteTab', 'HTTP Server:'))
@ -237,34 +239,49 @@ class ApiTab(SettingsTab):
self._server_disabled = translate('RemotePlugin.RemoteTab', 'Disabled', 'Server is disabled') self._server_disabled = translate('RemotePlugin.RemoteTab', 'Disabled', 'Server is disabled')
@property @property
def master_version(self): def available_version(self):
""" """
Property getter for the remote master version Property getter for the available version
""" """
return self._master_version return self._available_version
@master_version.setter @available_version.setter
def master_version(self, value): def available_version(self, value):
""" """
Property setter for the remote master version Property setter for the available version
""" """
self._master_version = value self._available_version = value
self.master_version_value.setText(self._master_version or self._unknown_version) self.available_version_value.setText(self._available_version or self._unknown_version)
self.upgrade_button.setEnabled(self.can_enable_upgrade_button()) self.install_button.setEnabled(self.can_enable_install_button())
def can_enable_upgrade_button(self): @property
def installed_version(self):
""" """
Do a couple checks to set the upgrade button state Property getter for the installed version
""" """
return self.master_version_value.text() != self._unknown_version and \ return self._installed_version
self.master_version_value.text() != self.current_version_value.text()
def set_master_version(self): @installed_version.setter
def installed_version(self, value):
"""
Property setter for the installed version
"""
self._installed_version = value
self.installed_version_value.setText(self._installed_version or self._not_installed_version)
def can_enable_install_button(self):
"""
Do a couple checks to set the install button state
"""
return self.available_version_value.text() != self._unknown_version and \
self.available_version_value.text() != self.installed_version_value.text()
def validate_available_version(self):
""" """
Check if the master version is not set, and set it to None to invoke the "unknown version" label Check if the master version is not set, and set it to None to invoke the "unknown version" label
""" """
if not self._master_version: if not self._available_version:
self.master_version = None self.available_version = None
def set_urls(self): def set_urls(self):
""" """
@ -281,7 +298,7 @@ class ApiTab(SettingsTab):
image = QtGui.QPixmap.fromImage(img) image = QtGui.QPixmap.fromImage(img)
self.app_qr_code_label.setPixmap(image) self.app_qr_code_label.setPixmap(image)
def get_server_states(self): def set_server_states(self):
""" """
Update the display with the current state of the servers Update the display with the current state of the servers
""" """
@ -333,10 +350,13 @@ class ApiTab(SettingsTab):
self.user_login_group_box.setChecked(self.settings.value('api/authentication enabled')) self.user_login_group_box.setChecked(self.settings.value('api/authentication enabled'))
self.user_id.setText(self.settings.value('api/user id')) self.user_id.setText(self.settings.value('api/user id'))
self.password.setText(self.settings.value('api/password')) self.password.setText(self.settings.value('api/password'))
self.current_version_value.setText(self.settings.value('api/download version')) self.installed_version = get_installed_version()
self.set_master_version() # TODO: Left in for backwards compatibilty, remove eventually
if not self.installed_version:
self.installed_version = self.settings.value('api/download version')
self.validate_available_version()
self.set_urls() self.set_urls()
self.get_server_states() self.set_server_states()
def save(self): def save(self):
""" """
@ -376,7 +396,7 @@ class ApiTab(SettingsTab):
if check_state == QtCore.Qt.Checked: if check_state == QtCore.Qt.Checked:
self.thumbnails = True self.thumbnails = True
def on_check_version_button_clicked(self): def on_check_for_updates_button_clicked(self):
""" """
Check for the latest version on the server Check for the latest version on the server
""" """
@ -385,28 +405,31 @@ class ApiTab(SettingsTab):
app.process_events() app.process_events()
version_info = download_version_info() version_info = download_version_info()
app.process_events() app.process_events()
self.master_version = version_info['latest']['version'] self.available_version = version_info['latest']['version']
app.process_events() app.process_events()
app.set_normal_cursor() app.set_normal_cursor()
app.process_events() app.process_events()
if self.can_enable_upgrade_button(): if self.can_enable_install_button():
Registry().get('main_window').information_message('New version available!', Registry().get('main_window').information_message(
'There\'s a new version of the web remote available.') translate('OpenLP.APITab', 'New version available!'),
translate('OpenLP.APITab', 'There\'s a new version of the web remote available.')
)
def on_upgrade_button_clicked(self): def on_install_button_clicked(self):
""" """
Download/upgrade the web remote Download/install the web remote
""" """
app = Registry().get('application') app = Registry().get('application')
progress = DownloadProgressDialog(self, app) progress = DownloadProgressDialog(self, app)
progress.show() progress.show()
app.process_events() app.process_events()
sleep(0.5) sleep(0.5)
downloaded_version = download_and_check(progress) downloaded_version = download_and_install(progress)
app.process_events() app.process_events()
sleep(0.5) sleep(0.5)
progress.close() progress.close()
app.process_events() app.process_events()
self.current_version_value.setText(downloaded_version) self.installed_version = downloaded_version
# TODO: Left in for backwards compatibilty for versions of the remote prior to 0.9.8, and versions
# of OpenLP prior to 2.9.5. We need to remove this eventually.
self.settings.setValue('api/download version', downloaded_version) self.settings.setValue('api/download version', downloaded_version)
self.upgrade_button.setEnabled(self.can_enable_upgrade_button())

View File

@ -208,7 +208,7 @@ class Settings(QtCore.QSettings):
'api/authentication enabled': False, 'api/authentication enabled': False,
'api/ip address': '0.0.0.0', 'api/ip address': '0.0.0.0',
'api/thumbnails': True, 'api/thumbnails': True,
'api/download version': '0.0', 'api/download version': None,
'api/last version test': '', 'api/last version test': '',
'api/update check': True, 'api/update check': True,
'bibles/db type': 'sqlite', 'bibles/db type': 'sqlite',

View File

@ -32,7 +32,7 @@ from tempfile import gettempdir
from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5 import QtCore, QtWidgets, QtGui
from openlp.core.api.deploy import get_latest_size, download_and_check from openlp.core.api.deploy import get_latest_size, download_and_install
from openlp.core.common import trace_error_handler from openlp.core.common import trace_error_handler
from openlp.core.common.applocation import AppLocation from openlp.core.common.applocation import AppLocation
from openlp.core.common.httputils import DownloadWorker, download_file, get_url_file_size, get_web_page from openlp.core.common.httputils import DownloadWorker, download_file, get_url_file_size, get_web_page
@ -539,7 +539,7 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties):
if self.remote_page.can_download_remote: if self.remote_page.can_download_remote:
self._increment_progress_bar(self.downloading.format(name='Web Remote'), 0) self._increment_progress_bar(self.downloading.format(name='Web Remote'), 0)
self.previous_size = 0 self.previous_size = 0
remote_version = download_and_check(self, can_update_range=False) remote_version = download_and_install(self, can_update_range=False)
if remote_version: if remote_version:
self.settings.setValue('api/download version', remote_version) self.settings.setValue('api/download version', remote_version)
else: else:

View File

@ -22,7 +22,8 @@ import json
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from openlp.core.api.deploy import REMOTE_URL, deploy_zipfile, download_version_info, download_and_check from openlp.core.api.deploy import REMOTE_URL, deploy_zipfile, download_version_info, download_and_install, \
get_installed_version
CONFIG_FILE = '{"latest": {"version": "0.1", "filename": "remote-0.1.zip", "sha256": "", "size": 854039}}' CONFIG_FILE = '{"latest": {"version": "0.1", "filename": "remote-0.1.zip", "sha256": "", "size": 854039}}'
@ -100,15 +101,15 @@ def test_download_version_info(mocked_get_web_page, mocked_get_openlp_user_agent
@patch('openlp.core.api.deploy.log.warning') @patch('openlp.core.api.deploy.log.warning')
@patch('openlp.core.api.deploy.download_version_info') @patch('openlp.core.api.deploy.download_version_info')
def test_download_and_check_log_warning(mocked_download_version_info, mocked_warning): def test_download_and_install_log_warning(mocked_download_version_info, mocked_warning):
""" """
Test that when the version info fails, a warning is logged Test that when the version info fails, a warning is logged
""" """
# GIVEN: A few mocks, and a version info of None # GIVEN: A few mocks, and a version info of None
mocked_download_version_info.return_value = None mocked_download_version_info.return_value = None
# WHEN: download_and_check is run # WHEN: download_and_install is run
result = download_and_check(None) result = download_and_install(None)
# THEN: None is returned and a warning is logged # THEN: None is returned and a warning is logged
assert result is None, 'The result should be None' assert result is None, 'The result should be None'
@ -118,7 +119,7 @@ def test_download_and_check_log_warning(mocked_download_version_info, mocked_war
@patch('openlp.core.api.deploy.AppLocation.get_section_data_path') @patch('openlp.core.api.deploy.AppLocation.get_section_data_path')
@patch('openlp.core.api.deploy.download_file') @patch('openlp.core.api.deploy.download_file')
@patch('openlp.core.api.deploy.download_version_info') @patch('openlp.core.api.deploy.download_version_info')
def test_download_and_check_download_fails(mocked_download_version_info, mocked_download_file, def test_download_and_install_download_fails(mocked_download_version_info, mocked_download_file,
mocked_get_section_data_path): mocked_get_section_data_path):
""" """
Test that when the version info fails, a warning is logged Test that when the version info fails, a warning is logged
@ -129,8 +130,8 @@ def test_download_and_check_download_fails(mocked_download_version_info, mocked_
mocked_download_file.return_value = False mocked_download_file.return_value = False
mocked_get_section_data_path.return_value = Path('.') mocked_get_section_data_path.return_value = Path('.')
# WHEN: download_and_check is run # WHEN: download_and_install is run
result = download_and_check(mocked_callback) result = download_and_install(mocked_callback)
# THEN: None is returned and a warning is logged # THEN: None is returned and a warning is logged
assert result is None, 'The result should be None' assert result is None, 'The result should be None'
@ -140,7 +141,7 @@ def test_download_and_check_download_fails(mocked_download_version_info, mocked_
@patch('openlp.core.api.deploy.deploy_zipfile') @patch('openlp.core.api.deploy.deploy_zipfile')
@patch('openlp.core.api.deploy.download_file') @patch('openlp.core.api.deploy.download_file')
@patch('openlp.core.api.deploy.download_version_info') @patch('openlp.core.api.deploy.download_version_info')
def test_download_and_check(mocked_download_version_info, mocked_download_file, mocked_deploy_zipfile, def test_download_and_install(mocked_download_version_info, mocked_download_file, mocked_deploy_zipfile,
mocked_get_section_data_path): mocked_get_section_data_path):
# GIVEN: A bunch of mocks # GIVEN: A bunch of mocks
mocked_callback = MagicMock() mocked_callback = MagicMock()
@ -150,10 +151,60 @@ def test_download_and_check(mocked_download_version_info, mocked_download_file,
mocked_remote_zip = mocked_remote_path / 'remote.zip' mocked_remote_zip = mocked_remote_path / 'remote.zip'
mocked_get_section_data_path.return_value = mocked_remote_path mocked_get_section_data_path.return_value = mocked_remote_path
# WHEN: download_and_check() is called # WHEN: download_and_install() is called
result = download_and_check(mocked_callback) result = download_and_install(mocked_callback)
# THEN: The correct things should have been done # THEN: The correct things should have been done
assert result == CONFIG_DICT['latest']['version'], 'The correct version is returned' assert result == CONFIG_DICT['latest']['version'], 'The correct version is returned'
mocked_download_file.assert_called_once_with(mocked_callback, REMOTE_URL + '0.1/remote-0.1.zip', mocked_remote_zip) mocked_download_file.assert_called_once_with(mocked_callback, REMOTE_URL + '0.1/remote-0.1.zip', mocked_remote_zip)
mocked_deploy_zipfile.assert_called_once_with(mocked_remote_path, 'remote.zip') mocked_deploy_zipfile.assert_called_once_with(mocked_remote_path, 'remote.zip')
@patch('openlp.core.api.deploy.AppLocation.get_section_data_path')
def test_get_installed_version_not_installed(mocked_get_section_data_path):
"""Test that if there is no remote installed, None is returned"""
# GIVEN: A mocked AppLocation and no file installed
mocked_version_file = MagicMock()
mocked_version_file.__truediv__.return_value = mocked_version_file
mocked_version_file.exists.return_value = False
mocked_get_section_data_path.return_value = mocked_version_file
# WHEN: get_installed_version() is called but there is no version file
result = get_installed_version()
# THEN: The result should be None
assert result is None
@patch('openlp.core.api.deploy.AppLocation.get_section_data_path')
def test_get_installed_version_no_version(mocked_get_section_data_path):
"""Test that if there is no matching version number, None is returned"""
# GIVEN: A mocked AppLocation and no file installed
mocked_version_file = MagicMock()
mocked_version_file.__truediv__.return_value = mocked_version_file
mocked_version_file.exists.return_value = True
mocked_version_file.read.return_value = 'let app_version = 0.9.7;'
mocked_get_section_data_path.return_value = mocked_version_file
# WHEN: get_installed_version() is called but there is no version in the file
result = get_installed_version()
# THEN: The result should be None
assert result is None
@patch('openlp.core.api.deploy.AppLocation.get_section_data_path')
def test_get_installed_version(mocked_get_section_data_path):
"""Test that get_installed_version returns the version number"""
# GIVEN: A mocked AppLocation and no file installed
mocked_version_file = MagicMock()
mocked_version_file.__truediv__.return_value = mocked_version_file
mocked_version_file.exists.return_value = True
mocked_version_file.read.return_value = 'let appVersion = \'0.9.7\';'
mocked_get_section_data_path.return_value = mocked_version_file
# WHEN: get_installed_version() is called but there is no version file
result = get_installed_version()
# THEN: The result should be None
assert result == '0.9.7'

View File

@ -24,6 +24,7 @@ This module contains tests for the lib submodule of the Remotes plugin.
import hashlib import hashlib
import pytest import pytest
import re import re
from unittest.mock import MagicMock, patch
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
@ -114,22 +115,217 @@ def test_address_revert_button_clicked(api_tab, settings):
assert api_tab.address_edit.text() == settings.get_default_value('api/ip address') assert api_tab.address_edit.text() == settings.get_default_value('api/ip address')
def test_save(api_tab, settings): @patch('openlp.core.api.tab.QtWidgets.QMessageBox.information')
def test_save(mocked_information, api_tab, registry, settings):
""" """
Test the IP revert function works Test the save method works correctly
""" """
# GIVEN: The ip address text set to a non default value # GIVEN: Various settings are set on the form and a mocked settings form
api_tab.address_edit.setText(settings.value('api/ip address')) mocked_settings_form = MagicMock()
registry.remove('settings_form')
registry.register('settings_form', mocked_settings_form)
settings.setValue('api/ip address', '0.0.0.0')
api_tab.address_edit.setText('192.168.1.1')
api_tab.twelve_hour = True api_tab.twelve_hour = True
api_tab.thumbnails = True api_tab.thumbnails = True
api_tab.user_login_group_box.setChecked(True) api_tab.user_login_group_box.setChecked(True)
api_tab.user_id.setText('user id thing') api_tab.user_id.setText('user id thing')
api_tab.password.setText('user password thing') api_tab.password.setText('user password thing')
# WHEN: save is called # WHEN: save is called
api_tab.save() api_tab.save()
# THEN: The text should have been changed to the default value # THEN: The text should have been changed to the default value
mocked_information.assert_called_once_with(api_tab, 'Restart Required',
'This change will only take effect once OpenLP has been restarted.')
mocked_settings_form.register_post_process.called_once_with('remotes_config_updated')
assert settings.value('api/twelve hour') is True assert settings.value('api/twelve hour') is True
assert settings.value('api/thumbnails') is True assert settings.value('api/thumbnails') is True
assert settings.value('api/authentication enabled') is True assert settings.value('api/authentication enabled') is True
assert settings.value('api/user id') == 'user id thing' assert settings.value('api/user id') == 'user id thing'
assert settings.value('api/password') == 'user password thing' assert settings.value('api/password') == 'user password thing'
def test_available_version_property_get_none(api_tab):
"""Test that the available version property is None on init"""
# GIVEN: An uninitialised API tab
# WHEN: the available version is GET'ed
result = api_tab.available_version
# THEN: The result is None
assert result is None
def test_available_version_property_set(api_tab):
"""Test that the available version property is set correctly"""
# GIVEN: An uninitialised API tab
available_version = '0.9.7'
# WHEN: the available version is SET
api_tab.available_version = available_version
# THEN: The internal value should be set, and the right methods should have been called
assert api_tab._available_version == available_version
assert api_tab.available_version_value.text() == available_version
def test_available_version_property_set_none(api_tab):
"""Test that the available version property is set correctly"""
# GIVEN: An uninitialised API tab
available_version = None
# WHEN: the available version is SET
api_tab.available_version = available_version
# THEN: The internal value should be set, and the right methods should have been called
assert api_tab._available_version == available_version
assert api_tab.available_version_value.text() == '(unknown)'
def test_installed_version_property_get_none(api_tab):
"""Test that the installed version property is None on init"""
# GIVEN: An uninitialised API tab
# WHEN: the installed version is GET'ed
result = api_tab.installed_version
# THEN: The result is None
assert result is None
def test_installed_version_property_set(api_tab):
"""Test that the installed version property is set correctly"""
# GIVEN: An uninitialised API tab
installed_version = '0.9.7'
# WHEN: the installed version is SET
api_tab.installed_version = installed_version
# THEN: The internal value should be set, and the right methods should have been called
assert api_tab._installed_version == installed_version
assert api_tab.installed_version_value.text() == installed_version
def test_installed_version_property_set_none(api_tab):
"""Test that the installed version property is set correctly"""
# GIVEN: An uninitialised API tab
installed_version = None
# WHEN: the installed version is SET
api_tab.installed_version = installed_version
# THEN: The internal value should be set, and the right methods should have been called
assert api_tab._installed_version == installed_version
assert api_tab.installed_version_value.text() == '(not installed)'
def test_validate_available_version(api_tab):
"""Test that the validate_available_version() method sets the label correctly"""
# GIVEN: An uninitialised API tab
# WHEN: validate_available_version() is run
api_tab.validate_available_version()
# THEN: The label should say "(unknown)"
assert api_tab.available_version_value.text() == '(unknown)'
@patch('openlp.core.api.tab.is_thread_finished')
def test_set_server_states_up(mock_is_thread_finished, registry, settings, api_tab):
"""Test getting the server states when the servers are up"""
# GIVEN: An API tab and some mocks
mock_is_thread_finished.return_value = False
# WHEN: set_server_states() is called
api_tab.set_server_states()
# THEN: The servers should all be "up"
assert api_tab.server_http_state.text() == 'Active'
assert api_tab.server_websocket_state.text() == 'Active'
assert api_tab.server_zeroconf_state.text() == 'Active'
@patch('openlp.core.api.tab.is_thread_finished')
def test_set_server_states_disabled(mock_is_thread_finished, registry, settings, api_tab):
"""Test getting the server states when the servers are disabled"""
# GIVEN: An API tab and some mocks
mock_is_thread_finished.return_value = True
registry.set_flag('no_web_server', True)
# WHEN: set_server_states() is called
api_tab.set_server_states()
# THEN: The servers should all be "up"
assert api_tab.server_http_state.text() == 'Disabled'
assert api_tab.server_websocket_state.text() == 'Disabled'
assert api_tab.server_zeroconf_state.text() == 'Disabled'
@patch('openlp.core.api.tab.is_thread_finished')
def test_set_server_states_down(mock_is_thread_finished, registry, settings, api_tab):
"""Test getting the server states when the servers are down"""
# GIVEN: An API tab and some mocks
mock_is_thread_finished.return_value = True
registry.set_flag('no_web_server', False)
# WHEN: set_server_states() is called
api_tab.set_server_states()
# THEN: The servers should all be "up"
assert api_tab.server_http_state.text() == 'Failed'
assert api_tab.server_websocket_state.text() == 'Failed'
assert api_tab.server_zeroconf_state.text() == 'Failed'
@patch('openlp.core.api.tab.download_version_info')
def test_on_check_for_updates_button_clicked(mocked_download_version_info, mocked_qapp, registry, settings, api_tab):
"""Test that the correct methods are called when the Check for Updates button is clicked"""
# GIVEN: An API tab and a couple of mocks
mocked_download_version_info.return_value = {'latest': {'version': '0.9.5'}}
mocked_main_window = MagicMock()
registry.register('main_window', mocked_main_window)
registry.remove('application')
registry.register('application', mocked_qapp)
# WHEN: The Check for Updates button is clicked
with patch.object(api_tab, 'can_enable_install_button') as mocked_can_enable_install_button:
mocked_can_enable_install_button.return_value = True
api_tab.on_check_for_updates_button_clicked()
assert mocked_can_enable_install_button.call_count == 2
# THEN: The correct methods were called
mocked_qapp.set_busy_cursor.assert_called_once()
assert mocked_qapp.process_events.call_count == 4
mocked_qapp.set_normal_cursor.assert_called_once()
mocked_download_version_info.assert_called_once()
mocked_main_window.information_message.assert_called_once_with(
'New version available!', 'There\'s a new version of the web remote available.'
)
assert api_tab.available_version == '0.9.5'
@patch('openlp.core.api.tab.DownloadProgressDialog')
@patch('openlp.core.api.tab.download_and_install')
@patch('openlp.core.api.tab.sleep')
def test_on_install_button_clicked(mocked_sleep, mocked_download_and_install, MockDownloadProgressDialog,
mocked_qapp, registry, settings, api_tab):
"""Test that the correct methods are called when the Check for Updates button is clicked"""
# GIVEN: An API tab and a couple of mocks
mocked_download_and_install.return_value = '0.9.6'
mocked_progress = MagicMock()
MockDownloadProgressDialog.return_value = mocked_progress
registry.remove('application')
registry.register('application', mocked_qapp)
# WHEN: The Check for Updates button is clicked
api_tab.on_install_button_clicked()
# THEN: The correct methods were called
assert mocked_qapp.process_events.call_count == 3
MockDownloadProgressDialog.assert_called_once_with(api_tab, mocked_qapp)
mocked_progress.show.assert_called_once()
mocked_progress.close.assert_called_once()
mocked_download_and_install.assert_called_once_with(mocked_progress)
assert api_tab.installed_version == '0.9.6'
assert settings.value('api/download version') == '0.9.6'