forked from openlp/openlp
Merge branch 'master' of gitlab.com:openlp/openlp
This commit is contained in:
commit
9eb645cc37
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@
|
||||
.vscode
|
||||
.eggs
|
||||
.venv
|
||||
.mypy_cache
|
||||
OpenLP.egg-info
|
||||
\#*\#
|
||||
__pycache__
|
||||
|
@ -63,19 +63,6 @@ test-macos:
|
||||
only:
|
||||
- master@openlp/openlp
|
||||
|
||||
test-windows:
|
||||
stage: test
|
||||
tags:
|
||||
- windows
|
||||
script:
|
||||
- C:\Users\raoul\GitLab-Runner\venv\Scripts\pytest.exe --color=no --disable-warnings --cov openlp
|
||||
- mv .coverage windows.coverage
|
||||
artifacts:
|
||||
paths:
|
||||
- windows.coverage
|
||||
only:
|
||||
- master@openlp/openlp
|
||||
|
||||
test-display:
|
||||
stage: test
|
||||
image: openlp/angular
|
||||
@ -87,7 +74,7 @@ pages:
|
||||
stage: deploy
|
||||
image: openlp/debian
|
||||
script:
|
||||
- python3-coverage combine linux.coverage macos.coverage windows.coverage
|
||||
- python3-coverage combine linux.coverage macos.coverage
|
||||
- fixpaths .coverage
|
||||
- python3-coverage html
|
||||
- mv htmlcov public
|
||||
@ -99,6 +86,5 @@ pages:
|
||||
dependencies:
|
||||
- test-debian
|
||||
- test-macos
|
||||
- test-windows
|
||||
only:
|
||||
- master@openlp/openlp
|
||||
|
@ -385,17 +385,12 @@ def main():
|
||||
application.setApplicationName('OpenLP')
|
||||
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||
# Set the libvlc environment variable if we're frozen
|
||||
if getattr(sys, 'frozen', False):
|
||||
if is_macosx():
|
||||
vlc_lib = 'libvlc.dylib'
|
||||
elif is_win():
|
||||
vlc_lib = 'libvlc.dll'
|
||||
# Path to libvlc
|
||||
os.environ['PYTHON_VLC_LIB_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc' / vlc_lib)
|
||||
log.debug('VLC Path: {}'.format(os.environ['PYTHON_VLC_LIB_PATH']))
|
||||
# Path to VLC directory containing VLC's "plugins" directory
|
||||
if getattr(sys, 'frozen', False) and is_win():
|
||||
# Path to libvlc and the plugins
|
||||
os.environ['PYTHON_VLC_LIB_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc' / 'libvlc.dll')
|
||||
os.environ['PYTHON_VLC_MODULE_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc')
|
||||
log.debug('VLC Path: {}'.format(os.environ['PYTHON_VLC_LIB_PATH']))
|
||||
log.debug('VLC Plugins Path: {}'.format(os.environ['PYTHON_VLC_MODULE_PATH']))
|
||||
# Initialise the Registry
|
||||
Registry.create()
|
||||
Registry().register('application', application)
|
||||
|
@ -38,6 +38,13 @@ from PyQt5.QtCore import QCryptographicHash as QHash
|
||||
from PyQt5.QtNetwork import QAbstractSocket, QHostAddress, QNetworkInterface
|
||||
from chardet.universaldetector import UniversalDetector
|
||||
|
||||
try:
|
||||
from distro import id as distro_id
|
||||
except ImportError:
|
||||
# The distro module is only valid for Linux, so if it doesn't exist, create a function that always returns False
|
||||
def distro_id():
|
||||
return False
|
||||
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
|
||||
@ -212,13 +219,17 @@ def is_macosx():
|
||||
return sys.platform.startswith('darwin')
|
||||
|
||||
|
||||
def is_linux():
|
||||
def is_linux(distro=None):
|
||||
"""
|
||||
Returns true if running on a system with a linux kernel e.g. Ubuntu, Debian, etc
|
||||
|
||||
:param distro: If not None, check if running that Linux distro
|
||||
:return: True if system is running a linux kernel false otherwise
|
||||
"""
|
||||
return sys.platform.startswith('linux')
|
||||
result = sys.platform.startswith('linux')
|
||||
if result and distro:
|
||||
result = result and distro == distro_id()
|
||||
return result
|
||||
|
||||
|
||||
def is_64bit_instance():
|
||||
|
@ -34,6 +34,7 @@ from PyQt5 import QtCore
|
||||
|
||||
from openlp.core.state import State
|
||||
from openlp.core.api.http import register_endpoint
|
||||
from openlp.core.common import is_linux, is_macosx
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||
from openlp.core.common.registry import Registry, RegistryBase
|
||||
@ -89,23 +90,35 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
self.vlc_player = VlcPlayer(self)
|
||||
State().add_service('mediacontroller', 0)
|
||||
State().add_service('media_live', 0)
|
||||
getvlc = get_vlc()
|
||||
if getvlc and pymediainfo_available:
|
||||
has_vlc = get_vlc()
|
||||
if has_vlc and pymediainfo_available:
|
||||
State().update_pre_conditions('mediacontroller', True)
|
||||
State().update_pre_conditions('media_live', True)
|
||||
else:
|
||||
if hasattr(self.main_window, 'splash') and self.main_window.splash.isVisible():
|
||||
self.main_window.splash.hide()
|
||||
text_vlc = translate('OpenLP.MediaController',
|
||||
'The media integration library is missing (python - vlc is not installed)')
|
||||
text_info = translate('OpenLP.MediaController',
|
||||
'The media integration library is missing (python - pymediainfo is not installed)')
|
||||
if not getvlc and not pymediainfo_available:
|
||||
State().missing_text('media_live', "{text}\n{base}".format(text=text_vlc, base=text_info))
|
||||
if getvlc and not pymediainfo_available:
|
||||
State().missing_text('media_live', "{text}".format(text=text_info))
|
||||
if not getvlc and pymediainfo_available:
|
||||
State().missing_text('media_live', "{text}".format(text=text_vlc))
|
||||
generic_message = translate('OpenLP.MediaController',
|
||||
'OpenLP requires the following libraries in order to show videos and other '
|
||||
'media, but they are not installed. Please install these libraries to enable '
|
||||
'media playback in OpenLP.')
|
||||
fedora_rpmfusion = translate('OpenLP.MediaController',
|
||||
'To install these libraries, you will need to enable the RPMFusion '
|
||||
'repository: https://rpmfusion.org/')
|
||||
message = ''
|
||||
if is_macosx():
|
||||
message = translate('OpenLP.MediaController',
|
||||
'macOS is missing VLC. Please download and install from the VLC web site: '
|
||||
'https://www.videolan.org/vlc/')
|
||||
else:
|
||||
packages = []
|
||||
if not has_vlc:
|
||||
packages.append('python3-vlc')
|
||||
if not pymediainfo_available:
|
||||
packages.append('python3-pymediainfo')
|
||||
message = generic_message + '\n\n' + ', '.join(packages)
|
||||
if not has_vlc and is_linux(distro='fedora'):
|
||||
message += '\n\n' + fedora_rpmfusion
|
||||
State().missing_text('media_live', message)
|
||||
return True
|
||||
|
||||
def bootstrap_post_set_up(self):
|
||||
|
@ -34,7 +34,6 @@ from openlp.core.common.actions import ActionList, CategoryOrder
|
||||
from openlp.core.common.i18n import UiStrings, translate
|
||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||
from openlp.core.common.registry import Registry, RegistryBase
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.display.screens import ScreenList
|
||||
from openlp.core.display.window import DisplayWindow
|
||||
from openlp.core.lib import ServiceItemAction, image_to_byte
|
||||
@ -324,7 +323,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.play_slides_once = create_action(self, 'playSlidesOnce', text=UiStrings().PlaySlidesToEnd,
|
||||
icon=UiIcons().clock, checked=False, can_shortcuts=True,
|
||||
category=self.category, triggers=self.on_play_slides_once)
|
||||
if Settings().value(self.main_window.advanced_settings_section + '/slide limits') == SlideLimits.Wrap:
|
||||
if self.settings.value(self.main_window.advanced_settings_section + '/slide limits') == SlideLimits.Wrap:
|
||||
self.play_slides_menu.setDefaultAction(self.play_slides_loop)
|
||||
else:
|
||||
self.play_slides_menu.setDefaultAction(self.play_slides_once)
|
||||
@ -697,13 +696,13 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
"""
|
||||
Adjusts the value of the ``delay_spin_box`` to the given one.
|
||||
"""
|
||||
self.delay_spin_box.setValue(Settings().value('core/loop delay'))
|
||||
self.delay_spin_box.setValue(self.settings.value('core/loop delay'))
|
||||
|
||||
def update_slide_limits(self):
|
||||
"""
|
||||
Updates the Slide Limits variable from the settings.
|
||||
"""
|
||||
self.slide_limits = Settings().value(self.main_window.advanced_settings_section + '/slide limits')
|
||||
self.slide_limits = self.settings.value(self.main_window.advanced_settings_section + '/slide limits')
|
||||
|
||||
def enable_tool_bar(self, item):
|
||||
"""
|
||||
@ -737,7 +736,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.play_slides_loop.setIcon(UiIcons().clock)
|
||||
self.play_slides_loop.setText(UiStrings().PlaySlidesInLoop)
|
||||
if item.is_text():
|
||||
if (Settings().value(self.main_window.songs_settings_section + '/display songbar') and
|
||||
if (self.settings.value(self.main_window.songs_settings_section + '/display songbar') and
|
||||
not self.song_menu.menu().isEmpty()):
|
||||
self.toolbar.set_widget_visible('song_menu', True)
|
||||
if item.is_capable(ItemCapabilities.CanLoop) and len(item.slides) > 1:
|
||||
@ -1013,9 +1012,9 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.theme_screen.setChecked(False)
|
||||
self.desktop_screen.setChecked(False)
|
||||
if checked:
|
||||
Settings().setValue(self.main_window.general_settings_section + '/screen blank', 'blanked')
|
||||
self.settings.setValue(self.main_window.general_settings_section + '/screen blank', 'blanked')
|
||||
else:
|
||||
Settings().remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.settings.remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.blank_plugin()
|
||||
self.update_preview()
|
||||
self.on_toggle_loop()
|
||||
@ -1034,9 +1033,9 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.theme_screen.setChecked(checked)
|
||||
self.desktop_screen.setChecked(False)
|
||||
if checked:
|
||||
Settings().setValue(self.main_window.general_settings_section + '/screen blank', 'themed')
|
||||
self.settings.setValue(self.main_window.general_settings_section + '/screen blank', 'themed')
|
||||
else:
|
||||
Settings().remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.settings.remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.blank_plugin()
|
||||
self.update_preview()
|
||||
self.on_toggle_loop()
|
||||
@ -1056,9 +1055,9 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.theme_screen.setChecked(False)
|
||||
self.desktop_screen.setChecked(checked)
|
||||
if checked:
|
||||
Settings().setValue(self.main_window.general_settings_section + '/screen blank', 'hidden')
|
||||
self.settings.setValue(self.main_window.general_settings_section + '/screen blank', 'hidden')
|
||||
else:
|
||||
Settings().remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.settings.remove(self.main_window.general_settings_section + '/screen blank')
|
||||
self.hide_plugin(checked)
|
||||
self.update_preview()
|
||||
self.on_toggle_loop()
|
||||
@ -1145,7 +1144,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
return
|
||||
# If "click live slide to unblank" is enabled, unblank the display. And start = Item is sent to Live.
|
||||
# Note: If this if statement is placed at the bottom of this function instead of top slide transitions are lost.
|
||||
if self.is_live and Settings().value('core/click live slide to unblank'):
|
||||
if self.is_live and self.settings.value('core/click live slide to unblank'):
|
||||
if not start:
|
||||
Registry().execute('slidecontroller_live_unblank')
|
||||
row = self.preview_widget.current_slide_number()
|
||||
@ -1353,7 +1352,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
|
||||
self.play_slides_menu.setDefaultAction(self.play_slides_loop)
|
||||
self.play_slides_once.setChecked(False)
|
||||
if Settings().value('core/click live slide to unblank'):
|
||||
if self.settings.value('core/click live slide to unblank'):
|
||||
Registry().execute('slidecontroller_live_unblank')
|
||||
else:
|
||||
self.play_slides_loop.setIcon(UiIcons().clock)
|
||||
@ -1378,7 +1377,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.play_slides_loop.setText(UiStrings().PlaySlidesInLoop)
|
||||
self.play_slides_menu.setDefaultAction(self.play_slides_once)
|
||||
self.play_slides_loop.setChecked(False)
|
||||
if Settings().value('core/click live slide to unblank'):
|
||||
if self.settings.value('core/click live slide to unblank'):
|
||||
Registry().execute('slidecontroller_live_unblank')
|
||||
else:
|
||||
self.play_slides_once.setIcon(UiIcons().clock)
|
||||
@ -1423,7 +1422,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
Triggered when a preview slide item is double clicked
|
||||
"""
|
||||
if self.service_item:
|
||||
if Settings().value('advanced/double click live') and Settings().value('core/auto unblank'):
|
||||
if self.settings.value('advanced/double click live') and self.settings.value('core/auto unblank'):
|
||||
# Live and Preview have issues if we have video or presentations
|
||||
# playing in both at the same time.
|
||||
if self.service_item.is_command():
|
||||
|
@ -43,7 +43,7 @@ from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.widgets.edits import PathEdit
|
||||
from openlp.core.widgets.wizard import OpenLPWizard, WizardStrings
|
||||
from openlp.plugins.bibles.lib.db import clean_filename
|
||||
from openlp.plugins.bibles.lib.importers.http import BGExtract, BSExtract, CWExtract
|
||||
from openlp.plugins.bibles.lib.importers.http import BGExtract, CWExtract
|
||||
from openlp.plugins.bibles.lib.manager import BibleFormat
|
||||
|
||||
|
||||
@ -59,7 +59,8 @@ class WebDownload(object):
|
||||
BibleGateway = 1
|
||||
Bibleserver = 2
|
||||
|
||||
Names = ['Crosswalk', 'BibleGateway', 'Bibleserver']
|
||||
# NOTE: BibleServer support has been disabled since we can't currently parse it. Re-add if/when fixed.
|
||||
Names = ['Crosswalk', 'BibleGateway']
|
||||
|
||||
|
||||
class BibleImportForm(OpenLPWizard):
|
||||
@ -227,7 +228,8 @@ class BibleImportForm(OpenLPWizard):
|
||||
self.web_bible_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.web_source_label)
|
||||
self.web_source_combo_box = QtWidgets.QComboBox(self.web_widget)
|
||||
self.web_source_combo_box.setObjectName('WebSourceComboBox')
|
||||
self.web_source_combo_box.addItems(['', '', ''])
|
||||
# NOTE: Set to 2 items since BibleServer has been disabled. Set to 3 if/when fixed
|
||||
self.web_source_combo_box.addItems(['', ''])
|
||||
self.web_source_combo_box.setEnabled(False)
|
||||
self.web_bible_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.web_source_combo_box)
|
||||
self.web_translation_label = QtWidgets.QLabel(self.web_bible_tab)
|
||||
@ -239,7 +241,8 @@ class BibleImportForm(OpenLPWizard):
|
||||
self.web_translation_combo_box.setEnabled(False)
|
||||
self.web_bible_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.web_translation_combo_box)
|
||||
self.web_progress_bar = QtWidgets.QProgressBar(self)
|
||||
self.web_progress_bar.setRange(0, 3)
|
||||
# NOTE: Set to 2 since BibleServer has been disabled. Set to 3 if/when fixed
|
||||
self.web_progress_bar.setRange(0, 2)
|
||||
self.web_progress_bar.setObjectName('WebTranslationProgressBar')
|
||||
self.web_progress_bar.setVisible(False)
|
||||
self.web_bible_layout.setWidget(3, QtWidgets.QFormLayout.SpanningRole, self.web_progress_bar)
|
||||
@ -400,8 +403,9 @@ class BibleImportForm(OpenLPWizard):
|
||||
'Crosswalk'))
|
||||
self.web_source_combo_box.setItemText(WebDownload.BibleGateway, translate('BiblesPlugin.ImportWizardForm',
|
||||
'BibleGateway'))
|
||||
self.web_source_combo_box.setItemText(WebDownload.Bibleserver, translate('BiblesPlugin.ImportWizardForm',
|
||||
'Bibleserver'))
|
||||
# NOTE: BibleServer support has been disabled since we can't currently parse it. Re-add if/when fixed.
|
||||
# self.web_source_combo_box.setItemText(WebDownload.Bibleserver, translate('BiblesPlugin.ImportWizardForm',
|
||||
# 'Bibleserver'))
|
||||
self.web_translation_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Bible:'))
|
||||
self.sword_bible_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Bibles:'))
|
||||
self.sword_folder_label.setText(translate('BiblesPlugin.ImportWizardForm', 'SWORD data folder:'))
|
||||
@ -578,9 +582,9 @@ class BibleImportForm(OpenLPWizard):
|
||||
self.web_progress_bar.setVisible(True)
|
||||
self.web_progress_bar.setValue(0)
|
||||
# TODO: Where does critical_error_message_box get %s string from?
|
||||
# NOTE: BibleServer support has been disabled since we can't currently parse it. Re-add if/when fixed.
|
||||
for (download_type, extractor) in ((WebDownload.Crosswalk, CWExtract()),
|
||||
(WebDownload.BibleGateway, BGExtract()),
|
||||
(WebDownload.Bibleserver, BSExtract())):
|
||||
(WebDownload.BibleGateway, BGExtract())):
|
||||
try:
|
||||
bibles = extractor.get_bibles_from_http()
|
||||
except (urllib.error.URLError, ConnectionError):
|
||||
|
@ -310,7 +310,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i)
|
||||
thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i)
|
||||
while image_path.is_file():
|
||||
service_item.add_from_image(str(image_path), file_name, thumbnail=str(thumbnail_path))
|
||||
service_item.add_from_image(image_path, file_name, thumbnail=str(thumbnail_path))
|
||||
i += 1
|
||||
image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i)
|
||||
thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i)
|
||||
|
@ -56,6 +56,7 @@ WIN32_MODULES = [
|
||||
LINUX_MODULES = [
|
||||
# Optical drive detection.
|
||||
'dbus',
|
||||
'distro',
|
||||
'Xlib',
|
||||
]
|
||||
|
||||
|
1
setup.py
1
setup.py
@ -101,6 +101,7 @@ using a computer and a data projector.""",
|
||||
'beautifulsoup4',
|
||||
'chardet',
|
||||
'dbus-python; platform_system=="Linux"',
|
||||
'distro; platform_system=="Linux"',
|
||||
'lxml',
|
||||
'Mako',
|
||||
'pymediainfo >= 2.2',
|
||||
|
@ -23,6 +23,7 @@ All the tests
|
||||
"""
|
||||
import os
|
||||
from tempfile import mkstemp
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
@ -39,24 +40,34 @@ def qapp():
|
||||
del app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def registry():
|
||||
"""An instance of the Registry"""
|
||||
Registry.create()
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def settings(qapp):
|
||||
def settings(qapp, registry):
|
||||
"""A Settings() instance"""
|
||||
fd, ini_file = mkstemp('.ini')
|
||||
Settings.set_filename(ini_file)
|
||||
Registry.create()
|
||||
Settings().setDefaultFormat(QtCore.QSettings.IniFormat)
|
||||
# Needed on windows to make sure a Settings object is available during the tests
|
||||
sets = Settings()
|
||||
sets.setValue('themes/global theme', 'my_theme')
|
||||
Registry().register('settings', set)
|
||||
Registry().register('settings', sets)
|
||||
yield sets
|
||||
del sets
|
||||
os.close(fd)
|
||||
os.unlink(Settings().fileName())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def registry():
|
||||
"""An instance of the Registry"""
|
||||
Registry.create()
|
||||
@pytest.yield_fixture
|
||||
def mock_settings(registry):
|
||||
"""A Mock Settings() instance"""
|
||||
# Create and register a mock settings object to work with
|
||||
mock_settings = MagicMock()
|
||||
Registry().register('settings', mock_settings)
|
||||
yield mock_settings
|
||||
Registry().remove('settings')
|
||||
del mock_settings
|
||||
|
@ -22,11 +22,11 @@
|
||||
Functional tests to test the AppLocation class and related methods.
|
||||
"""
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
from unittest import TestCase, skipUnless
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
from openlp.core.common import Singleton, clean_button_text, de_hump, extension_loader, is_linux, is_macosx, is_win, \
|
||||
normalize_str, path_to_module, trace_error_handler
|
||||
is_64bit_instance, normalize_str, path_to_module, trace_error_handler
|
||||
|
||||
|
||||
class TestCommonFunctions(TestCase):
|
||||
@ -243,7 +243,7 @@ class TestCommonFunctions(TestCase):
|
||||
# GIVEN: Mocked out objects
|
||||
with patch('openlp.core.common.os') as mocked_os, patch('openlp.core.common.sys') as mocked_sys:
|
||||
|
||||
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectivly
|
||||
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
|
||||
mocked_os.name = 'posix'
|
||||
mocked_sys.platform = 'linux3'
|
||||
|
||||
@ -252,6 +252,40 @@ class TestCommonFunctions(TestCase):
|
||||
assert is_win() is False, 'is_win() should return False'
|
||||
assert is_macosx() is False, 'is_macosx() should return False'
|
||||
|
||||
@skipUnless(is_linux(), 'This can only run on Linux')
|
||||
def test_is_linux_distro(self):
|
||||
"""
|
||||
Test the is_linux() function for a particular Linux distribution
|
||||
"""
|
||||
# GIVEN: Mocked out objects
|
||||
with patch('openlp.core.common.os') as mocked_os, \
|
||||
patch('openlp.core.common.sys') as mocked_sys, \
|
||||
patch('openlp.core.common.distro_id') as mocked_distro_id:
|
||||
|
||||
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
|
||||
# and the distro is Fedora
|
||||
mocked_os.name = 'posix'
|
||||
mocked_sys.platform = 'linux3'
|
||||
mocked_distro_id.return_value = 'fedora'
|
||||
|
||||
# THEN: The three platform functions should perform properly
|
||||
assert is_linux(distro='fedora') is True, 'is_linux(distro="fedora") should return True'
|
||||
assert is_win() is False, 'is_win() should return False'
|
||||
assert is_macosx() is False, 'is_macosx() should return False'
|
||||
|
||||
def test_is_64bit_instance(self):
|
||||
"""
|
||||
Test the is_64bit_instance() function
|
||||
"""
|
||||
# GIVEN: Mocked out objects
|
||||
with patch('openlp.core.common.sys') as mocked_sys:
|
||||
|
||||
# WHEN: The mocked sys.maxsize is set to 32-bit
|
||||
mocked_sys.maxsize = 2**32
|
||||
|
||||
# THEN: The result should be False
|
||||
assert is_64bit_instance() is False, 'is_64bit_instance() should return False'
|
||||
|
||||
def test_normalize_str_leaves_newlines(self):
|
||||
# GIVEN: a string containing newlines
|
||||
string = 'something\nelse'
|
||||
|
@ -25,6 +25,7 @@ from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.ui import DisplayControllerType
|
||||
from openlp.core.ui.media.mediacontroller import MediaController
|
||||
from openlp.core.ui.media import ItemMediaInfo
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
@ -202,3 +203,122 @@ class TestMediaController(TestCase, TestMixin):
|
||||
|
||||
# THEN you can determine the run time
|
||||
assert results == test_data[1], 'The correct duration is returned for ' + test_data[0]
|
||||
|
||||
def test_on_media_play(self):
|
||||
"""
|
||||
Test the on_media_play method
|
||||
"""
|
||||
# GIVEN: A mocked live controller and a mocked media_play() method
|
||||
mocked_live_controller = MagicMock()
|
||||
Registry().register('live_controller', mocked_live_controller)
|
||||
media_controller = MediaController()
|
||||
media_controller.media_play = MagicMock()
|
||||
|
||||
# WHEN: the on_media_play() method is called
|
||||
media_controller.on_media_play()
|
||||
|
||||
# The mocked live controller should be called
|
||||
media_controller.media_play.assert_called_once_with(mocked_live_controller, False)
|
||||
|
||||
def test_on_media_pause(self):
|
||||
"""
|
||||
Test the on_media_pause method
|
||||
"""
|
||||
# GIVEN: A mocked live controller and a mocked media_pause() method
|
||||
mocked_live_controller = MagicMock()
|
||||
Registry().register('live_controller', mocked_live_controller)
|
||||
media_controller = MediaController()
|
||||
media_controller.media_pause = MagicMock()
|
||||
|
||||
# WHEN: the on_media_pause() method is called
|
||||
media_controller.on_media_pause()
|
||||
|
||||
# The mocked live controller should be called
|
||||
media_controller.media_pause.assert_called_once_with(mocked_live_controller)
|
||||
|
||||
def test_on_media_stop(self):
|
||||
"""
|
||||
Test the on_media_stop method
|
||||
"""
|
||||
# GIVEN: A mocked live controller and a mocked media_stop() method
|
||||
mocked_live_controller = MagicMock()
|
||||
Registry().register('live_controller', mocked_live_controller)
|
||||
media_controller = MediaController()
|
||||
media_controller.media_stop = MagicMock()
|
||||
|
||||
# WHEN: the on_media_stop() method is called
|
||||
media_controller.on_media_stop()
|
||||
|
||||
# The mocked live controller should be called
|
||||
media_controller.media_stop.assert_called_once_with(mocked_live_controller)
|
||||
|
||||
def test_display_controllers_live(self):
|
||||
"""
|
||||
Test that the display_controllers() method returns the live controller when requested
|
||||
"""
|
||||
# GIVEN: A mocked live controller
|
||||
media_controller = MediaController()
|
||||
mocked_live_controller = MagicMock()
|
||||
mocked_preview_controller = MagicMock()
|
||||
Registry().register('live_controller', mocked_live_controller)
|
||||
Registry().register('preview_controller', mocked_preview_controller)
|
||||
|
||||
# WHEN: display_controllers() is called with DisplayControllerType.Live
|
||||
controller = media_controller.display_controllers(DisplayControllerType.Live)
|
||||
|
||||
# THEN: the controller should be the live controller
|
||||
assert controller is mocked_live_controller
|
||||
|
||||
def test_display_controllers_preview(self):
|
||||
"""
|
||||
Test that the display_controllers() method returns the preview controller when requested
|
||||
"""
|
||||
# GIVEN: A mocked live controller
|
||||
media_controller = MediaController()
|
||||
mocked_live_controller = MagicMock()
|
||||
mocked_preview_controller = MagicMock()
|
||||
Registry().register('live_controller', mocked_live_controller)
|
||||
Registry().register('preview_controller', mocked_preview_controller)
|
||||
|
||||
# WHEN: display_controllers() is called with DisplayControllerType.Preview
|
||||
controller = media_controller.display_controllers(DisplayControllerType.Preview)
|
||||
|
||||
# THEN: the controller should be the live controller
|
||||
assert controller is mocked_preview_controller
|
||||
|
||||
def test_set_controls_visible(self):
|
||||
"""
|
||||
Test that "set_controls_visible" sets the media controls on the controller to be visible or not
|
||||
"""
|
||||
# GIVEN: A mocked controller
|
||||
mocked_controller = MagicMock()
|
||||
|
||||
# WHEN: Set to visible
|
||||
MediaController.set_controls_visible(mocked_controller, True)
|
||||
|
||||
# THEN: The media controls should have been set to visible
|
||||
mocked_controller.mediabar.setVisible.assert_called_once_with(True)
|
||||
|
||||
@patch('openlp.core.ui.media.mediacontroller.ItemMediaInfo')
|
||||
def test_setup_display(self, MockItemMediaInfo):
|
||||
"""
|
||||
Test that the display/controllers are set up correctly
|
||||
"""
|
||||
# GIVEN: A media controller object and some mocks
|
||||
mocked_media_info = MagicMock()
|
||||
MockItemMediaInfo.return_value = mocked_media_info
|
||||
media_controller = MediaController()
|
||||
media_controller.vlc_player = MagicMock()
|
||||
mocked_display = MagicMock()
|
||||
media_controller._define_display = MagicMock(return_value=mocked_display)
|
||||
media_controller.vlc_player = MagicMock()
|
||||
controller = MagicMock()
|
||||
|
||||
# WHEN: setup_display() is called
|
||||
media_controller.setup_display(controller, True)
|
||||
|
||||
# THEN: The right calls should have been made
|
||||
assert controller.media_info == mocked_media_info
|
||||
assert controller.has_audio is False
|
||||
media_controller._define_display.assert_called_once_with(controller)
|
||||
media_controller.vlc_player.setup(controller, mocked_display, False)
|
||||
|
@ -21,7 +21,6 @@
|
||||
"""
|
||||
Package to test the openlp.core.ui.slidecontroller package.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from PyQt5 import QtCore, QtGui
|
||||
@ -32,15 +31,7 @@ from openlp.core.ui.slidecontroller import NON_TEXT_MENU, WIDE_MENU, InfoLabel,
|
||||
SlideController
|
||||
|
||||
|
||||
class TestSlideController(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the components need for all tests.
|
||||
"""
|
||||
Registry.create()
|
||||
|
||||
def test_initial_slide_controller(self):
|
||||
def test_initial_slide_controller(registry):
|
||||
"""
|
||||
Test the initial slide controller state .
|
||||
"""
|
||||
@ -51,7 +42,8 @@ class TestSlideController(TestCase):
|
||||
# THEN: The controller should not be a live controller.
|
||||
assert slide_controller.is_live is False, 'The base slide controller should not be a live controller'
|
||||
|
||||
def test_text_service_item_blank(self):
|
||||
|
||||
def test_text_service_item_blank():
|
||||
"""
|
||||
Test that loading a text-based service item into the slide controller sets the correct blank menu
|
||||
"""
|
||||
@ -70,7 +62,8 @@ class TestSlideController(TestCase):
|
||||
# THEN: the call to set the visible items on the toolbar should be correct
|
||||
toolbar.set_widget_visible.assert_called_with(WIDE_MENU, True)
|
||||
|
||||
def test_non_text_service_item_blank(self):
|
||||
|
||||
def test_non_text_service_item_blank():
|
||||
"""
|
||||
Test that loading a non-text service item into the slide controller sets the correct blank menu
|
||||
"""
|
||||
@ -89,14 +82,13 @@ class TestSlideController(TestCase):
|
||||
# THEN: then call set up the toolbar to blank the display screen.
|
||||
toolbar.set_widget_visible.assert_called_with(NON_TEXT_MENU, True)
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def test_receive_spin_delay(self, MockedSettings):
|
||||
|
||||
def test_receive_spin_delay(mock_settings):
|
||||
"""
|
||||
Test that the spin box is updated accordingly after a call to receive_spin_delay()
|
||||
"""
|
||||
# GIVEN: A new SlideController instance.
|
||||
mocked_value = MagicMock(return_value=1)
|
||||
MockedSettings.return_value = MagicMock(value=mocked_value)
|
||||
mock_settings.value.return_value = 1
|
||||
mocked_delay_spin_box = MagicMock()
|
||||
slide_controller = SlideController(None)
|
||||
slide_controller.delay_spin_box = mocked_delay_spin_box
|
||||
@ -104,11 +96,13 @@ class TestSlideController(TestCase):
|
||||
# WHEN: The receive_spin_delay() method is called
|
||||
slide_controller.receive_spin_delay()
|
||||
|
||||
# THEN: The Settings()value() and delay_spin_box.setValue() methods should have been called correctly
|
||||
mocked_value.assert_called_with('core/loop delay')
|
||||
# THEN: The settings value() and delay_spin_box.setValue() methods should have been called correctly
|
||||
msv = mock_settings.value
|
||||
msv.assert_called_with('core/loop delay')
|
||||
mocked_delay_spin_box.setValue.assert_called_with(1)
|
||||
|
||||
def test_toggle_display_blank(self):
|
||||
|
||||
def test_toggle_display_blank():
|
||||
"""
|
||||
Check that the toggle_display('blank') method calls the on_blank_display() method
|
||||
"""
|
||||
@ -129,7 +123,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called'
|
||||
assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called'
|
||||
|
||||
def test_toggle_display_hide(self):
|
||||
|
||||
def test_toggle_display_hide():
|
||||
"""
|
||||
Check that the toggle_display('hide') method calls the on_blank_display() method
|
||||
"""
|
||||
@ -150,7 +145,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called'
|
||||
assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called'
|
||||
|
||||
def test_toggle_display_theme(self):
|
||||
|
||||
def test_toggle_display_theme():
|
||||
"""
|
||||
Check that the toggle_display('theme') method calls the on_theme_display() method
|
||||
"""
|
||||
@ -171,7 +167,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_on_blank_display.call_count, 'on_blank_display should not have been called'
|
||||
assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called'
|
||||
|
||||
def test_toggle_display_desktop(self):
|
||||
|
||||
def test_toggle_display_desktop():
|
||||
"""
|
||||
Check that the toggle_display('desktop') method calls the on_hide_display() method
|
||||
"""
|
||||
@ -192,7 +189,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_on_blank_display.call_count, 'on_blank_display should not have been called'
|
||||
assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called'
|
||||
|
||||
def test_toggle_display_show(self):
|
||||
|
||||
def test_toggle_display_show():
|
||||
"""
|
||||
Check that the toggle_display('show') method calls all the on_X_display() methods
|
||||
"""
|
||||
@ -213,7 +211,8 @@ class TestSlideController(TestCase):
|
||||
mocked_on_theme_display.assert_called_once_with(False)
|
||||
mocked_on_hide_display.assert_called_once_with(False)
|
||||
|
||||
def test_on_go_live_preview_controller(self):
|
||||
|
||||
def test_on_go_live_preview_controller():
|
||||
"""
|
||||
Test that when the on_go_preview() method is called the message is sent to the preview controller and focus is
|
||||
set correctly.
|
||||
@ -240,7 +239,8 @@ class TestSlideController(TestCase):
|
||||
# THEN: the preview controller should have the service item and the focus set to live
|
||||
mocked_preview_controller.preview_widget.setFocus.assert_called_once_with()
|
||||
|
||||
def test_on_go_live_live_controller(self):
|
||||
|
||||
def test_on_go_live_live_controller():
|
||||
"""
|
||||
Test that when the on_go_live() method is called the message is sent to the live controller and focus is
|
||||
set correctly.
|
||||
@ -268,7 +268,8 @@ class TestSlideController(TestCase):
|
||||
mocked_live_controller.add_service_manager_item.assert_called_once_with(mocked_service_item, 1)
|
||||
mocked_live_controller.preview_widget.setFocus.assert_called_once_with()
|
||||
|
||||
def test_on_go_live_service_manager(self):
|
||||
|
||||
def test_on_go_live_service_manager():
|
||||
"""
|
||||
Test that when the on_go_live() method is called the message is sent to the live controller and focus is
|
||||
set correctly.
|
||||
@ -299,7 +300,8 @@ class TestSlideController(TestCase):
|
||||
mocked_service_manager.preview_live.assert_called_once_with(42, 1)
|
||||
mocked_live_controller.preview_widget.setFocus.assert_called_once_with()
|
||||
|
||||
def test_service_previous(self):
|
||||
|
||||
def test_service_previous():
|
||||
"""
|
||||
Check that calling the service_previous() method adds the previous key to the queue and processes the queue
|
||||
"""
|
||||
@ -317,7 +319,8 @@ class TestSlideController(TestCase):
|
||||
mocked_keypress_queue.append.assert_called_once_with(ServiceItemAction.Previous)
|
||||
mocked_process_queue.assert_called_once_with()
|
||||
|
||||
def test_service_next(self):
|
||||
|
||||
def test_service_next():
|
||||
"""
|
||||
Check that calling the service_next() method adds the next key to the queue and processes the queue
|
||||
"""
|
||||
@ -335,16 +338,14 @@ class TestSlideController(TestCase):
|
||||
mocked_keypress_queue.append.assert_called_once_with(ServiceItemAction.Next)
|
||||
mocked_process_queue.assert_called_once_with()
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def test_update_slide_limits(self, MockedSettings):
|
||||
|
||||
def test_update_slide_limits(mock_settings):
|
||||
"""
|
||||
Test that calling the update_slide_limits() method updates the slide limits
|
||||
"""
|
||||
# GIVEN: A mocked out Settings object, a new SlideController and a mocked out main_window
|
||||
mocked_value = MagicMock(return_value=10)
|
||||
MockedSettings.return_value = MagicMock(value=mocked_value)
|
||||
mock_settings.value.return_value = 10
|
||||
mocked_main_window = MagicMock(advanced_settings_section='advanced')
|
||||
Registry.create()
|
||||
Registry().register('main_window', mocked_main_window)
|
||||
slide_controller = SlideController(None)
|
||||
|
||||
@ -352,10 +353,12 @@ class TestSlideController(TestCase):
|
||||
slide_controller.update_slide_limits()
|
||||
|
||||
# THEN: The value of slide_limits should be 10
|
||||
mocked_value.assert_called_once_with('advanced/slide limits')
|
||||
msv = mock_settings.value
|
||||
msv.assert_called_once_with('advanced/slide limits')
|
||||
assert 10 == slide_controller.slide_limits, 'Slide limits should have been updated to 10'
|
||||
|
||||
def test_enable_tool_bar_live(self):
|
||||
|
||||
def test_enable_tool_bar_live():
|
||||
"""
|
||||
Check that when enable_tool_bar on a live slide controller is called, enable_live_tool_bar is called
|
||||
"""
|
||||
@ -375,7 +378,8 @@ class TestSlideController(TestCase):
|
||||
mocked_enable_live_tool_bar.assert_called_once_with(mocked_service_item)
|
||||
assert 0 == mocked_enable_preview_tool_bar.call_count, 'The preview method should not have been called'
|
||||
|
||||
def test_enable_tool_bar_preview(self):
|
||||
|
||||
def test_enable_tool_bar_preview():
|
||||
"""
|
||||
Check that when enable_tool_bar on a preview slide controller is called, enable_preview_tool_bar is called
|
||||
"""
|
||||
@ -395,7 +399,8 @@ class TestSlideController(TestCase):
|
||||
mocked_enable_preview_tool_bar.assert_called_once_with(mocked_service_item)
|
||||
assert 0 == mocked_enable_live_tool_bar.call_count, 'The live method should not have been called'
|
||||
|
||||
def test_refresh_service_item_text(self):
|
||||
|
||||
def test_refresh_service_item_text():
|
||||
"""
|
||||
Test that the refresh_service_item() method refreshes a text service item
|
||||
"""
|
||||
@ -418,7 +423,8 @@ class TestSlideController(TestCase):
|
||||
mocked_service_item.render.assert_called_once_with()
|
||||
mocked_process_item.assert_called_once_with(mocked_service_item, 5)
|
||||
|
||||
def test_refresh_service_item_image(self):
|
||||
|
||||
def test_refresh_service_item_image():
|
||||
"""
|
||||
Test that the refresh_service_item() method refreshes a image service item
|
||||
"""
|
||||
@ -441,7 +447,8 @@ class TestSlideController(TestCase):
|
||||
mocked_service_item.render.assert_called_once_with()
|
||||
mocked_process_item.assert_called_once_with(mocked_service_item, 5)
|
||||
|
||||
def test_refresh_service_item_not_image_or_text(self):
|
||||
|
||||
def test_refresh_service_item_not_image_or_text():
|
||||
"""
|
||||
Test that the refresh_service_item() method does not refresh a service item if it's neither text or an image
|
||||
"""
|
||||
@ -464,7 +471,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_service_item.render.call_count, 'The render() method should not have been called'
|
||||
assert 0 == mocked_process_item.call_count, 'The mocked_process_item() method should not have been called'
|
||||
|
||||
def test_add_service_item_with_song_edit(self):
|
||||
|
||||
def test_add_service_item_with_song_edit():
|
||||
"""
|
||||
Test the add_service_item() method when song_edit is True
|
||||
"""
|
||||
@ -483,7 +491,8 @@ class TestSlideController(TestCase):
|
||||
assert slide_controller.song_edit is False, 'song_edit should be False'
|
||||
mocked_process_item.assert_called_once_with(mocked_item, 2)
|
||||
|
||||
def test_add_service_item_without_song_edit(self):
|
||||
|
||||
def test_add_service_item_without_song_edit():
|
||||
"""
|
||||
Test the add_service_item() method when song_edit is False
|
||||
"""
|
||||
@ -502,7 +511,8 @@ class TestSlideController(TestCase):
|
||||
assert slide_controller.song_edit is False, 'song_edit should be False'
|
||||
mocked_process_item.assert_called_once_with(mocked_item, 0)
|
||||
|
||||
def test_replace_service_manager_item_different_items(self):
|
||||
|
||||
def test_replace_service_manager_item_different_items():
|
||||
"""
|
||||
Test that when the service items are not the same, nothing happens
|
||||
"""
|
||||
@ -523,7 +533,8 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_preview_widget.current_slide_number.call_count, \
|
||||
'The preview_widget current_slide_number.() method should not have been called'
|
||||
|
||||
def test_replace_service_manager_item_same_item(self):
|
||||
|
||||
def test_replace_service_manager_item_same_item():
|
||||
"""
|
||||
Test that when the service item is the same, the service item is reprocessed
|
||||
"""
|
||||
@ -544,7 +555,8 @@ class TestSlideController(TestCase):
|
||||
mocked_preview_widget.current_slide_number.assert_called_with()
|
||||
mocked_process_item.assert_called_once_with(mocked_item, 7)
|
||||
|
||||
def test_on_slide_blank(self):
|
||||
|
||||
def test_on_slide_blank():
|
||||
"""
|
||||
Test on_slide_blank
|
||||
"""
|
||||
@ -558,7 +570,8 @@ class TestSlideController(TestCase):
|
||||
# THEN: on_blank_display should have been called with True
|
||||
slide_controller.on_blank_display.assert_called_once_with(True)
|
||||
|
||||
def test_on_slide_unblank(self):
|
||||
|
||||
def test_on_slide_unblank():
|
||||
"""
|
||||
Test on_slide_unblank
|
||||
"""
|
||||
@ -572,7 +585,8 @@ class TestSlideController(TestCase):
|
||||
# THEN: on_blank_display should have been called with False
|
||||
slide_controller.on_blank_display.assert_called_once_with(False)
|
||||
|
||||
def test_on_slide_selected_index_no_service_item(self):
|
||||
|
||||
def test_on_slide_selected_index_no_service_item():
|
||||
"""
|
||||
Test that when there is no service item, the on_slide_selected_index() method returns immediately
|
||||
"""
|
||||
@ -587,8 +601,9 @@ class TestSlideController(TestCase):
|
||||
# THEN: It should have exited early
|
||||
assert 0 == mocked_item.is_command.call_count, 'The service item should have not been called'
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_on_slide_selected_index_service_item_command(self, mocked_execute):
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_on_slide_selected_index_service_item_command(mocked_execute):
|
||||
"""
|
||||
Test that when there is a command service item, the command is executed
|
||||
"""
|
||||
@ -617,8 +632,9 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_preview_widget.change_slide.call_count, 'Change slide should not have been called'
|
||||
assert 0 == mocked_slide_selected.call_count, 'slide_selected should not have been called'
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_on_slide_selected_index_service_item_not_command(self, mocked_execute):
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_on_slide_selected_index_service_item_not_command(mocked_execute):
|
||||
"""
|
||||
Test that when there is a service item but it's not a command, the preview widget is updated
|
||||
"""
|
||||
@ -646,8 +662,9 @@ class TestSlideController(TestCase):
|
||||
mocked_preview_widget.change_slide.assert_called_once_with(7)
|
||||
mocked_slide_selected.assert_called_once_with()
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_process_item(self, mocked_execute):
|
||||
|
||||
@patch.object(Registry, 'execute')
|
||||
def test_process_item(mocked_execute):
|
||||
"""
|
||||
Test that presentation service-items is closed when followed by a media service-item
|
||||
"""
|
||||
@ -667,8 +684,8 @@ class TestSlideController(TestCase):
|
||||
mocked_media_item.is_image.return_value = False
|
||||
mocked_media_item.from_service = False
|
||||
mocked_media_item.get_frames.return_value = []
|
||||
Registry.create()
|
||||
mocked_main_window = MagicMock()
|
||||
Registry.create()
|
||||
Registry().register('main_window', mocked_main_window)
|
||||
Registry().register('media_controller', MagicMock())
|
||||
slide_controller = SlideController(None)
|
||||
@ -693,7 +710,8 @@ class TestSlideController(TestCase):
|
||||
assert 'mocked_presentation_item_stop' == mocked_execute.call_args_list[1][0][0], \
|
||||
'The presentation should have been stopped.'
|
||||
|
||||
def test_live_stolen_focus_shortcuts(self):
|
||||
|
||||
def test_live_stolen_focus_shortcuts():
|
||||
"""
|
||||
Test that all the needed shortcuts are available in scenarios where Live has stolen focus.
|
||||
These are found under def __add_actions_to_widget(self, widget): in slidecontroller.py
|
||||
@ -721,20 +739,19 @@ class TestSlideController(TestCase):
|
||||
slide_controller.theme_screen, slide_controller.blank_screen
|
||||
])
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def test_on_preview_double_click_unblank_display(self, MockedSettings):
|
||||
# GIVEN: A slide controller, actions needed, settins set to True.
|
||||
|
||||
def test_on_preview_double_click_unblank_display(mock_settings):
|
||||
# GIVEN: A slide controller, actions needed, settings set to True.
|
||||
slide_controller = SlideController(None)
|
||||
mocked_settings = MagicMock()
|
||||
mocked_settings.return_value = True
|
||||
MockedSettings.return_value = mocked_settings
|
||||
mock_settings.return_value = mocked_settings
|
||||
slide_controller.service_item = MagicMock()
|
||||
slide_controller.service_item.is_media = MagicMock()
|
||||
slide_controller.on_media_close = MagicMock()
|
||||
slide_controller.on_go_live = MagicMock()
|
||||
slide_controller.on_preview_add_to_service = MagicMock()
|
||||
slide_controller.media_reset = MagicMock()
|
||||
Registry.create()
|
||||
Registry().set_flag('has doubleclick added item to service', True)
|
||||
|
||||
# WHEN: on_preview_double_click is called
|
||||
@ -744,20 +761,17 @@ class TestSlideController(TestCase):
|
||||
assert 1 == slide_controller.on_go_live.call_count, 'on_go_live should have been called once.'
|
||||
assert 0 == slide_controller.on_preview_add_to_service.call_count, 'Should have not been called.'
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def test_on_preview_double_click_add_to_service(self, MockedSettings):
|
||||
# GIVEN: A slide controller, actions needed, settins set to False.
|
||||
|
||||
def test_on_preview_double_click_add_to_service(mock_settings):
|
||||
# GIVEN: A slide controller, actions needed, settings set to False.
|
||||
slide_controller = SlideController(None)
|
||||
mocked_settings = MagicMock()
|
||||
mocked_settings.value.return_value = False
|
||||
MockedSettings.return_value = mocked_settings
|
||||
mock_settings.value.return_value = False
|
||||
slide_controller.service_item = MagicMock()
|
||||
slide_controller.service_item.is_media = MagicMock()
|
||||
slide_controller.on_media_close = MagicMock()
|
||||
slide_controller.on_go_live = MagicMock()
|
||||
slide_controller.on_preview_add_to_service = MagicMock()
|
||||
slide_controller.media_reset = MagicMock()
|
||||
Registry.create()
|
||||
Registry().set_flag('has doubleclick added item to service', False)
|
||||
|
||||
# WHEN: on_preview_double_click is called
|
||||
@ -767,9 +781,10 @@ class TestSlideController(TestCase):
|
||||
assert 0 == slide_controller.on_go_live.call_count, 'on_go_live Should have not been called.'
|
||||
assert 1 == slide_controller.on_preview_add_to_service.call_count, 'Should have been called once.'
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_live(self, mocked_singleShot, mocked_image_manager):
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_live(mocked_singleShot, mocked_image_manager):
|
||||
"""
|
||||
Test that the preview screen is updated with a screen grab for live service items
|
||||
"""
|
||||
@ -809,9 +824,10 @@ class TestSlideController(TestCase):
|
||||
assert 2 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should have been called 2 times'
|
||||
assert 0 == mocked_image_manager.get_image.call_count, 'image_manager not be called'
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_pres(self, mocked_singleShot, mocked_image_manager):
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_pres(mocked_singleShot, mocked_image_manager):
|
||||
"""
|
||||
Test that the preview screen is updated with the correct preview for presentation service items
|
||||
"""
|
||||
@ -849,11 +865,11 @@ class TestSlideController(TestCase):
|
||||
# THEN: setPixmap and the image_manager should have been called
|
||||
assert 1 == slide_controller.preview_display.set_single_image.call_count, 'set_single_image should be called'
|
||||
assert 0 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called'
|
||||
# assert 1 == mocked_image_manager.get_image.call_count, 'image_manager should be called'
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_media(self, mocked_singleShot, mocked_image_manager):
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_media(mocked_singleShot, mocked_image_manager):
|
||||
"""
|
||||
Test that the preview screen is updated with the correct preview for media service items
|
||||
"""
|
||||
@ -893,9 +909,10 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called'
|
||||
assert 0 == mocked_image_manager.get_image.call_count, 'image_manager should not be called'
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_image(self, mocked_singleShot, mocked_image_manager):
|
||||
|
||||
@patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager')
|
||||
@patch(u'PyQt5.QtCore.QTimer.singleShot')
|
||||
def test_update_preview_image(mocked_singleShot, mocked_image_manager):
|
||||
"""
|
||||
Test that the preview screen is updated with the correct preview for image service items
|
||||
"""
|
||||
@ -935,14 +952,14 @@ class TestSlideController(TestCase):
|
||||
assert 0 == mocked_image_manager.get_image.call_count, 'image_manager should not be called'
|
||||
|
||||
|
||||
class TestInfoLabel(TestCase):
|
||||
|
||||
def test_paint_event_text_fits(self):
|
||||
def test_paint_event_text_fits():
|
||||
"""
|
||||
Test the paintEvent method when text fits the label
|
||||
"""
|
||||
font = QtGui.QFont()
|
||||
metrics = QtGui.QFontMetrics(font)
|
||||
|
||||
with patch('openlp.core.ui.slidecontroller.QtWidgets.QLabel'), \
|
||||
patch('openlp.core.ui.slidecontroller.QtGui.QFontMetrics') as MockFontMetrics, \
|
||||
patch('openlp.core.ui.slidecontroller.QtGui.QPainter') as mocked_qpainter:
|
||||
|
||||
# GIVEN: An instance of InfoLabel, with mocked text return, width and rect methods
|
||||
@ -955,28 +972,28 @@ class TestInfoLabel(TestCase):
|
||||
info_label.rect = mocked_rect
|
||||
info_label.text = mocked_text
|
||||
info_label.width = mocked_width
|
||||
mocked_font_metrics = MagicMock()
|
||||
mocked_font_metrics.elidedText.return_value = test_string
|
||||
MockFontMetrics.return_value = mocked_font_metrics
|
||||
|
||||
# WHEN: The instance is wider than its text, and the paintEvent method is called
|
||||
info_label.width.return_value = metrics.boundingRect(test_string).width() + 20
|
||||
info_label.paintEvent(MagicMock())
|
||||
|
||||
# THEN: The text should be drawn centered with the complete test_string
|
||||
mocked_qpainter().drawText.assert_called_once_with(mocked_rect(), QtCore.Qt.AlignCenter, test_string)
|
||||
|
||||
def test_paint_event_text_doesnt_fit(self):
|
||||
|
||||
def test_paint_event_text_doesnt_fit():
|
||||
"""
|
||||
Test the paintEvent method when text fits the label
|
||||
"""
|
||||
font = QtGui.QFont()
|
||||
metrics = QtGui.QFontMetrics(font)
|
||||
|
||||
with patch('openlp.core.ui.slidecontroller.QtWidgets.QLabel'), \
|
||||
patch('openlp.core.ui.slidecontroller.QtGui.QFontMetrics') as MockFontMetrics, \
|
||||
patch('openlp.core.ui.slidecontroller.QtGui.QPainter') as mocked_qpainter:
|
||||
|
||||
# GIVEN: An instance of InfoLabel, with mocked text return, width and rect methods
|
||||
info_label = InfoLabel()
|
||||
test_string = 'Label Text'
|
||||
elided_test_string = test_string[0:5] + '...'
|
||||
mocked_rect = MagicMock()
|
||||
mocked_text = MagicMock()
|
||||
mocked_width = MagicMock()
|
||||
@ -984,18 +1001,19 @@ class TestInfoLabel(TestCase):
|
||||
info_label.rect = mocked_rect
|
||||
info_label.text = mocked_text
|
||||
info_label.width = mocked_width
|
||||
mocked_font_metrics = MagicMock()
|
||||
mocked_font_metrics.elidedText.return_value = elided_test_string
|
||||
MockFontMetrics.return_value = mocked_font_metrics
|
||||
|
||||
# WHEN: The instance is narrower than its text, and the paintEvent method is called
|
||||
label_width = metrics.boundingRect(test_string).width() - 20
|
||||
info_label.width.return_value = label_width
|
||||
info_label.paintEvent(MagicMock())
|
||||
|
||||
# THEN: The text should be drawn aligned left with an elided test_string
|
||||
elided_test_string = metrics.elidedText(test_string, QtCore.Qt.ElideRight, label_width)
|
||||
mocked_qpainter().drawText.assert_called_once_with(mocked_rect(), QtCore.Qt.AlignLeft, elided_test_string)
|
||||
|
||||
@patch('builtins.super')
|
||||
def test_set_text(self, mocked_super):
|
||||
|
||||
@patch('builtins.super')
|
||||
def test_set_text(mocked_super):
|
||||
"""
|
||||
Test the reimplemented setText method
|
||||
"""
|
||||
@ -1012,9 +1030,7 @@ class TestInfoLabel(TestCase):
|
||||
mocked_super().setText.assert_called_once_with('Label Text')
|
||||
|
||||
|
||||
class TestLiveController(TestCase):
|
||||
|
||||
def test_initial_live_controller(self):
|
||||
def test_initial_live_controller():
|
||||
"""
|
||||
Test the initial live slide controller state .
|
||||
"""
|
||||
@ -1027,9 +1043,7 @@ class TestLiveController(TestCase):
|
||||
assert live_controller.is_live is True, 'The slide controller should be a live controller'
|
||||
|
||||
|
||||
class TestPreviewLiveController(TestCase):
|
||||
|
||||
def test_initial_preview_controller(self):
|
||||
def test_initial_preview_controller():
|
||||
"""
|
||||
Test the initial preview slide controller state.
|
||||
"""
|
||||
|
@ -22,7 +22,7 @@
|
||||
Package to test the openlp.plugin.bible.lib.https package.
|
||||
"""
|
||||
import os
|
||||
from unittest import TestCase, skipIf
|
||||
from unittest import TestCase, skipIf, skip
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
@ -122,6 +122,7 @@ class TestBibleHTTP(TestCase):
|
||||
# THEN: We should get back a valid service item
|
||||
assert len(results.verse_list) == 36, 'The book of John should not have had any verses added or removed'
|
||||
|
||||
@skip("We can't currently parse BibelServer")
|
||||
def test_bibleserver_get_bibles(self):
|
||||
"""
|
||||
Test getting list of bibles from BibleServer.com
|
||||
|
@ -35,8 +35,9 @@ class FakeIP4InterfaceEntry(QObject):
|
||||
"""
|
||||
Class to face an interface for testing purposes
|
||||
"""
|
||||
def __init__(self, name='lo'):
|
||||
def __init__(self, name='lo', is_valid=True):
|
||||
self.my_name = name
|
||||
self._is_valid = is_valid
|
||||
if name in ['localhost', 'lo']:
|
||||
self.my_ip = QNetworkAddressEntry()
|
||||
self.my_ip.setBroadcast(QHostAddress('255.0.0.0'))
|
||||
@ -75,7 +76,7 @@ class FakeIP4InterfaceEntry(QObject):
|
||||
return self.my_name
|
||||
|
||||
def isValid(self):
|
||||
return True
|
||||
return self._is_valid
|
||||
|
||||
|
||||
class TestInterfaces(TestCase, TestMixin):
|
||||
@ -92,6 +93,7 @@ class TestInterfaces(TestCase, TestMixin):
|
||||
self.fake_lo = FakeIP4InterfaceEntry()
|
||||
self.fake_localhost = FakeIP4InterfaceEntry(name='localhost')
|
||||
self.fake_address = FakeIP4InterfaceEntry(name='eth25')
|
||||
self.invalid_if = FakeIP4InterfaceEntry(name='invalid', is_valid=False)
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
@ -126,7 +128,7 @@ class TestInterfaces(TestCase, TestMixin):
|
||||
# GIVEN: Test environment
|
||||
call_debug = [
|
||||
call('Getting local IPv4 interface(es) information'),
|
||||
call("Filtering out interfaces we don't care about: lo")
|
||||
call('Filtering out interfaces we don\'t care about: lo')
|
||||
]
|
||||
|
||||
# WHEN: get_network_interfaces() is called
|
||||
@ -146,7 +148,7 @@ class TestInterfaces(TestCase, TestMixin):
|
||||
# GIVEN: Test environment
|
||||
call_debug = [
|
||||
call('Getting local IPv4 interface(es) information'),
|
||||
call("Filtering out interfaces we don't care about: localhost")
|
||||
call('Filtering out interfaces we don\'t care about: localhost')
|
||||
]
|
||||
|
||||
# WHEN: get_network_interfaces() is called
|
||||
@ -190,7 +192,7 @@ class TestInterfaces(TestCase, TestMixin):
|
||||
# GIVEN: Test environment
|
||||
call_debug = [
|
||||
call('Getting local IPv4 interface(es) information'),
|
||||
call("Filtering out interfaces we don't care about: lo"),
|
||||
call('Filtering out interfaces we don\'t care about: lo'),
|
||||
call('Checking for isValid and flags == IsUP | IsRunning'),
|
||||
call('Checking address(es) protocol'),
|
||||
call('Checking for protocol == IPv4Protocol'),
|
||||
@ -205,4 +207,26 @@ class TestInterfaces(TestCase, TestMixin):
|
||||
|
||||
# THEN: There should be a fake 'eth25' interface
|
||||
mock_log.debug.assert_has_calls(call_debug)
|
||||
assert interfaces == self.fake_address.fake_data, "There should have been only 'eth25' interface listed"
|
||||
assert interfaces == self.fake_address.fake_data, 'There should have been only "eth25" interface listed'
|
||||
|
||||
@patch.object(openlp.core.common, 'log')
|
||||
def test_network_interfaces_invalid(self, mock_log):
|
||||
"""
|
||||
Test get_network_interfaces() returns an empty dictionary when there are no valid interfaces
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
call_debug = [
|
||||
call('Getting local IPv4 interface(es) information'),
|
||||
call('Checking for isValid and flags == IsUP | IsRunning')
|
||||
]
|
||||
call_warning = [call('No active IPv4 network interfaces detected')]
|
||||
|
||||
# WHEN: get_network_interfaces() is called
|
||||
with patch('openlp.core.common.QNetworkInterface') as mock_network_interface:
|
||||
mock_network_interface.allInterfaces.return_value = [self.invalid_if]
|
||||
interfaces = get_network_interfaces()
|
||||
|
||||
# THEN: There should be a fake 'eth25' interface
|
||||
mock_log.debug.assert_has_calls(call_debug)
|
||||
mock_log.warning.assert_has_calls(call_warning)
|
||||
assert interfaces == {}, 'There should not be any interfaces listed'
|
||||
|
Loading…
Reference in New Issue
Block a user