diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index 892680409..7861ae368 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -250,7 +250,7 @@ def build_icon(icon):
pix_map = QtGui.QPixmap(icon)
elif isinstance(icon, Path):
pix_map = QtGui.QPixmap(str(icon))
- elif isinstance(icon, QtGui.QImage):
+ elif isinstance(icon, QtGui.QImage): # pragma: no cover
pix_map = QtGui.QPixmap.fromImage(icon)
if pix_map:
button_icon.addPixmap(pix_map, QtGui.QIcon.Normal, QtGui.QIcon.Off)
diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py
index 198702e0d..4a477a3a0 100644
--- a/openlp/plugins/songs/lib/songstab.py
+++ b/openlp/plugins/songs/lib/songstab.py
@@ -154,17 +154,16 @@ class SongsTab(SettingsTab):
['ccli_number', translate('SongsPlugin.SongsTab', 'Song CCLI Number'), True, False],
['topics', translate('SongsPlugin.SongsTab', 'Topics'), False, True],
]
- placeholder_info = '
\n{ph} | {desc} |
\n'\
- .format(ph=translate('SongsPlugin.SongsTab', 'Placeholder'),
- desc=translate('SongsPlugin.SongsTab', 'Description'))
+ placeholder_info = '{ph} | {desc} |
'.format(
+ ph=translate('SongsPlugin.SongsTab', 'Placeholder'), desc=translate('SongsPlugin.SongsTab', 'Description'))
for placeholder in placeholders:
- placeholder_info += '${{{pl}}} | {des}{opt} |
\n'\
- .format(pl=placeholder[0], des=placeholder[1],
- opt=(' ¹' if placeholder[2] else '') +
- (' ²' if placeholder[3] else ''))
+ placeholder_info += '${{{pl}}} | {des}{opt} |
'.format(
+ pl=placeholder[0], des=placeholder[1], opt=(' 1' if placeholder[2] else '') +
+ (' 2' if placeholder[3] else ''))
placeholder_info += '
'
- placeholder_info += '\n
¹ {}'.format(translate('SongsPlugin.SongsTab', 'can be empty'))
- placeholder_info += '\n
² {}'.format(translate('SongsPlugin.SongsTab', 'list of entries, can be empty'))
+ placeholder_info += '1 {}
'.format(translate('SongsPlugin.SongsTab', 'can be empty'))
+ placeholder_info += '2 {}
'.format(
+ translate('SongsPlugin.SongsTab', 'list of entries, can be empty'))
self.footer_placeholder_info.setHtml(placeholder_info)
self.footer_placeholder_info.setReadOnly(True)
diff --git a/tests/functional/openlp_core/api/v2/test_core.py b/tests/functional/openlp_core/api/v2/test_core.py
index 5f2428489..3dcf2ba17 100644
--- a/tests/functional/openlp_core/api/v2/test_core.py
+++ b/tests/functional/openlp_core/api/v2/test_core.py
@@ -113,6 +113,11 @@ def test_toggle_display_invalid_action(flask_client, settings):
assert res.status_code == 400
+def test_toggle_display_no_data(flask_client, settings):
+ res = flask_client.post('/api/v2/core/display', json={})
+ assert res.status_code == 400
+
+
def test_toggle_display_valid_action_updates_controller(flask_client, settings):
class FakeController:
class Emitter:
diff --git a/tests/functional/openlp_core/lib/test_lib.py b/tests/functional/openlp_core/lib/test_lib.py
index 756db3147..6bae20572 100644
--- a/tests/functional/openlp_core/lib/test_lib.py
+++ b/tests/functional/openlp_core/lib/test_lib.py
@@ -220,29 +220,30 @@ def test_build_icon_with_resource():
# best we can do is to assert that we get back a MagicMock object.
assert isinstance(result, MagicMock), 'The result should be a MagicMock, because we mocked it out'
- def test_image_to_byte(self):
- """
- Test the image_to_byte() function
- """
- with patch('openlp.core.lib.QtCore') as MockedQtCore:
- # GIVEN: A set of mocked-out Qt classes
- mocked_byte_array = MagicMock()
- MockedQtCore.QByteArray.return_value = mocked_byte_array
- mocked_buffer = MagicMock()
- MockedQtCore.QBuffer.return_value = mocked_buffer
- MockedQtCore.QIODevice.WriteOnly = 'writeonly'
- mocked_image = MagicMock()
- # WHEN: We convert an image to a byte array
- result = image_to_byte(mocked_image, base_64=False)
+def test_image_to_byte():
+ """
+ Test the image_to_byte() function
+ """
+ with patch('openlp.core.lib.QtCore') as MockedQtCore:
+ # GIVEN: A set of mocked-out Qt classes
+ mocked_byte_array = MagicMock()
+ MockedQtCore.QByteArray.return_value = mocked_byte_array
+ mocked_buffer = MagicMock()
+ MockedQtCore.QBuffer.return_value = mocked_buffer
+ MockedQtCore.QIODevice.WriteOnly = 'writeonly'
+ mocked_image = MagicMock()
- # THEN: We should receive the mocked_buffer
- MockedQtCore.QByteArray.assert_called_with()
- MockedQtCore.QBuffer.assert_called_with(mocked_byte_array)
- mocked_buffer.open.assert_called_with('writeonly')
- mocked_image.save.assert_called_with(mocked_buffer, "PNG")
- assert mocked_byte_array.toBase64.called is False
- assert mocked_byte_array == result, 'The mocked out byte array should be returned'
+ # WHEN: We convert an image to a byte array
+ result = image_to_byte(mocked_image, base_64=False)
+
+ # THEN: We should receive the mocked_buffer
+ MockedQtCore.QByteArray.assert_called_with()
+ MockedQtCore.QBuffer.assert_called_with(mocked_byte_array)
+ mocked_buffer.open.assert_called_with('writeonly')
+ mocked_image.save.assert_called_with(mocked_buffer, "PNG")
+ assert mocked_byte_array.toBase64.called is False
+ assert mocked_byte_array == result, 'The mocked out byte array should be returned'
def test_image_to_byte_base_64():
@@ -498,6 +499,25 @@ def test_create_thumb_empty_img():
pass
+@patch('openlp.core.lib.QtGui.QImageReader')
+@patch('openlp.core.lib.build_icon')
+def test_create_thumb_path_fails(mocked_build_icon, MockQImageReader):
+ """
+ Test that build_icon() is run against the image_path when the thumbnail fails to be created
+ """
+ # GIVEN: A bunch of mocks
+ image_path = RESOURCE_PATH / 'church.jpg'
+ thumb_path = Path('doesnotexist')
+ mocked_image_reader = MagicMock()
+ mocked_image_reader.size.return_value.isEmpty.return_value = True
+
+ # WHEN: Create the thumb
+ create_thumb(image_path, thumb_path)
+
+ # THEN: The image path should have been used
+ mocked_build_icon.assert_called_once_with(image_path)
+
+
@patch('openlp.core.lib.QtWidgets', MagicMock())
def test_check_item_selected_true():
"""
@@ -631,6 +651,42 @@ def test_resize_thumb_ignoring_aspect_ratio():
assert image.pixel(0, 0) == wanted_background_rgb, 'The background should be white.'
+def test_resize_thumb_width_aspect_ratio():
+ """
+ Test the resize_thumb() function using the image's width as the reference
+ """
+ # GIVEN: A path to an image.
+ image_path = str(RESOURCE_PATH / 'church.jpg')
+ wanted_width = 10
+ wanted_height = 1000
+
+ # WHEN: Resize the image and add a background.
+ image = resize_image(image_path, wanted_width, wanted_height)
+
+ # THEN: Check if the size is correct and the background was set.
+ result_size = image.size()
+ assert wanted_height == result_size.height(), 'The image should have the requested height.'
+ assert wanted_width == result_size.width(), 'The image should have the requested width.'
+
+
+def test_resize_thumb_same_aspect_ratio():
+ """
+ Test the resize_thumb() function when the image and the wanted aspect ratio are the same
+ """
+ # GIVEN: A path to an image.
+ image_path = str(RESOURCE_PATH / 'church.jpg')
+ wanted_width = 1122
+ wanted_height = 1544
+
+ # WHEN: Resize the image and add a background.
+ image = resize_image(image_path, wanted_width, wanted_height)
+
+ # THEN: Check if the size is correct and the background was set.
+ result_size = image.size()
+ assert wanted_height == result_size.height(), 'The image should have the requested height.'
+ assert wanted_width == result_size.width(), 'The image should have the requested width.'
+
+
@patch('openlp.core.lib.QtCore.QLocale.createSeparatedList')
def test_create_separated_list_qlocate(mocked_createSeparatedList):
"""
diff --git a/tests/functional/openlp_core/ui/test_firsttimeform.py b/tests/functional/openlp_core/ui/test_firsttimeform.py
index 7a689c030..7b214ec8e 100644
--- a/tests/functional/openlp_core/ui/test_firsttimeform.py
+++ b/tests/functional/openlp_core/ui/test_firsttimeform.py
@@ -25,10 +25,11 @@ import pytest
from pathlib import Path
from unittest.mock import MagicMock, call, patch, DEFAULT
-from PyQt5 import QtWidgets
+from PyQt5 import QtCore, QtWidgets
from openlp.core.common.registry import Registry
from openlp.core.ui.firsttimeform import FirstTimeForm, ThemeListWidgetItem
+from openlp.core.ui.firsttimewizard import ThemeListWidget
INVALID_CONFIG = """
@@ -364,3 +365,22 @@ def test_on_projectors_check_box_unchecked(mock_settings):
# THEN: The visibility of the projects panel should have been set
mock_settings.value.assert_called_once_with('projector/show after wizard')
mock_settings.setValue.assert_called_once_with('projector/show after wizard', True)
+
+
+def test_theme_list_widget_resize(ftf_app):
+ """
+ Test that the resizeEvent() method in the ThemeListWidget works correctly
+ """
+ # GIVEN: An instance of the ThemeListWidget
+ widget = ThemeListWidget(None)
+
+ # WHEN: resizeEvent() is called
+ with patch.object(widget, 'viewport') as mocked_viewport, \
+ patch.object(widget, 'setGridSize') as mocked_setGridSize:
+ mocked_viewport.return_value.width.return_value = 600
+ widget.resizeEvent(None)
+
+ # THEN: Check that the correct calculations were done
+ mocked_setGridSize.assert_called_once_with(QtCore.QSize(149, 140))
+
+ # THEN: everything resizes correctly
diff --git a/tests/functional/openlp_plugins/bibles/test_lib.py b/tests/functional/openlp_plugins/bibles/test_lib.py
index b9eae6e67..1ed99537d 100644
--- a/tests/functional/openlp_plugins/bibles/test_lib.py
+++ b/tests/functional/openlp_plugins/bibles/test_lib.py
@@ -26,7 +26,7 @@ from unittest.mock import MagicMock, patch
from openlp.core.common.registry import Registry
from openlp.plugins.bibles import lib
-from openlp.plugins.bibles.lib import SearchResults, get_reference_match
+from openlp.plugins.bibles.lib import SearchResults, get_reference_match, update_reference_separators
@pytest.yield_fixture
@@ -252,3 +252,44 @@ def test_reference_matched_range_separator(mocked_bible_test):
# THEN: The list of references should be as the expected results
assert references == ranges
+
+
+def test_update_reference_separators_custom_seps(request, settings):
+ """
+ Test the update_reference_separators() function with custom separators
+ """
+ # Clean up after the test
+ def cleanup_references():
+ lib.REFERENCE_SEPARATORS = {}
+ settings.remove('bibles/verse separator')
+ settings.remove('bibles/range separator')
+ settings.remove('bibles/list separator')
+ settings.remove('bibles/end separator')
+ update_reference_separators()
+
+ request.addfinalizer(cleanup_references)
+
+ # GIVEN: A custom set of separators
+ settings.setValue('bibles/verse separator', ':||v')
+ settings.setValue('bibles/range separator', '-')
+ settings.setValue('bibles/list separator', ',')
+ settings.setValue('bibles/end separator', '.')
+
+ # WHEN: update_reference_separators() is called
+ update_reference_separators()
+
+ # THEN: The reference separators should be updated and correct
+ expected_separators = {
+ 'sep_e': '\\s*(?:\\.)\\s*',
+ 'sep_e_default': 'end',
+ 'sep_l': '\\s*(?:(?:[,‚]))\\s*',
+ 'sep_l_default': ',|and',
+ 'sep_l_display': ',',
+ 'sep_r': '\\s*(?:(?:[-\xad‐‑‒——−﹣-]))\\s*',
+ 'sep_r_default': '-|to',
+ 'sep_r_display': '-',
+ 'sep_v': '\\s*(?::|v)\\s*',
+ 'sep_v_default': ':|v|V|verse|verses',
+ 'sep_v_display': ':'
+ }
+ assert lib.REFERENCE_SEPARATORS == expected_separators