Merge branch 'fix-unreadable-footer-380' into 'master'

Fix up the formatting of the contents of the help box

Closes #380

See merge request openlp/openlp!163
This commit is contained in:
Tim Bentley 2020-04-04 06:51:02 +00:00
commit fb006dabcd
6 changed files with 154 additions and 33 deletions

View File

@ -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)

View File

@ -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 = '<table style="background: #eee">\n<tr><th><b>{ph}</b></th><th><b>{desc}</b></th></tr>\n'\
.format(ph=translate('SongsPlugin.SongsTab', 'Placeholder'),
desc=translate('SongsPlugin.SongsTab', 'Description'))
placeholder_info = '<table><tr><th><b>{ph}</b></th><th><b>{desc}</b></th></tr>'.format(
ph=translate('SongsPlugin.SongsTab', 'Placeholder'), desc=translate('SongsPlugin.SongsTab', 'Description'))
for placeholder in placeholders:
placeholder_info += '<tr><td>${{{pl}}}</td><td>{des}{opt}</td></tr>\n'\
.format(pl=placeholder[0], des=placeholder[1],
opt=('&nbsp;¹' if placeholder[2] else '') +
('&nbsp;²' if placeholder[3] else ''))
placeholder_info += '<tr><td>${{{pl}}}</td><td>{des}{opt}</td></tr>'.format(
pl=placeholder[0], des=placeholder[1], opt=('&nbsp;<sup>1</sup>' if placeholder[2] else '') +
('&nbsp;<sup>2</sup>' if placeholder[3] else ''))
placeholder_info += '</table>'
placeholder_info += '\n<br/>¹ {}'.format(translate('SongsPlugin.SongsTab', 'can be empty'))
placeholder_info += '\n<br/>² {}'.format(translate('SongsPlugin.SongsTab', 'list of entries, can be empty'))
placeholder_info += '<p><sup>1</sup> {}<br/>'.format(translate('SongsPlugin.SongsTab', 'can be empty'))
placeholder_info += '<sup>2</sup> {}</p>'.format(
translate('SongsPlugin.SongsTab', 'list of entries, can be empty'))
self.footer_placeholder_info.setHtml(placeholder_info)
self.footer_placeholder_info.setReadOnly(True)

View File

@ -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:

View File

@ -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):
"""

View File

@ -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

View File

@ -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