diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index cbec14a40..61b82780b 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -249,10 +249,11 @@ class UiFirstTimeWizard(object): self.no_internet_text = translate('OpenLP.FirstTimeWizard', 'No Internet connection was found. The First Time Wizard needs an Internet ' 'connection in order to be able to download sample songs, Bibles and themes.' - ' Click the Finish button now to start OpenLP with initial settings and ' + ' Click the %s button now to start OpenLP with initial settings and ' 'no sample data.\n\nTo re-run the First Time Wizard and import this sample ' 'data at a later time, check your Internet connection and re-run this ' - 'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.') + 'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.') % \ + clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.FinishButton)) self.cancel_wizard_text = translate('OpenLP.FirstTimeWizard', '\n\nTo cancel the First Time Wizard completely (and not start OpenLP), ' 'click the %s button now.') % \ @@ -272,5 +273,7 @@ class UiFirstTimeWizard(object): self.progress_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Please wait while resources are downloaded ' 'and OpenLP is configured.')) self.progress_label.setText(translate('OpenLP.FirstTimeWizard', 'Starting configuration process...')) - first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton1, translate('OpenLP.FirstTimeWizard', 'Finish')) - first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton2, translate('OpenLP.FirstTimeWizard', 'Cancel')) + first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton1, + clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.FinishButton))) + first_time_wizard.setButtonText(QtWidgets.QWizard.CustomButton2, + clean_button_text(first_time_wizard.buttonText(QtWidgets.QWizard.CancelButton))) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index a80640150..bb8a1a8a7 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -760,8 +760,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage used_count = plugin.uses_theme(theme) if used_count: plugin_usage = "%s%s" % (plugin_usage, (translate('OpenLP.ThemeManager', - '%s time(s) by %s') % - (used_count, plugin.name))) + '%(count)s time(s) by %(plugin)s') % + {'count': used_count, 'plugin': plugin.name})) plugin_usage = "%s\n" % plugin_usage if plugin_usage: critical_error_message_box(translate('OpenLP.ThemeManager', 'Unable to delete theme'), diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index c81e65575..4398688ee 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -504,7 +504,7 @@ class CWExtract(RegistryProperties): soup = get_soup_for_bible_ref(chapter_url) if not soup: return None - content = soup.find_all(('h4', {'class': 'small-header'})) + content = soup.find_all('h4', {'class': 'small-header'}) if not content: log.error('No books found in the Crosswalk response.') send_error_message('parse') diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index cd728a68b..1d7b5a897 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -764,6 +764,9 @@ class BibleMediaItem(MediaManagerItem): except IndexError: log.exception('The second_search_results does not have as many verses as the search_results.') break + except TypeError: + log.exception('The second_search_results does not have this book.') + break bible_text = '%s %d%s%d (%s, %s)' % (book, verse.chapter, verse_separator, verse.verse, version, second_version) else: diff --git a/openlp/plugins/bibles/lib/zefania.py b/openlp/plugins/bibles/lib/zefania.py index 6e9f0b956..9b44cdf26 100644 --- a/openlp/plugins/bibles/lib/zefania.py +++ b/openlp/plugins/bibles/lib/zefania.py @@ -70,7 +70,8 @@ class ZefaniaBible(BibleDB): log.error('Importing books from "%s" failed' % self.filename) return False self.save_meta('language_id', language_id) - num_books = int(zefania_bible_tree.xpath("count(//BIBLEBOOK)")) + num_books = int(zefania_bible_tree.xpath('count(//BIBLEBOOK)')) + self.wizard.progress_bar.setMaximum(int(zefania_bible_tree.xpath('count(//CHAPTER)'))) # Strip tags we don't use - keep content etree.strip_tags(zefania_bible_tree, ('STYLE', 'GRAM', 'NOTE', 'SUP', 'XREF')) # Strip tags we don't use - remove content diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 1d45f52b2..0e03bfe7c 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -255,6 +255,7 @@ class VerseType(object): for num, translation in enumerate(VerseType.translated_names): if verse_name == translation.lower(): return num + return None @staticmethod def from_loose_input(verse_name, default=Other): @@ -270,7 +271,7 @@ class VerseType(object): if verse_index is None: verse_index = VerseType.from_string(verse_name, default) elif len(verse_name) == 1: - verse_index = VerseType.from_translated_tag(verse_name, default) + verse_index = VerseType.from_translated_tag(verse_name, None) if verse_index is None: verse_index = VerseType.from_tag(verse_name, default) else: diff --git a/openlp/plugins/songs/lib/importers/wordsofworship.py b/openlp/plugins/songs/lib/importers/wordsofworship.py index 8b87ee214..6135ae2b8 100644 --- a/openlp/plugins/songs/lib/importers/wordsofworship.py +++ b/openlp/plugins/songs/lib/importers/wordsofworship.py @@ -107,9 +107,9 @@ class WordsOfWorshipImport(SongImport): song_data = open(source, 'rb') if song_data.read(19).decode() != 'WoW File\nSong Words': self.log_error(source, - str(translate('SongsPlugin.WordsofWorshipSongImport', - 'Invalid Words of Worship song file. Missing "%s" header.' - % 'WoW File\\nSong Words'))) + translate('SongsPlugin.WordsofWorshipSongImport', + 'Invalid Words of Worship song file. Missing "%s" header.') + % 'WoW File\\nSong Words') continue # Seek to byte which stores number of blocks in the song song_data.seek(56) @@ -117,9 +117,9 @@ class WordsOfWorshipImport(SongImport): song_data.seek(66) if song_data.read(16).decode() != 'CSongDoc::CBlock': self.log_error(source, - str(translate('SongsPlugin.WordsofWorshipSongImport', - 'Invalid Words of Worship song file. Missing "%s" ' - 'string.' % 'CSongDoc::CBlock'))) + translate('SongsPlugin.WordsofWorshipSongImport', + 'Invalid Words of Worship song file. Missing "%s" string.') + % 'CSongDoc::CBlock') continue # Seek to the beginning of the first block song_data.seek(82) diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py index d30361d63..33a4ee96b 100644 --- a/tests/functional/__init__.py +++ b/tests/functional/__init__.py @@ -26,12 +26,12 @@ import sys from PyQt5 import QtWidgets if sys.version_info[1] >= 3: - from unittest.mock import ANY, MagicMock, patch, mock_open, call + from unittest.mock import ANY, MagicMock, patch, mock_open, call, PropertyMock else: - from mock import ANY, MagicMock, patch, mock_open, call + from mock import ANY, MagicMock, patch, mock_open, call, PropertyMock # Only one QApplication can be created. Use QtWidgets.QApplication.instance() when you need to "create" a QApplication. application = QtWidgets.QApplication([]) application.setApplicationName('OpenLP') -__all__ = ['ANY', 'MagicMock', 'patch', 'mock_open', 'call', 'application'] +__all__ = ['ANY', 'MagicMock', 'patch', 'mock_open', 'call', 'application', 'PropertyMock'] diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index 8cca502b0..77da4f543 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -26,7 +26,7 @@ from unittest import TestCase from openlp.plugins.songs.lib import VerseType, clean_string, clean_title, strip_rtf from openlp.plugins.songs.lib.songcompare import songs_probably_equal, _remove_typos, _op_length -from tests.functional import patch, MagicMock +from tests.functional import patch, MagicMock, PropertyMock class TestLib(TestCase): @@ -477,3 +477,27 @@ class TestVerseType(TestCase): # THEN: The result should be None self.assertIsNone(result, 'The result should be None, but was "%s"' % result) + + @patch('openlp.plugins.songs.lib.VerseType.translated_tags', new_callable=PropertyMock, return_value=['x']) + def from_loose_input_with_invalid_input_test(self, mocked_translated_tags): + """ + Test that the from_loose_input() method returns a sane default when passed an invalid tag and None as default. + """ + # GIVEN: A mocked VerseType.translated_tags + # WHEN: We run the from_loose_input() method with an invalid verse type, we get the specified default back + result = VerseType.from_loose_input('m', None) + + # THEN: The result should be None + self.assertIsNone(result, 'The result should be None, but was "%s"' % result) + + @patch('openlp.plugins.songs.lib.VerseType.translated_tags', new_callable=PropertyMock, return_value=['x']) + def from_loose_input_with_valid_input_test(self, mocked_translated_tags): + """ + Test that the from_loose_input() method returns valid output on valid input. + """ + # GIVEN: A mocked VerseType.translated_tags + # WHEN: We run the from_loose_input() method with a valid verse type, we get the expected VerseType back + result = VerseType.from_loose_input('v') + + # THEN: The result should be a Verse + self.assertEqual(result, VerseType.Verse, 'The result should be a verse, but was "%s"' % result)