From fa9a3c6f92a6d7107005acd38ac0e7f52091dd53 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 11 Mar 2020 21:53:41 +0000 Subject: [PATCH] Tests plugin 5 --- tests/conftest.py | 7 + .../openlp_core/lib/test_serviceitem.py | 21 +- .../songs/test_chordproimport.py | 25 +- .../songs/test_easyslidesimport.py | 23 +- .../openlp_plugins/songs/test_editsongform.py | 132 +++---- .../songs/test_editverseform.py | 128 +++---- .../openlp_plugins/songs/test_lyriximport.py | 27 +- .../songs/test_powerpraiseimport.py | 23 +- .../songs/test_presentationmanagerimport.py | 28 +- .../songs/test_songproimport.py | 19 +- .../songs/test_songshowplusimport.py | 33 +- .../songs/test_sundayplusimport.py | 25 +- .../openlp_plugins/songs/test_videopsalm.py | 29 +- .../songs/test_worshipassistantimport.py | 28 +- .../songs/test_zionworximport.py | 18 +- tests/helpers/songfileimport.py | 3 +- .../openlp_core/ui/test_servicenotedialog.py | 91 ++--- .../openlp_core/ui/test_settings_form.py | 244 ++++++------- .../openlp_core/ui/test_shortcutlistform.py | 326 +++++++++--------- .../openlp_core/ui/test_starttimedialog.py | 138 ++++---- .../openlp_core/ui/test_thememanager.py | 163 ++++----- .../openlp_core/widgets/test_edits.py | 198 +++++------ .../openlp_core/widgets/test_views.py | 129 +++---- 23 files changed, 782 insertions(+), 1076 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 5036c6cbe..499afd19d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -96,3 +96,10 @@ def mock_settings(qapp, registry): def state(): yield State().load_settings() State._instances = {} + + +@pytest.fixture() +def state_media(state): + State().add_service("media", 0) + State().update_pre_conditions("media", True) + State().flush_preconditions() diff --git a/tests/functional/openlp_core/lib/test_serviceitem.py b/tests/functional/openlp_core/lib/test_serviceitem.py index 4d547621c..244c50bc1 100644 --- a/tests/functional/openlp_core/lib/test_serviceitem.py +++ b/tests/functional/openlp_core/lib/test_serviceitem.py @@ -26,7 +26,6 @@ import pytest from pathlib import Path from unittest.mock import Mock, MagicMock, patch -from openlp.core.state import State from openlp.core.common import ThemeLevel, md5_hash from openlp.core.common.enum import ServiceItemType from openlp.core.common.registry import Registry @@ -62,13 +61,6 @@ FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456'] TEST_PATH = RESOURCE_PATH / 'service' -@pytest.fixture() -def state_env(state): - State().add_service("media", 0) - State().update_pre_conditions("media", True) - State().flush_preconditions() - - @pytest.fixture() def service_item_env(state): # Mock the renderer and its format_slide method @@ -97,7 +89,7 @@ def test_service_item_basic(): assert service_item.missing_frames() is True, 'There should not be any frames in the service item' -def test_service_item_load_custom_from_service(state_env, settings, service_item_env): +def test_service_item_load_custom_from_service(state_media, settings, service_item_env): """ Test the Service Item - adding a custom slide from a saved service """ @@ -108,9 +100,6 @@ def test_service_item_load_custom_from_service(state_env, settings, service_item # WHEN: We add a custom from a saved serviceand set the media state line = convert_file_service_item(TEST_PATH, 'serviceitem_custom_1.osj') - State().add_service("media", 0) - State().update_pre_conditions("media", True) - State().flush_preconditions() service_item.set_from_service(line) # THEN: We should get back a valid service item @@ -127,7 +116,7 @@ def test_service_item_load_custom_from_service(state_env, settings, service_item assert '' == service_item.get_frame_title(2), 'Blank has been returned as the title of slide 3' -def test_service_item_load_image_from_service(state_env, settings): +def test_service_item_load_image_from_service(state_media, settings): """ Test the Service Item - adding an image from a saved service """ @@ -169,7 +158,7 @@ def test_service_item_load_image_from_service(state_env, settings): @patch('openlp.core.lib.serviceitem.os.path.exists') @patch('openlp.core.lib.serviceitem.AppLocation.get_section_data_path') -def test_service_item_load_image_from_local_service(mocked_get_section_data_path, mocked_exists, settings, state_env): +def test_service_item_load_image_from_local_service(mocked_get_section_data_path, mocked_exists, settings, state_media): """ Test the Service Item - adding an image from a saved local service """ @@ -293,7 +282,7 @@ def test_add_from_command_for_a_presentation_thumb(mocked_get_section_data_path, # assert 1 == mocked_image_manager.add_image.call_count, 'image_manager should be used' -def test_service_item_load_optical_media_from_service(state_env): +def test_service_item_load_optical_media_from_service(state_media): """ Test the Service Item - load an optical media item """ @@ -315,7 +304,7 @@ def test_service_item_load_optical_media_from_service(state_env): assert service_item.media_length == 17.694, 'Media length should be 17.694' -def test_service_item_load_song_and_audio_from_service(state_env, settings, service_item_env): +def test_service_item_load_song_and_audio_from_service(state_media, settings, service_item_env): """ Test the Service Item - adding a song slide from a saved service """ diff --git a/tests/functional/openlp_plugins/songs/test_chordproimport.py b/tests/functional/openlp_plugins/songs/test_chordproimport.py index 989a9a173..9e38b877c 100644 --- a/tests/functional/openlp_plugins/songs/test_chordproimport.py +++ b/tests/functional/openlp_plugins/songs/test_chordproimport.py @@ -31,25 +31,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'chordpro' def test_chordpro(mock_settings): - class TestChordProFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'ChordProImport' - self.importer_module_name = 'chordpro' - super().__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an ChordPro file works correctly on various files - """ - # Mock out the settings - always return False - Registry().get('settings').value.side_effect = lambda value: True \ - if value == 'songs/enable chords' else False - # Do the test import - self.file_import([TEST_PATH / 'swing-low.chordpro'], - self.load_external_result_data(TEST_PATH / 'swing-low.json')) - - test_file_import = TestChordProFileImport() + test_file_import = SongImportTestHelper('ChordProImport', 'chordpro') test_file_import.setUp() - test_file_import.test_song_import() + Registry().get('settings').value.side_effect = lambda value: True if value == 'songs/enable chords' else False + # Do the test import + test_file_import.file_import([TEST_PATH / 'swing-low.chordpro'], + test_file_import.load_external_result_data(TEST_PATH / 'swing-low.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_easyslidesimport.py b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py index 417776d8e..639ea1b28 100644 --- a/tests/functional/openlp_plugins/songs/test_easyslidesimport.py +++ b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py @@ -30,23 +30,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'easyslides' def test_easyslides(mock_settings): - class TestEasySlidesFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'EasySlidesImport' - self.importer_module_name = 'easyslides' - super().__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an EasySlides file works correctly on various files - """ - self.file_import(TEST_PATH / 'amazing-grace.xml', - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - self.file_import(TEST_PATH / 'Export_2017-01-12_BB.xml', - self.load_external_result_data(TEST_PATH / 'Export_2017-01-12_BB.json')) - - test_file_import = TestEasySlidesFileImport() + test_file_import = SongImportTestHelper('EasySlidesImport', 'easyslides') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import(TEST_PATH / 'amazing-grace.xml', + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + test_file_import.file_import(TEST_PATH / 'Export_2017-01-12_BB.xml', + test_file_import.load_external_result_data(TEST_PATH / 'Export_2017-01-12_BB.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_editsongform.py b/tests/functional/openlp_plugins/songs/test_editsongform.py index 1143e2355..9e361525e 100644 --- a/tests/functional/openlp_plugins/songs/test_editsongform.py +++ b/tests/functional/openlp_plugins/songs/test_editsongform.py @@ -21,88 +21,68 @@ """ This module contains tests for the lib submodule of the Songs plugin. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, patch -from PyQt5 import QtCore - -from openlp.core.common.registry import Registry from openlp.plugins.songs.forms.editsongform import EditSongForm -from tests.helpers.testmixin import TestMixin -class TestEditSongForm(TestCase, TestMixin): +@pytest.fixture() +def edit_song_form(): + with patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__', return_value=None): + return EditSongForm(None, MagicMock(), MagicMock()) + + +def test_validate_matching_tags(edit_song_form): + # Given a set of tags + tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{su}', '{/su}'] + + # WHEN we validate them + valid = edit_song_form._validate_tags(tags) + + # THEN they should be valid + assert valid is True, "The tags list should be valid" + + +def test_validate_nonmatching_tags(edit_song_form): + # Given a set of tags + tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{br}', '{su}', '{/su}'] + + # WHEN we validate them + valid = edit_song_form._validate_tags(tags) + + # THEN they should be valid + assert valid is True, "The tags list should be valid" + + +@patch('openlp.plugins.songs.forms.editsongform.set_case_insensitive_completer') +def test_load_objects(mocked_set_case_insensitive_completer, edit_song_form, settings): """ - Test the functions in the :mod:`lib` module. + Test the _load_objects() method """ - def setUp(self): - """ - Set up the components need for all tests. - """ - Registry.create() - Registry().register('service_list', MagicMock()) - Registry().register('main_window', MagicMock()) - self.setup_application() - self.build_settings() - Registry().register('settings', self.setting) - with patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__', return_value=None): - self.edit_song_form = EditSongForm(None, MagicMock(), MagicMock()) - QtCore.QLocale.setDefault(QtCore.QLocale('en_GB')) + # GIVEN: A song edit form and some mocked stuff + mocked_class = MagicMock() + mocked_class.name = 'Author' + mocked_combo = MagicMock() + mocked_combo.count.return_value = 0 + mocked_cache = MagicMock() + mocked_object = MagicMock() + mocked_object.name = 'Charles' + mocked_object.id = 1 + mocked_manager = MagicMock() + mocked_manager.get_all_objects.return_value = [mocked_object] + edit_song_form.manager = mocked_manager - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - self.destroy_settings() + # WHEN: _load_objects() is called + edit_song_form._load_objects(mocked_class, mocked_combo, mocked_cache) - def test_validate_matching_tags(self): - # Given a set of tags - tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{su}', '{/su}'] - - # WHEN we validate them - valid = self.edit_song_form._validate_tags(tags) - - # THEN they should be valid - assert valid is True, "The tags list should be valid" - - def test_validate_nonmatching_tags(self): - # Given a set of tags - tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{br}', '{su}', '{/su}'] - - # WHEN we validate them - valid = self.edit_song_form._validate_tags(tags) - - # THEN they should be valid - assert valid is True, "The tags list should be valid" - - @patch('openlp.plugins.songs.forms.editsongform.set_case_insensitive_completer') - def test_load_objects(self, mocked_set_case_insensitive_completer): - """ - Test the _load_objects() method - """ - # GIVEN: A song edit form and some mocked stuff - mocked_class = MagicMock() - mocked_class.name = 'Author' - mocked_combo = MagicMock() - mocked_combo.count.return_value = 0 - mocked_cache = MagicMock() - mocked_object = MagicMock() - mocked_object.name = 'Charles' - mocked_object.id = 1 - mocked_manager = MagicMock() - mocked_manager.get_all_objects.return_value = [mocked_object] - self.edit_song_form.manager = mocked_manager - - # WHEN: _load_objects() is called - self.edit_song_form._load_objects(mocked_class, mocked_combo, mocked_cache) - - # THEN: All the correct methods should have been called - self.edit_song_form.manager.get_all_objects.assert_called_once_with(mocked_class) - mocked_combo.clear.assert_called_once_with() - mocked_combo.count.assert_called_once_with() - mocked_combo.addItem.assert_called_once_with('Charles') - mocked_cache.append.assert_called_once_with('Charles') - mocked_combo.setItemData.assert_called_once_with(0, 1) - mocked_set_case_insensitive_completer.assert_called_once_with(mocked_cache, mocked_combo) - mocked_combo.setCurrentIndex.assert_called_once_with(-1) - mocked_combo.setCurrentText.assert_called_once_with('') + # THEN: All the correct methods should have been called + edit_song_form.manager.get_all_objects.assert_called_once_with(mocked_class) + mocked_combo.clear.assert_called_once_with() + mocked_combo.count.assert_called_once_with() + mocked_combo.addItem.assert_called_once_with('Charles') + mocked_cache.append.assert_called_once_with('Charles') + mocked_combo.setItemData.assert_called_once_with(0, 1) + mocked_set_case_insensitive_completer.assert_called_once_with(mocked_cache, mocked_combo) + mocked_combo.setCurrentIndex.assert_called_once_with(-1) + mocked_combo.setCurrentText.assert_called_once_with('') diff --git a/tests/functional/openlp_plugins/songs/test_editverseform.py b/tests/functional/openlp_plugins/songs/test_editverseform.py index 86a449ef3..7057dd5ae 100644 --- a/tests/functional/openlp_plugins/songs/test_editverseform.py +++ b/tests/functional/openlp_plugins/songs/test_editverseform.py @@ -21,94 +21,76 @@ """ This module contains tests for the editverseform of the Songs plugin. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock -from PyQt5 import QtCore - -from openlp.core.common.registry import Registry from openlp.plugins.songs.forms.editverseform import EditVerseForm -from tests.helpers.testmixin import TestMixin -class TestEditVerseForm(TestCase, TestMixin): +@pytest.fixture() +def edit_verse_form(settings): + return EditVerseForm(None) + + +def test_update_suggested_verse_number_has_no_effect(edit_verse_form): """ - Test the functions in the :mod:`lib` module. + Test that update_suggested_verse_number() has no effect when editing a single verse """ - def setUp(self): - """ - Set up the components need for all tests. - """ - self.setup_application() - self.build_settings() - self.setting.setValue('songs/enable chords', True) - Registry.create() - Registry().register('settings', self.setting) - self.edit_verse_form = EditVerseForm(None) - QtCore.QLocale.setDefault(QtCore.QLocale('en_GB')) + # GIVEN some input values + edit_verse_form.has_single_verse = True + edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=0) + edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') + edit_verse_form.verse_number_box.setValue(3) - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - self.destroy_settings() + # WHEN the method is called + edit_verse_form.update_suggested_verse_number() - def test_update_suggested_verse_number_has_no_effect(self): - """ - Test that update_suggested_verse_number() has no effect when editing a single verse - """ - # GIVEN some input values - self.edit_verse_form.has_single_verse = True - self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=0) - self.edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') - self.edit_verse_form.verse_number_box.setValue(3) + # THEN the verse number must not be changed + assert 3 == edit_verse_form.verse_number_box.value(), 'The verse number should be 3' - # WHEN the method is called - self.edit_verse_form.update_suggested_verse_number() - # THEN the verse number must not be changed - assert 3 == self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3' +def test_update_suggested_verse_number_different_type(edit_verse_form): + """ + Test that update_suggested_verse_number() returns 0 when editing a second verse of a different type + """ + # GIVEN some input values + edit_verse_form.has_single_verse = False + edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=2) + edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') + edit_verse_form.verse_number_box.setValue(3) - def test_update_suggested_verse_number_different_type(self): - """ - Test that update_suggested_verse_number() returns 0 when editing a second verse of a different type - """ - # GIVEN some input values - self.edit_verse_form.has_single_verse = False - self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=2) - self.edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') - self.edit_verse_form.verse_number_box.setValue(3) + # WHEN the method is called + edit_verse_form.update_suggested_verse_number() - # WHEN the method is called - self.edit_verse_form.update_suggested_verse_number() + # THEN the verse number must be changed to 1 + assert 1 == edit_verse_form.verse_number_box.value(), 'The verse number should be 1' - # THEN the verse number must be changed to 1 - assert 1 == self.edit_verse_form.verse_number_box.value(), 'The verse number should be 1' - def test_on_divide_split_button_clicked(self): - """ - Test that divide adds text at the correct position - """ - # GIVEN some input values - self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4) - self.edit_verse_form.verse_text_edit.setPlainText('Text\n') +def test_on_divide_split_button_clicked(edit_verse_form): + """ + Test that divide adds text at the correct position + """ + # GIVEN some input values + edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4) + edit_verse_form.verse_text_edit.setPlainText('Text\n') - # WHEN the method is called - self.edit_verse_form.on_forced_split_button_clicked() - # THEN the verse number must not be changed - assert '[--}{--]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ - 'The verse number should be [--}{--]\nText\n' + # WHEN the method is called + edit_verse_form.on_forced_split_button_clicked() + # THEN the verse number must not be changed + assert '[--}{--]\nText\n' == edit_verse_form.verse_text_edit.toPlainText(), \ + 'The verse number should be [--}{--]\nText\n' - def test_on_split_button_clicked(self): - """ - Test that divide adds text at the correct position - """ - # GIVEN some input values - self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4) - self.edit_verse_form.verse_text_edit.setPlainText('Text\n') - # WHEN the method is called - self.edit_verse_form.on_overflow_split_button_clicked() - # THEN the verse number must not be changed - assert '[---]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ - 'The verse number should be [---]\nText\n' +def test_on_split_button_clicked(edit_verse_form): + """ + Test that divide adds text at the correct position + """ + # GIVEN some input values + edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4) + edit_verse_form.verse_text_edit.setPlainText('Text\n') + + # WHEN the method is called + edit_verse_form.on_overflow_split_button_clicked() + # THEN the verse number must not be changed + assert '[---]\nText\n' == edit_verse_form.verse_text_edit.toPlainText(), \ + 'The verse number should be [---]\nText\n' diff --git a/tests/functional/openlp_plugins/songs/test_lyriximport.py b/tests/functional/openlp_plugins/songs/test_lyriximport.py index 4c30de506..a739acd39 100644 --- a/tests/functional/openlp_plugins/songs/test_lyriximport.py +++ b/tests/functional/openlp_plugins/songs/test_lyriximport.py @@ -30,25 +30,12 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'lyrix' def test_Lyrix(mock_settings): - class TestLyrixFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'LyrixImport' - self.importer_module_name = 'lyrix' - super(TestLyrixFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an LyriX file works correctly on various files - """ - self.file_import([TEST_PATH / 'A06.TXT'], - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - self.file_import([TEST_PATH / 'A002.TXT'], - self.load_external_result_data(TEST_PATH / 'Amazing Grace2.json')) - self.file_import([TEST_PATH / 'AO05.TXT'], - self.load_external_result_data(TEST_PATH / 'in die regterhand.json')) - - test_file_import = TestLyrixFileImport() + test_file_import = SongImportTestHelper('LyrixImport', 'lyrix') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import([TEST_PATH / 'A06.TXT'], + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + test_file_import.file_import([TEST_PATH / 'A002.TXT'], + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace2.json')) + test_file_import.file_import([TEST_PATH / 'AO05.TXT'], + test_file_import.load_external_result_data(TEST_PATH / 'in die regterhand.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py index 667150727..1e14af32e 100644 --- a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py +++ b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py @@ -31,23 +31,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'powerpraise' def test_power_praise(mock_settings): - class TestPowerPraiseFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'PowerPraiseImport' - self.importer_module_name = 'powerpraise' - super(TestPowerPraiseFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading a PowerPraise file works correctly - """ - self.file_import([TEST_PATH / 'Naher, mein Gott zu Dir.ppl'], - self.load_external_result_data(TEST_PATH / 'Naher, mein Gott zu Dir.json')) - self.file_import([TEST_PATH / 'You are so faithful.ppl'], - self.load_external_result_data(TEST_PATH / 'You are so faithful.json')) - - test_file_import = TestPowerPraiseFileImport() + test_file_import = SongImportTestHelper('PowerPraiseImport', 'powerpraise') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import([TEST_PATH / 'Naher, mein Gott zu Dir.ppl'], + test_file_import.load_external_result_data(TEST_PATH / 'Naher, mein Gott zu Dir.json')) + test_file_import.file_import([TEST_PATH / 'You are so faithful.ppl'], + test_file_import.load_external_result_data(TEST_PATH / 'You are so faithful.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py index f8e1ea7cf..46e8cd782 100644 --- a/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py +++ b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py @@ -21,9 +21,6 @@ """ This module contains tests for the PresentationManager song importer. """ -from unittest import skipIf - -from openlp.core.common import is_macosx from tests.helpers.songfileimport import SongImportTestHelper from tests.utils.constants import RESOURCE_PATH @@ -33,24 +30,11 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'presentationmanager' def test_presenter_manager(mock_settings): - class TestPresentationManagerFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'PresentationManagerImport' - self.importer_module_name = 'presentationmanager' - super(TestPresentationManagerFileImport, self).__init__(*args, **kwargs) - - @skipIf(is_macosx(), 'This test fails for an undetermined reason on macOS') - def test_song_import(self): - """ - Test that loading a PresentationManager file works correctly - """ - self.file_import([TEST_PATH / 'Great Is Thy Faithfulness.sng'], - self.load_external_result_data(TEST_PATH / 'Great Is Thy Faithfulness.json')) - self.file_import([TEST_PATH / 'Amazing Grace.sng'], - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - - test_file_import = TestPresentationManagerFileImport() + test_file_import = SongImportTestHelper('PresentationManagerImport', 'presentationmanager') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import([TEST_PATH / 'Great Is Thy Faithfulness.sng'], + test_file_import.load_external_result_data(TEST_PATH / + 'Great Is Thy Faithfulness.json')) + test_file_import.file_import([TEST_PATH / 'Amazing Grace.sng'], + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_songproimport.py b/tests/functional/openlp_plugins/songs/test_songproimport.py index 1f9035237..a8a89f559 100644 --- a/tests/functional/openlp_plugins/songs/test_songproimport.py +++ b/tests/functional/openlp_plugins/songs/test_songproimport.py @@ -31,21 +31,8 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'songpro' def test_song_pro(mock_settings): - class TestSongProFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'SongProImport' - self.importer_module_name = 'songpro' - super(TestSongProFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an SongPro file works correctly - """ - self.file_import(TEST_PATH / 'amazing-grace.txt', - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - - test_file_import = TestSongProFileImport() + test_file_import = SongImportTestHelper('SongProImport', 'songpro') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import(TEST_PATH / 'amazing-grace.txt', + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index 3d67f1ca7..f41aded82 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -35,29 +35,18 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'songshowplus' def test_song_show_plus(mock_settings): - class TestSongShowPlusFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'SongShowPlusImport' - self.importer_module_name = 'songshowplus' - super(TestSongShowPlusFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading a SongShow Plus file works correctly on various files - """ - self.file_import([TEST_PATH / 'Amazing Grace.sbsong'], - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - self.file_import([TEST_PATH / 'Beautiful Garden Of Prayer.sbsong'], - self.load_external_result_data(TEST_PATH / 'Beautiful Garden Of Prayer.json')) - self.file_import([TEST_PATH / 'a mighty fortress is our god.sbsong'], - self.load_external_result_data(TEST_PATH / 'a mighty fortress is our god.json')) - self.file_import([TEST_PATH / 'cleanse-me.sbsong'], - self.load_external_result_data(TEST_PATH / 'cleanse-me.json')) - - test_file_import = TestSongShowPlusFileImport() + test_file_import = SongImportTestHelper('SongShowPlusImport', 'songshowplus') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import([TEST_PATH / 'Amazing Grace.sbsong'], + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + test_file_import.file_import([TEST_PATH / 'Beautiful Garden Of Prayer.sbsong'], + test_file_import.load_external_result_data(TEST_PATH / + 'Beautiful Garden Of Prayer.json')) + test_file_import.file_import([TEST_PATH / 'a mighty fortress is our god.sbsong'], + test_file_import.load_external_result_data(TEST_PATH / + 'a mighty fortress is our god.json')) + test_file_import.file_import([TEST_PATH / 'cleanse-me.sbsong'], + test_file_import.load_external_result_data(TEST_PATH / 'cleanse-me.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_sundayplusimport.py b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py index 1248c3957..7a565f17a 100644 --- a/tests/functional/openlp_plugins/songs/test_sundayplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py @@ -32,24 +32,11 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'sundayplus' def test_sunday_plus(mock_settings): - class TestSundayPlusFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'SundayPlusImport' - self.importer_module_name = 'sundayplus' - super(TestSundayPlusFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an SundayPlus file works correctly on various files - """ - with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \ - mocked_retrieve_windows_encoding: - mocked_retrieve_windows_encoding.return_value = 'cp1252' - self.file_import([TEST_PATH / 'Amazing Grace.ptf'], - self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) - - test_file_import = TestSundayPlusFileImport() + test_file_import = SongImportTestHelper('SundayPlusImport', 'sundayplus') test_file_import.setUp() - test_file_import.test_song_import() + with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \ + mocked_retrieve_windows_encoding: + mocked_retrieve_windows_encoding.return_value = 'cp1252' + test_file_import.file_import([TEST_PATH / 'Amazing Grace.ptf'], + test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_videopsalm.py b/tests/functional/openlp_plugins/songs/test_videopsalm.py index f4bd4195e..00be8374c 100644 --- a/tests/functional/openlp_plugins/songs/test_videopsalm.py +++ b/tests/functional/openlp_plugins/songs/test_videopsalm.py @@ -31,27 +31,12 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'videopsalm' def test_video_psalms(mock_settings): - class TestVideoPsalmFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'VideoPsalmImport' - self.importer_module_name = 'videopsalm' - super(TestVideoPsalmFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an VideoPsalm file works correctly on various files - """ - # Mock out the settings - always return False - Registry().get('settings').value.side_effect = lambda value: True \ - if value == 'songs/enable chords' else False - # Do the test import - self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold.json', - self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold.json')) - self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold2.json', - self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold2.json')) - - test_file_import = TestVideoPsalmFileImport() + test_file_import = SongImportTestHelper('VideoPsalmImport', 'videopsalm') test_file_import.setUp() - test_file_import.test_song_import() + Registry().get('settings').value.side_effect = lambda value: True if value == 'songs/enable chords' else False + # Do the test import + test_file_import.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold.json', + test_file_import.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold.json')) + test_file_import.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold2.json', + test_file_import.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold2.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py index 6c2da532d..bba2f16c8 100644 --- a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py +++ b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py @@ -29,26 +29,14 @@ from tests.utils.constants import RESOURCE_PATH TEST_PATH = RESOURCE_PATH / 'songs' / 'worshipassistant' -def test_chordpro(mock_settings): +def test_worshipassistant(mock_settings): - class TestWorshipAssistantFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'WorshipAssistantImport' - self.importer_module_name = 'worshipassistant' - super(TestWorshipAssistantFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an Worship Assistant file works correctly - """ - self.file_import(TEST_PATH / 'du_herr.csv', self.load_external_result_data(TEST_PATH / 'du_herr.json')) - self.file_import(TEST_PATH / 'would_you_be_free.csv', - self.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) - self.file_import(TEST_PATH / 'would_you_be_free2.csv', - self.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) - - test_file_import = TestWorshipAssistantFileImport() + test_file_import = SongImportTestHelper('WorshipAssistantImport', 'worshipassistant') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import(TEST_PATH / 'du_herr.csv', + test_file_import.load_external_result_data(TEST_PATH / 'du_herr.json')) + test_file_import.file_import(TEST_PATH / 'would_you_be_free.csv', + test_file_import.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) + test_file_import.file_import(TEST_PATH / 'would_you_be_free2.csv', + test_file_import.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) test_file_import.tearDown() diff --git a/tests/functional/openlp_plugins/songs/test_zionworximport.py b/tests/functional/openlp_plugins/songs/test_zionworximport.py index a25720049..d76b3bbbc 100644 --- a/tests/functional/openlp_plugins/songs/test_zionworximport.py +++ b/tests/functional/openlp_plugins/songs/test_zionworximport.py @@ -49,20 +49,8 @@ def test_create_importer(registry): def test_zion_wrox(mock_settings): - class TestZionWorxFileImport(SongImportTestHelper): - - def __init__(self, *args, **kwargs): - self.importer_class_name = 'ZionWorxImport' - self.importer_module_name = 'zionworx' - super(TestZionWorxFileImport, self).__init__(*args, **kwargs) - - def test_song_import(self): - """ - Test that loading an ZionWorx file works correctly on various files - """ - self.file_import(TEST_PATH / 'zionworx.csv', self.load_external_result_data(TEST_PATH / 'zionworx.json')) - - test_file_import = TestZionWorxFileImport() + test_file_import = SongImportTestHelper('ZionWorxImport', 'zionworx') test_file_import.setUp() - test_file_import.test_song_import() + test_file_import.file_import(TEST_PATH / 'zionworx.csv', + test_file_import.load_external_result_data(TEST_PATH / 'zionworx.json')) test_file_import.tearDown() diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 11c74d568..89189d634 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -34,7 +34,8 @@ class SongImportTestHelper(object): This class is designed to be a helper class to reduce repetition when testing the import of song files. """ def __init__(self, *args, **kwargs): - super(SongImportTestHelper, self).__init__(*args, **kwargs) + self.importer_class_name = args[0] + self.importer_module_name = args[1] self.importer_module = __import__('openlp.plugins.songs.lib.importers.%s' % self.importer_module_name, fromlist=[self.importer_class_name]) self.importer_class = getattr(self.importer_module, self.importer_class_name) diff --git a/tests/interfaces/openlp_core/ui/test_servicenotedialog.py b/tests/interfaces/openlp_core/ui/test_servicenotedialog.py index 68374402f..09a283ff2 100644 --- a/tests/interfaces/openlp_core/ui/test_servicenotedialog.py +++ b/tests/interfaces/openlp_core/ui/test_servicenotedialog.py @@ -21,69 +21,54 @@ """ Package to test the openlp.core.ui package. """ -from unittest import TestCase +import pytest from unittest.mock import patch -from PyQt5 import QtCore, QtTest, QtWidgets +from PyQt5 import QtCore, QtTest -from openlp.core.common.registry import Registry -from openlp.core.ui import servicenoteform -from tests.helpers.testmixin import TestMixin +from openlp.core.ui.servicenoteform import ServiceNoteForm -class TestStartNoteDialog(TestCase, TestMixin): +@pytest.fixture() +def form(settings): + frm = ServiceNoteForm() + return frm - def setUp(self): - """ - Create the UI - """ - Registry.create() - self.setup_application() - self.main_window = QtWidgets.QMainWindow() - Registry().register('main_window', self.main_window) - self.form = servicenoteform.ServiceNoteForm() - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.form - del self.main_window +def test_basic_display(form): + """ + Test Service Note form functionality + """ + # GIVEN: A dialog with an empty text box + form.text_edit.setPlainText('') - def test_basic_display(self): - """ - Test Service Note form functionality - """ - # GIVEN: A dialog with an empty text box - self.form.text_edit.setPlainText('') + # WHEN displaying the UI and pressing enter + with patch('PyQt5.QtWidgets.QDialog.exec'): + form.exec() + ok_widget = form.button_box.button(form.button_box.Save) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # WHEN displaying the UI and pressing enter - with patch('PyQt5.QtWidgets.QDialog.exec'): - self.form.exec() - ok_widget = self.form.button_box.button(self.form.button_box.Save) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) + # THEN the following input text is returned + assert form.text_edit.toPlainText() == '', 'The returned text should be empty' - # THEN the following input text is returned - assert self.form.text_edit.toPlainText() == '', 'The returned text should be empty' + # WHEN displaying the UI, having set the text and pressing enter + text = 'OpenLP is the best worship software' + form.text_edit.setPlainText(text) + with patch('PyQt5.QtWidgets.QDialog.exec'): + form.exec() + ok_widget = form.button_box.button(form.button_box.Save) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # WHEN displaying the UI, having set the text and pressing enter - text = 'OpenLP is the best worship software' - self.form.text_edit.setPlainText(text) - with patch('PyQt5.QtWidgets.QDialog.exec'): - self.form.exec() - ok_widget = self.form.button_box.button(self.form.button_box.Save) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) + # THEN the following text is returned + assert form.text_edit.toPlainText() == text, 'The text originally entered should still be there' - # THEN the following text is returned - assert self.form.text_edit.toPlainText() == text, 'The text originally entered should still be there' + # WHEN displaying the UI, having set the text and pressing enter + form.text_edit.setPlainText('') + with patch('PyQt5.QtWidgets.QDialog.exec'): + form.exec() + form.text_edit.setPlainText(text) + ok_widget = form.button_box.button(form.button_box.Save) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # WHEN displaying the UI, having set the text and pressing enter - self.form.text_edit.setPlainText('') - with patch('PyQt5.QtWidgets.QDialog.exec'): - self.form.exec() - self.form.text_edit.setPlainText(text) - ok_widget = self.form.button_box.button(self.form.button_box.Save) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - - # THEN the following text is returned - assert self.form.text_edit.toPlainText() == text, 'The new text should be returned' + # THEN the following text is returned + assert form.text_edit.toPlainText() == text, 'The new text should be returned' diff --git a/tests/interfaces/openlp_core/ui/test_settings_form.py b/tests/interfaces/openlp_core/ui/test_settings_form.py index cd375ddf9..9f9ef9fae 100644 --- a/tests/interfaces/openlp_core/ui/test_settings_form.py +++ b/tests/interfaces/openlp_core/ui/test_settings_form.py @@ -21,172 +21,152 @@ """ Package to test the openlp.core.lib.settingsform package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, patch from PyQt5 import QtCore, QtTest from openlp.core.common.registry import Registry -from openlp.core.display.screens import ScreenList -from openlp.core.ui import settingsform -from tests.helpers.testmixin import TestMixin +from openlp.core.ui.settingsform import SettingsForm -SCREEN = { - 'primary': False, - 'number': 1, - 'size': QtCore.QRect(0, 0, 1024, 768) -} +@pytest.fixture() +def form(mock_settings): + frm = SettingsForm() + return frm -class TestSettingsForm(TestCase, TestMixin): +@pytest.fixture() +def dummy(): + return MagicMock(), MagicMock(), MagicMock() + + +def test_basic_cancel(form): """ - Test the PluginManager class + Test running the settings form and pressing Cancel """ + # GIVEN: An initial form - def setUp(self): - """ - Some pre-test setup required. - """ - self.dummy1 = MagicMock() - self.dummy2 = MagicMock() - self.dummy3 = MagicMock() - self.desktop = MagicMock() - self.setup_application() - self.desktop.primaryScreen.return_value = SCREEN['primary'] - self.desktop.screenCount.return_value = SCREEN['number'] - self.desktop.screenGeometry.return_value = SCREEN['size'] - Registry.create() - Registry().register('settings', MagicMock()) - self.screens = ScreenList.create(self.desktop) - self.form = settingsform.SettingsForm() + # WHEN displaying the UI and pressing cancel + with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject: + cancel_widget = form.button_box.button(form.button_box.Cancel) + QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton) - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.form + # THEN the dialog reject should have been called + assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called' - def test_basic_cancel(self): - """ - Test running the settings form and pressing Cancel - """ - # GIVEN: An initial form - # WHEN displaying the UI and pressing cancel - with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject: - cancel_widget = self.form.button_box.button(self.form.button_box.Cancel) - QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton) +def test_basic_accept(form): + """ + Test running the settings form and pressing Ok + """ + # GIVEN: An initial form - # THEN the dialog reject should have been called - assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called' + # WHEN displaying the UI and pressing Ok + with patch('PyQt5.QtWidgets.QDialog.accept') as mocked_accept: + ok_widget = form.button_box.button(form.button_box.Ok) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - def test_basic_accept(self): - """ - Test running the settings form and pressing Ok - """ - # GIVEN: An initial form + # THEN the dialog reject should have been called + assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called' - # WHEN displaying the UI and pressing Ok - with patch('PyQt5.QtWidgets.QDialog.accept') as mocked_accept: - ok_widget = self.form.button_box.button(self.form.button_box.Ok) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # THEN the dialog reject should have been called - assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called' +def test_basic_register(form): + """ + Test running the settings form and adding a single function + """ + # GIVEN: An initial form add a register function + form.register_post_process('function1') - def test_basic_register(self): - """ - Test running the settings form and adding a single function - """ - # GIVEN: An initial form add a register function - self.form.register_post_process('function1') + # WHEN displaying the UI and pressing Ok + with patch('PyQt5.QtWidgets.QDialog.accept'): + ok_widget = form.button_box.button(form.button_box.Ok) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # WHEN displaying the UI and pressing Ok - with patch('PyQt5.QtWidgets.QDialog.accept'): - ok_widget = self.form.button_box.button(self.form.button_box.Ok) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) + # THEN the processing stack should be empty + assert len(form.processes) == 0, 'The one requested process should have been removed from the stack' - # THEN the processing stack should be empty - assert len(self.form.processes) == 0, 'The one requested process should have been removed from the stack' - def test_register_multiple_functions(self): - """ - Test running the settings form and adding multiple functions - """ - # GIVEN: Registering a single function - self.form.register_post_process('function1') +def test_register_multiple_functions(form): + """ + Test running the settings form and adding multiple functions + """ + # GIVEN: Registering a single function + form.register_post_process('function1') - # WHEN testing the processing stack - # THEN the processing stack should have one item - assert len(self.form.processes) == 1, 'The one requested process should have been added to the stack' + # WHEN testing the processing stack + # THEN the processing stack should have one item + assert len(form.processes) == 1, 'The one requested process should have been added to the stack' - # GIVEN: Registering a new function - self.form.register_post_process('function2') + # GIVEN: Registering a new function + form.register_post_process('function2') - # WHEN testing the processing stack - # THEN the processing stack should have two items - assert len(self.form.processes) == 2, 'The two requested processes should have been added to the stack' + # WHEN testing the processing stack + # THEN the processing stack should have two items + assert len(form.processes) == 2, 'The two requested processes should have been added to the stack' - # GIVEN: Registering a process for the second time - self.form.register_post_process('function1') + # GIVEN: Registering a process for the second time + form.register_post_process('function1') - # WHEN testing the processing stack - # THEN the processing stack should still have two items - assert len(self.form.processes) == 2, 'No new processes should have been added to the stack' + # WHEN testing the processing stack + # THEN the processing stack should still have two items + assert len(form.processes) == 2, 'No new processes should have been added to the stack' - def test_register_image_manager_trigger_one(self): - """ - Test the triggering of the image manager rebuild event from image background change - """ - # GIVEN: Three functions registered to be call - Registry().register_function('images_config_updated', self.dummy1) - Registry().register_function('config_screen_changed', self.dummy2) - Registry().register_function('images_regenerate', self.dummy3) - # WHEN: The Images have been changed and the form submitted - self.form.register_post_process('images_config_updated') - self.form.accept() +def test_register_image_manager_trigger_one(form, dummy): + """ + Test the triggering of the image manager rebuild event from image background change + """ + # GIVEN: Three functions registered to be call + Registry().register_function('images_config_updated', dummy[0]) + Registry().register_function('config_screen_changed', dummy[1]) + Registry().register_function('images_regenerate', dummy[2]) - # THEN: images_regenerate should have been added. - assert self.dummy1.call_count == 1, 'dummy1 should have been called once' - assert self.dummy2.call_count == 0, 'dummy2 should not have been called at all' - assert self.dummy3.call_count == 1, 'dummy3 should have been called once' + # WHEN: The Images have been changed and the form submitted + form.register_post_process('images_config_updated') + form.accept() - def test_register_image_manager_trigger_two(self): - """ - Test the triggering of the image manager rebuild event from screen dimension change - """ - # GIVEN: Three functions registered to be call - Registry().register_function('images_config_updated', self.dummy1) - Registry().register_function('config_screen_changed', self.dummy2) - Registry().register_function('images_regenerate', self.dummy3) + # THEN: images_regenerate should have been added. + assert dummy[0].call_count == 1, 'dummy1 should have been called once' + assert dummy[1].call_count == 0, 'dummy2 should not have been called at all' + assert dummy[2].call_count == 1, 'dummy3 should have been called once' - # WHEN: The Images have been changed and the form submitted - self.form.register_post_process('config_screen_changed') - self.form.accept() - # THEN: images_regenerate should have been added. - assert self.dummy1.call_count == 0, 'dummy1 should not have been called at all' - assert self.dummy2.call_count == 1, 'dummy2 should have been called once' - assert self.dummy3.call_count == 1, 'dummy3 should have been called once' +def test_register_image_manager_trigger_two(form, dummy): + """ + Test the triggering of the image manager rebuild event from screen dimension change + """ + # GIVEN: Three functions registered to be call + Registry().register_function('images_config_updated', dummy[0]) + Registry().register_function('config_screen_changed', dummy[1]) + Registry().register_function('images_regenerate', dummy[2]) - def test_register_image_manager_trigger_three(self): - """ - Test the triggering of the image manager rebuild event from image background change and a change to the - screen dimension. - """ - # GIVEN: Three functions registered to be call - Registry().register_function('images_config_updated', self.dummy1) - Registry().register_function('config_screen_changed', self.dummy2) - Registry().register_function('images_regenerate', self.dummy3) + # WHEN: The Images have been changed and the form submitted + form.register_post_process('config_screen_changed') + form.accept() - # WHEN: The Images have been changed and the form submitted - self.form.register_post_process('config_screen_changed') - self.form.register_post_process('images_config_updated') - self.form.accept() + # THEN: images_regenerate should have been added. + assert dummy[0].call_count == 0, 'dummy1 should not have been called at all' + assert dummy[1].call_count == 1, 'dummy2 should have been called once' + assert dummy[2].call_count == 1, 'dummy3 should have been called once' - # THEN: Images_regenerate should have been added. - assert self.dummy1.call_count == 1, 'dummy1 should have been called once' - assert self.dummy2.call_count == 1, 'dummy2 should have been called once' - assert self.dummy3.call_count == 1, 'dummy3 should have been called once' + +def test_register_image_manager_trigger_three(form, dummy): + """ + Test the triggering of the image manager rebuild event from image background change and a change to the + screen dimension. + """ + # GIVEN: Three functions registered to be call + Registry().register_function('images_config_updated', dummy[0]) + Registry().register_function('config_screen_changed', dummy[1]) + Registry().register_function('images_regenerate', dummy[2]) + + # WHEN: The Images have been changed and the form submitted + form.register_post_process('config_screen_changed') + form.register_post_process('images_config_updated') + form.accept() + + # THEN: Images_regenerate should have been added. + assert dummy[0].call_count == 1, 'dummy1 should have been called once' + assert dummy[1].call_count == 1, 'dummy2 should have been called once' + assert dummy[2].call_count == 1, 'dummy3 should have been called once' diff --git a/tests/interfaces/openlp_core/ui/test_shortcutlistform.py b/tests/interfaces/openlp_core/ui/test_shortcutlistform.py index 47bec5ab9..13214c999 100644 --- a/tests/interfaces/openlp_core/ui/test_shortcutlistform.py +++ b/tests/interfaces/openlp_core/ui/test_shortcutlistform.py @@ -21,207 +21,201 @@ """ Package to test the openlp.core.ui.shortcutform package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, patch from PyQt5 import QtCore, QtWidgets -from openlp.core.common.registry import Registry from openlp.core.ui.shortcutlistform import ShortcutListForm -from tests.helpers.testmixin import TestMixin -class TestShortcutform(TestCase, TestMixin): +@pytest.fixture() +def form(mock_settings): + frm = ShortcutListForm() + return frm - def setUp(self): - """ - Create the UI - """ - Registry.create() - self.setup_application() - self.main_window = QtWidgets.QMainWindow() - Registry().register('main_window', self.main_window) - self.form = ShortcutListForm() - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.form - del self.main_window +def test_adjust_button(form): + """ + Test the _adjust_button() method + """ + # GIVEN: A button. + button = QtWidgets.QPushButton() + checked = True + enabled = True + text = 'new!' - def test_adjust_button(self): - """ - Test the _adjust_button() method - """ - # GIVEN: A button. - button = QtWidgets.QPushButton() - checked = True - enabled = True - text = 'new!' + # WHEN: Call the method. + with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method: + form._adjust_button(button, checked, enabled, text) - # WHEN: Call the method. - with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method: - self.form._adjust_button(button, checked, enabled, text) + # THEN: The button should be changed. + assert button.text() == text, 'The text should match.' + mocked_check_method.assert_called_once_with(True) + assert button.isEnabled() == enabled, 'The button should be disabled.' - # THEN: The button should be changed. - assert button.text() == text, 'The text should match.' - mocked_check_method.assert_called_once_with(True) - assert button.isEnabled() == enabled, 'The button should be disabled.' - def test_space_key_press_event(self): - """ - Test the keyPressEvent when the spacebar was pressed - """ - # GIVEN: A key event that is a space +def test_space_key_press_event(form): + """ + Test the keyPressEvent when the spacebar was pressed + """ + # GIVEN: A key event that is a space + mocked_event = MagicMock() + mocked_event.key.return_value = QtCore.Qt.Key_Space + + # WHEN: The event is handled + with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event: + form.keyPressEvent(mocked_event) + + # THEN: The key should be released + mocked_key_release_event.assert_called_with(mocked_event) + assert 0 == mocked_event.accept.call_count + + +def test_primary_push_button_checked_key_press_event(form): + """ + Test the keyPressEvent when the primary push button is checked + """ + # GIVEN: The primary push button is checked + with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event, \ + patch.object(form.primary_push_button, 'isChecked') as mocked_is_checked: + mocked_is_checked.return_value = True mocked_event = MagicMock() - mocked_event.key.return_value = QtCore.Qt.Key_Space # WHEN: The event is handled - with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event: - self.form.keyPressEvent(mocked_event) + form.keyPressEvent(mocked_event) - # THEN: The key should be released - mocked_key_release_event.assert_called_with(mocked_event) - assert 0 == mocked_event.accept.call_count + # THEN: The key should be released + mocked_key_release_event.assert_called_with(mocked_event) + assert 0 == mocked_event.accept.call_count - def test_primary_push_button_checked_key_press_event(self): - """ - Test the keyPressEvent when the primary push button is checked - """ - # GIVEN: The primary push button is checked - with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event, \ - patch.object(self.form.primary_push_button, 'isChecked') as mocked_is_checked: - mocked_is_checked.return_value = True - mocked_event = MagicMock() - # WHEN: The event is handled - self.form.keyPressEvent(mocked_event) - - # THEN: The key should be released - mocked_key_release_event.assert_called_with(mocked_event) - assert 0 == mocked_event.accept.call_count - - def test_alternate_push_button_checked_key_press_event(self): - """ - Test the keyPressEvent when the alternate push button is checked - """ - # GIVEN: The primary push button is checked - with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event, \ - patch.object(self.form.alternate_push_button, 'isChecked') as mocked_is_checked: - mocked_is_checked.return_value = True - mocked_event = MagicMock() - - # WHEN: The event is handled - self.form.keyPressEvent(mocked_event) - - # THEN: The key should be released - mocked_key_release_event.assert_called_with(mocked_event) - assert 0 == mocked_event.accept.call_count - - def test_escape_key_press_event(self): - """ - Test the keyPressEvent when the escape key was pressed - """ - # GIVEN: A key event that is an escape +def test_alternate_push_button_checked_key_press_event(form): + """ + Test the keyPressEvent when the alternate push button is checked + """ + # GIVEN: The primary push button is checked + with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event, \ + patch.object(form.alternate_push_button, 'isChecked') as mocked_is_checked: + mocked_is_checked.return_value = True mocked_event = MagicMock() - mocked_event.key.return_value = QtCore.Qt.Key_Escape # WHEN: The event is handled - with patch.object(self.form, 'close') as mocked_close: - self.form.keyPressEvent(mocked_event) + form.keyPressEvent(mocked_event) - # THEN: The key should be released - mocked_event.accept.assert_called_with() - mocked_close.assert_called_with() + # THEN: The key should be released + mocked_key_release_event.assert_called_with(mocked_event) + assert 0 == mocked_event.accept.call_count - def test_on_default_radio_button_not_toggled(self): - """ - Test that the default radio button method exits early when the button is not toggled - """ - # GIVEN: A not-toggled custom radio button - with patch.object(self.form, '_current_item_action') as mocked_current_item_action: - # WHEN: The clicked method is called - self.form.on_default_radio_button_clicked(False) +def test_escape_key_press_event(form): + """ + Test the keyPressEvent when the escape key was pressed + """ + # GIVEN: A key event that is an escape + mocked_event = MagicMock() + mocked_event.key.return_value = QtCore.Qt.Key_Escape - # THEN: The method should exit early (i.e. the rest of the methods are not called) - assert 0 == mocked_current_item_action.call_count + # WHEN: The event is handled + with patch.object(form, 'close') as mocked_close: + form.keyPressEvent(mocked_event) - def test_on_default_radio_button_clicked_no_action(self): - """ - Test that nothing happens when an action hasn't been selected and you click the default radio button - """ - # GIVEN: Some mocked out methods, a current action, and some shortcuts - with patch.object(self.form, '_current_item_action') as mocked_current_item_action, \ - patch.object(self.form, '_action_shortcuts') as mocked_action_shortcuts: - mocked_current_item_action.return_value = None + # THEN: The key should be released + mocked_event.accept.assert_called_with() + mocked_close.assert_called_with() - # WHEN: The default radio button is clicked - self.form.on_default_radio_button_clicked(True) - # THEN: The method should exit early (i.e. the rest of the methods are not called) - mocked_current_item_action.assert_called_with() - assert 0 == mocked_action_shortcuts.call_count +def test_on_default_radio_button_not_toggled(form): + """ + Test that the default radio button method exits early when the button is not toggled + """ + # GIVEN: A not-toggled custom radio button + with patch.object(form, '_current_item_action') as mocked_current_item_action: - def test_on_default_radio_button_clicked(self): - """ - Test that the values are copied across correctly when the default radio button is selected - """ - # GIVEN: Some mocked out methods, a current action, and some shortcuts - with patch.object(self.form, '_current_item_action') as mocked_current_item_action, \ - patch.object(self.form, '_action_shortcuts') as mocked_action_shortcuts, \ - patch.object(self.form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ - patch.object(self.form, 'get_shortcut_string') as mocked_get_shortcut_string, \ - patch.object(self.form.primary_push_button, 'setText') as mocked_set_text: - mocked_action = MagicMock() - mocked_action.default_shortcuts = [QtCore.Qt.Key_Escape] - mocked_current_item_action.return_value = mocked_action - mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape] - mocked_get_shortcut_string.return_value = 'Esc' + # WHEN: The clicked method is called + form.on_default_radio_button_clicked(False) - # WHEN: The default radio button is clicked - self.form.on_default_radio_button_clicked(True) + # THEN: The method should exit early (i.e. the rest of the methods are not called) + assert 0 == mocked_current_item_action.call_count - # THEN: The shorcuts should be copied across - mocked_current_item_action.assert_called_with() - mocked_action_shortcuts.assert_called_with(mocked_action) - mocked_refresh_shortcut_list.assert_called_with() - mocked_set_text.assert_called_with('Esc') - def test_on_custom_radio_button_not_toggled(self): - """ - Test that the custom radio button method exits early when the button is not toggled - """ - # GIVEN: A not-toggled custom radio button - with patch.object(self.form, '_current_item_action') as mocked_current_item_action: +def test_on_default_radio_button_clicked_no_action(form): + """ + Test that nothing happens when an action hasn't been selected and you click the default radio button + """ + # GIVEN: Some mocked out methods, a current action, and some shortcuts + with patch.object(form, '_current_item_action') as mocked_current_item_action, \ + patch.object(form, '_action_shortcuts') as mocked_action_shortcuts: + mocked_current_item_action.return_value = None - # WHEN: The clicked method is called - self.form.on_custom_radio_button_clicked(False) + # WHEN: The default radio button is clicked + form.on_default_radio_button_clicked(True) - # THEN: The method should exit early (i.e. the rest of the methods are not called) - assert 0 == mocked_current_item_action.call_count + # THEN: The method should exit early (i.e. the rest of the methods are not called) + mocked_current_item_action.assert_called_with() + assert 0 == mocked_action_shortcuts.call_count - def test_on_custom_radio_button_clicked(self): - """ - Test that the values are copied across correctly when the custom radio button is selected - """ - # GIVEN: Some mocked out methods, a current action, and some shortcuts - with patch.object(self.form, '_current_item_action') as mocked_current_item_action, \ - patch.object(self.form, '_action_shortcuts') as mocked_action_shortcuts, \ - patch.object(self.form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ - patch.object(self.form, 'get_shortcut_string') as mocked_get_shortcut_string, \ - patch.object(self.form.primary_push_button, 'setText') as mocked_set_text: - mocked_action = MagicMock() - mocked_current_item_action.return_value = mocked_action - mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape] - mocked_get_shortcut_string.return_value = 'Esc' - # WHEN: The custom radio button is clicked - self.form.on_custom_radio_button_clicked(True) +def test_on_default_radio_button_clicked(form): + """ + Test that the values are copied across correctly when the default radio button is selected + """ + # GIVEN: Some mocked out methods, a current action, and some shortcuts + with patch.object(form, '_current_item_action') as mocked_current_item_action, \ + patch.object(form, '_action_shortcuts') as mocked_action_shortcuts, \ + patch.object(form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ + patch.object(form, 'get_shortcut_string') as mocked_get_shortcut_string, \ + patch.object(form.primary_push_button, 'setText') as mocked_set_text: + mocked_action = MagicMock() + mocked_action.default_shortcuts = [QtCore.Qt.Key_Escape] + mocked_current_item_action.return_value = mocked_action + mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape] + mocked_get_shortcut_string.return_value = 'Esc' - # THEN: The shorcuts should be copied across - mocked_current_item_action.assert_called_with() - mocked_action_shortcuts.assert_called_with(mocked_action) - mocked_refresh_shortcut_list.assert_called_with() - mocked_set_text.assert_called_with('Esc') + # WHEN: The default radio button is clicked + form.on_default_radio_button_clicked(True) + + # THEN: The shorcuts should be copied across + mocked_current_item_action.assert_called_with() + mocked_action_shortcuts.assert_called_with(mocked_action) + mocked_refresh_shortcut_list.assert_called_with() + mocked_set_text.assert_called_with('Esc') + + +def test_on_custom_radio_button_not_toggled(form): + """ + Test that the custom radio button method exits early when the button is not toggled + """ + # GIVEN: A not-toggled custom radio button + with patch.object(form, '_current_item_action') as mocked_current_item_action: + + # WHEN: The clicked method is called + form.on_custom_radio_button_clicked(False) + + # THEN: The method should exit early (i.e. the rest of the methods are not called) + assert 0 == mocked_current_item_action.call_count + + +def test_on_custom_radio_button_clicked(form): + """ + Test that the values are copied across correctly when the custom radio button is selected + """ + # GIVEN: Some mocked out methods, a current action, and some shortcuts + with patch.object(form, '_current_item_action') as mocked_current_item_action, \ + patch.object(form, '_action_shortcuts') as mocked_action_shortcuts, \ + patch.object(form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ + patch.object(form, 'get_shortcut_string') as mocked_get_shortcut_string, \ + patch.object(form.primary_push_button, 'setText') as mocked_set_text: + mocked_action = MagicMock() + mocked_current_item_action.return_value = mocked_action + mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape] + mocked_get_shortcut_string.return_value = 'Esc' + + # WHEN: The custom radio button is clicked + form.on_custom_radio_button_clicked(True) + + # THEN: The shorcuts should be copied across + mocked_current_item_action.assert_called_with() + mocked_action_shortcuts.assert_called_with(mocked_action) + mocked_refresh_shortcut_list.assert_called_with() + mocked_set_text.assert_called_with('Esc') diff --git a/tests/interfaces/openlp_core/ui/test_starttimedialog.py b/tests/interfaces/openlp_core/ui/test_starttimedialog.py index 8cd05463e..0653ac8c5 100644 --- a/tests/interfaces/openlp_core/ui/test_starttimedialog.py +++ b/tests/interfaces/openlp_core/ui/test_starttimedialog.py @@ -21,92 +21,78 @@ """ Package to test the openlp.core.ui package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, patch -from PyQt5 import QtCore, QtTest, QtWidgets +from PyQt5 import QtCore, QtTest -from openlp.core.common.registry import Registry -from openlp.core.ui import starttimeform -from tests.helpers.testmixin import TestMixin +from openlp.core.ui.starttimeform import StartTimeForm -class TestStartTimeDialog(TestCase, TestMixin): +@pytest.fixture() +def form(mock_settings): + frm = StartTimeForm() + return frm - def setUp(self): - """ - Create the UI - """ - Registry.create() - self.setup_application() - self.main_window = QtWidgets.QMainWindow() - Registry().register('main_window', self.main_window) - self.form = starttimeform.StartTimeForm() - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.form - del self.main_window +def test_ui_defaults(form): + """ + Test StartTimeDialog are defaults correct + """ + assert form.hour_spin_box.minimum() == 0, 'The minimum hour should stay the same as the dialog' + assert form.hour_spin_box.maximum() == 4, 'The maximum hour should stay the same as the dialog' + assert form.minute_spin_box.minimum() == 0, 'The minimum minute should stay the same as the dialog' + assert form.minute_spin_box.maximum() == 59, 'The maximum minute should stay the same as the dialog' + assert form.second_spin_box.minimum() == 0, 'The minimum second should stay the same as the dialog' + assert form.second_spin_box.maximum() == 59, 'The maximum second should stay the same as the dialog' + assert form.hour_finish_spin_box.minimum() == 0, \ + 'The minimum finish hour should stay the same as the dialog' + assert form.hour_finish_spin_box.maximum() == 4, \ + 'The maximum finish hour should stay the same as the dialog' + assert form.minute_finish_spin_box.minimum() == 0, \ + 'The minimum finish minute should stay the same as the dialog' + assert form.minute_finish_spin_box.maximum() == 59, \ + 'The maximum finish minute should stay the same as the dialog' + assert form.second_finish_spin_box.minimum() == 0, \ + 'The minimum finish second should stay the same as the dialog' + assert form.second_finish_spin_box.maximum() == 59, \ + 'The maximum finish second should stay the same as the dialog' - def test_ui_defaults(self): - """ - Test StartTimeDialog are defaults correct - """ - assert self.form.hour_spin_box.minimum() == 0, 'The minimum hour should stay the same as the dialog' - assert self.form.hour_spin_box.maximum() == 4, 'The maximum hour should stay the same as the dialog' - assert self.form.minute_spin_box.minimum() == 0, 'The minimum minute should stay the same as the dialog' - assert self.form.minute_spin_box.maximum() == 59, 'The maximum minute should stay the same as the dialog' - assert self.form.second_spin_box.minimum() == 0, 'The minimum second should stay the same as the dialog' - assert self.form.second_spin_box.maximum() == 59, 'The maximum second should stay the same as the dialog' - assert self.form.hour_finish_spin_box.minimum() == 0, \ - 'The minimum finish hour should stay the same as the dialog' - assert self.form.hour_finish_spin_box.maximum() == 4, \ - 'The maximum finish hour should stay the same as the dialog' - assert self.form.minute_finish_spin_box.minimum() == 0, \ - 'The minimum finish minute should stay the same as the dialog' - assert self.form.minute_finish_spin_box.maximum() == 59, \ - 'The maximum finish minute should stay the same as the dialog' - assert self.form.second_finish_spin_box.minimum() == 0, \ - 'The minimum finish second should stay the same as the dialog' - assert self.form.second_finish_spin_box.maximum() == 59, \ - 'The maximum finish second should stay the same as the dialog' - def test_time_display(self): - """ - Test StartTimeDialog display functionality - """ - # GIVEN: A service item with with time - mocked_serviceitem = MagicMock() - mocked_serviceitem.start_time = 61 - mocked_serviceitem.end_time = 3701 - mocked_serviceitem.media_length = 3701 +def test_time_display(form): + """ + Test StartTimeDialog display functionality + """ + # GIVEN: A service item with with time + mocked_serviceitem = MagicMock() + mocked_serviceitem.start_time = 61 + mocked_serviceitem.end_time = 3701 + mocked_serviceitem.media_length = 3701 - # WHEN displaying the UI and pressing enter - self.form.item = {'service_item': mocked_serviceitem} - with patch('PyQt5.QtWidgets.QDialog.exec'): - self.form.exec() - ok_widget = self.form.button_box.button(self.form.button_box.Ok) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) + # WHEN displaying the UI and pressing enter + form.item = {'service_item': mocked_serviceitem} + with patch('PyQt5.QtWidgets.QDialog.exec'): + form.exec() + ok_widget = form.button_box.button(form.button_box.Ok) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # THEN the following input values are returned - assert self.form.hour_spin_box.value() == 0 - assert self.form.minute_spin_box.value() == 1 - assert self.form.second_spin_box.value() == 1 - assert self.form.item['service_item'].start_time == 61, 'The start time should stay the same' + # THEN the following input values are returned + assert form.hour_spin_box.value() == 0 + assert form.minute_spin_box.value() == 1 + assert form.second_spin_box.value() == 1 + assert form.item['service_item'].start_time == 61, 'The start time should stay the same' - # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter - self.form.item = {'service_item': mocked_serviceitem} - with patch('PyQt5.QtWidgets.QDialog.exec'): - self.form.exec() - self.form.minute_spin_box.setValue(2) - self.form.second_spin_box.setValue(3) - ok_widget = self.form.button_box.button(self.form.button_box.Ok) - QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) + # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter + form.item = {'service_item': mocked_serviceitem} + with patch('PyQt5.QtWidgets.QDialog.exec'): + form.exec() + form.minute_spin_box.setValue(2) + form.second_spin_box.setValue(3) + ok_widget = form.button_box.button(form.button_box.Ok) + QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) - # THEN the following values are returned - assert self.form.hour_spin_box.value() == 0 - assert self.form.minute_spin_box.value() == 2 - assert self.form.second_spin_box.value() == 3 - assert self.form.item['service_item'].start_time == 123, 'The start time should have changed' + # THEN the following values are returned + assert form.hour_spin_box.value() == 0 + assert form.minute_spin_box.value() == 2 + assert form.second_spin_box.value() == 3 + assert form.item['service_item'].start_time == 123, 'The start time should have changed' diff --git a/tests/interfaces/openlp_core/ui/test_thememanager.py b/tests/interfaces/openlp_core/ui/test_thememanager.py index d18c48d5e..beeaa7d35 100644 --- a/tests/interfaces/openlp_core/ui/test_thememanager.py +++ b/tests/interfaces/openlp_core/ui/test_thememanager.py @@ -21,116 +21,103 @@ """ Interface tests to test the themeManager class and related methods. """ +import pytest from pathlib import Path -from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.ui.thememanager import ThemeManager -from tests.helpers.testmixin import TestMixin -class TestThemeManager(TestCase, TestMixin): +@pytest.fixture() +def theme_manager(settings): + thm = ThemeManager() + return thm + + +def test_theme_manager_initialise(theme_manager): """ - Test the functions in the ThemeManager module + Test the thememanager initialise - basic test """ - def setUp(self): - """ - Create the UI - """ - self.setup_application() - self.build_settings() - Registry.create() - Registry().register('settings', Settings()) - self.theme_manager = ThemeManager() + # GIVEN: A new a call to initialise + theme_manager.setup_ui = MagicMock() + theme_manager.build_theme_path = MagicMock() + Settings().setValue('themes/global theme', 'my_theme') - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - self.destroy_settings() - del self.theme_manager + # WHEN: the initialisation is run + theme_manager.bootstrap_initialise() - def test_initialise(self): - """ - Test the thememanager initialise - basic test - """ - # GIVEN: A new a call to initialise - self.theme_manager.setup_ui = MagicMock() - self.theme_manager.build_theme_path = MagicMock() - Settings().setValue('themes/global theme', 'my_theme') + # THEN: + theme_manager.setup_ui.assert_called_once_with(theme_manager) + assert theme_manager.global_theme == 'my_theme' + theme_manager.build_theme_path.assert_called_once_with() - # WHEN: the initialisation is run - self.theme_manager.bootstrap_initialise() - # THEN: - self.theme_manager.setup_ui.assert_called_once_with(self.theme_manager) - assert self.theme_manager.global_theme == 'my_theme' - self.theme_manager.build_theme_path.assert_called_once_with() +@patch('openlp.core.ui.thememanager.create_paths') +@patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path') +def test_build_theme_path(mocked_get_section_data_path, mocked_create_paths, theme_manager): + """ + Test the thememanager build_theme_path + """ + # GIVEN: A mocked out AppLocation.get_directory() and mocked create_paths + mocked_get_section_data_path.return_value = Path('tests/my_theme') - @patch('openlp.core.ui.thememanager.create_paths') - @patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path') - def test_build_theme_path(self, mocked_get_section_data_path, mocked_create_paths): - """ - Test the thememanager build_theme_path - """ - # GIVEN: A mocked out AppLocation.get_directory() and mocked create_paths - mocked_get_section_data_path.return_value = Path('tests/my_theme') + # WHEN: the build_theme_path is run + theme_manager.build_theme_path() - # WHEN: the build_theme_path is run - self.theme_manager.build_theme_path() + # THEN: The theme path and the thumb path should be correct + assert theme_manager.theme_path == Path('tests/my_theme') + assert theme_manager.thumb_path == Path('tests/my_theme/thumbnails') + mocked_create_paths.assert_called_once_with(Path('tests/my_theme'), Path('tests/my_theme/thumbnails')) - # THEN: The theme path and the thumb path should be correct - assert self.theme_manager.theme_path == Path('tests/my_theme') - assert self.theme_manager.thumb_path == Path('tests/my_theme/thumbnails') - mocked_create_paths.assert_called_once_with(Path('tests/my_theme'), Path('tests/my_theme/thumbnails')) - def test_click_on_new_theme(self): - """ - Test the on_add_theme event handler is called by the UI - """ - # GIVEN: An initial form - Settings().setValue('themes/global theme', 'my_theme') - mocked_event = MagicMock() - self.theme_manager.on_add_theme = mocked_event - self.theme_manager.setup_ui(self.theme_manager) +def test_click_on_new_theme(theme_manager): + """ + Test the on_add_theme event handler is called by the UI + """ + # GIVEN: An initial form + Settings().setValue('themes/global theme', 'my_theme') + mocked_event = MagicMock() + theme_manager.on_add_theme = mocked_event + theme_manager.setup_ui(theme_manager) - # WHEN displaying the UI and pressing cancel - new_theme = self.theme_manager.toolbar.actions['newTheme'] - new_theme.trigger() + # WHEN displaying the UI and pressing cancel + new_theme = theme_manager.toolbar.actions['newTheme'] + new_theme.trigger() - assert mocked_event.call_count == 1, 'The on_add_theme method should have been called once' + assert mocked_event.call_count == 1, 'The on_add_theme method should have been called once' - @patch('openlp.core.ui.themeform.ThemeForm._setup') - @patch('openlp.core.ui.filerenameform.FileRenameForm._setup') - def test_bootstrap_post(self, mocked_rename_form, mocked_theme_form): - """ - Test the functions of bootstrap_post_setup are called. - """ - # GIVEN: - self.theme_manager.theme_path = MagicMock() - # WHEN: - with patch('openlp.core.ui.thememanager.ThemeProgressForm'): - self.theme_manager.bootstrap_post_set_up() +@patch('openlp.core.ui.themeform.ThemeForm._setup') +@patch('openlp.core.ui.filerenameform.FileRenameForm._setup') +def test_bootstrap_post(mocked_rename_form, mocked_theme_form, theme_manager): + """ + Test the functions of bootstrap_post_setup are called. + """ + # GIVEN: + theme_manager.theme_path = MagicMock() - # THEN: - assert self.theme_manager.progress_form is not None - assert self.theme_manager.theme_form is not None - assert self.theme_manager.file_rename_form is not None + # WHEN: + with patch('openlp.core.ui.thememanager.ThemeProgressForm'): + theme_manager.bootstrap_post_set_up() - def test_bootstrap_completion(self): - """ - Test the functions of bootstrap_post_setup are called. - """ - # GIVEN: - self.theme_manager.load_themes = MagicMock() - self.theme_manager.upgrade_themes = MagicMock() + # THEN: + assert theme_manager.progress_form is not None + assert theme_manager.theme_form is not None + assert theme_manager.file_rename_form is not None - # WHEN: - self.theme_manager.bootstrap_completion() - # THEN: - self.theme_manager.upgrade_themes.assert_called_once() - self.theme_manager.load_themes.assert_called_once() +def test_bootstrap_completion(theme_manager): + """ + Test the functions of bootstrap_post_setup are called. + """ + # GIVEN: + theme_manager.load_themes = MagicMock() + theme_manager.upgrade_themes = MagicMock() + + # WHEN: + theme_manager.bootstrap_completion() + + # THEN: + theme_manager.upgrade_themes.assert_called_once() + theme_manager.load_themes.assert_called_once() diff --git a/tests/interfaces/openlp_core/widgets/test_edits.py b/tests/interfaces/openlp_core/widgets/test_edits.py index 47d2b7112..f8c9943ff 100644 --- a/tests/interfaces/openlp_core/widgets/test_edits.py +++ b/tests/interfaces/openlp_core/widgets/test_edits.py @@ -21,14 +21,13 @@ """ Module to test the EditCustomForm. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, call from PyQt5 import QtCore, QtGui, QtTest, QtWidgets from openlp.core.common.registry import Registry from openlp.core.widgets.edits import HistoryComboBox, SearchEdit -from tests.helpers.testmixin import TestMixin class SearchTypes(object): @@ -44,120 +43,101 @@ SEARCH_TYPES = [(SearchTypes.First, QtGui.QIcon(), "First", "First Placeholder T (SearchTypes.Second, QtGui.QIcon(), "Second", SECOND_PLACEHOLDER_TEXT)] -class TestSearchEdit(TestCase, TestMixin): +@pytest.fixture() +def search_edit(mock_settings): + main_window = QtWidgets.QMainWindow() + Registry().register('main_window', main_window) + Registry().remove('settings') + Registry().register('settings', MagicMock(**{'value.return_value': SearchTypes.First})) + + s_edit = SearchEdit(main_window, 'settings_section') + # To complete set up we have to set the search types. + s_edit.set_search_types(SEARCH_TYPES) + return s_edit + + +@pytest.fixture() +def combo(mock_settings): + main_window = QtWidgets.QMainWindow() + Registry().register('main_window', main_window) + s_combo = HistoryComboBox(main_window) + return s_combo + + +def test_set_search_types(search_edit): """ - Test the EditCustomForm. + Test setting the search types of the search edit. """ - def setUp(self): - """ - Create the UI - """ - Registry.create() - self.setup_application() - self.main_window = QtWidgets.QMainWindow() - Registry().register('main_window', self.main_window) - Registry().register('settings', MagicMock(**{'value.return_value': SearchTypes.First})) + # GIVEN: The search edit with the search types set. NOTE: The set_search_types(types) is called in the setUp() + # method! - self.search_edit = SearchEdit(self.main_window, 'settings_section') - # To complete set up we have to set the search types. - self.search_edit.set_search_types(SEARCH_TYPES) + # WHEN: - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.search_edit - del self.main_window - - def test_set_search_types(self): - """ - Test setting the search types of the search edit. - """ - # GIVEN: The search edit with the search types set. NOTE: The set_search_types(types) is called in the setUp() - # method! - - # WHEN: - - # THEN: The first search type should be the first one in the list. The selected type should be saved in the - # settings - assert self.search_edit.current_search_type() == SearchTypes.First, \ - "The first search type should be selected." - Registry().get('settings').setValue.assert_called_once_with('settings_section/last used search type', 0) - - def test_set_current_search_type(self): - """ - Test if changing the search type works. - """ - # GIVEN: - # WHEN: Change the search type - result = self.search_edit.set_current_search_type(SearchTypes.Second) - - # THEN: - assert result is True, "The call should return success (True)." - assert self.search_edit.current_search_type() == SearchTypes.Second, \ - "The search type should be SearchTypes.Second" - assert self.search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \ - "The correct placeholder text should be 'Second Placeholder Text'." - Registry().get('settings').setValue.assert_has_calls( - [call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)]) - - def test_clear_button_visibility(self): - """ - Test if the clear button is hidden/shown correctly. - """ - # GIVEN: Everything is left to its defaults (hidden). - assert self.search_edit.clear_button.isHidden(), "Pre condition not met. Button should be hidden." - - # WHEN: Type something in the search edit. - QtTest.QTest.keyPress(self.search_edit, QtCore.Qt.Key_A) - QtTest.QTest.keyRelease(self.search_edit, QtCore.Qt.Key_A) - - # THEN: The clear button should not be hidden any more. - assert not self.search_edit.clear_button.isHidden(), "The clear button should be visible." - - def test_press_clear_button(self): - """ - Check if the search edit behaves correctly when pressing the clear button. - """ - # GIVEN: A search edit with text. - QtTest.QTest.keyPress(self.search_edit, QtCore.Qt.Key_A) - QtTest.QTest.keyRelease(self.search_edit, QtCore.Qt.Key_A) - - # WHEN: Press the clear button. - QtTest.QTest.mouseClick(self.search_edit.clear_button, QtCore.Qt.LeftButton) - - # THEN: The search edit text should be cleared and the button be hidden. - assert not self.search_edit.text(), "The search edit should not have any text." - assert self.search_edit.clear_button.isHidden(), "The clear button should be hidden." + # THEN: The first search type should be the first one in the list. The selected type should be saved in the + # settings + assert search_edit.current_search_type() == SearchTypes.First, \ + "The first search type should be selected." + Registry().get('settings').setValue.assert_called_once_with('settings_section/last used search type', 0) -class TestHistoryComboBox(TestCase, TestMixin): - def setUp(self): - """ - Some pre-test setup required. - """ - Registry.create() - self.setup_application() - self.main_window = QtWidgets.QMainWindow() - Registry().register('main_window', self.main_window) - self.combo = HistoryComboBox(self.main_window) +def test_set_current_search_type(search_edit): + """ + Test if changing the search type works. + """ + # GIVEN: + # WHEN: Change the search type + result = search_edit.set_current_search_type(SearchTypes.Second) - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault - """ - del self.combo - del self.main_window + # THEN: + assert result is True, "The call should return success (True)." + assert search_edit.current_search_type() == SearchTypes.Second, \ + "The search type should be SearchTypes.Second" + assert search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \ + "The correct placeholder text should be 'Second Placeholder Text'." + Registry().get('settings').setValue.assert_has_calls( + [call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)]) - def test_get_items(self): - """ - Test the getItems() method - """ - # GIVEN: The combo. - # WHEN: Add two items. - self.combo.addItem('test1') - self.combo.addItem('test2') +def test_clear_button_visibility(search_edit): + """ + Test if the clear button is hidden/shown correctly. + """ + # GIVEN: Everything is left to its defaults (hidden). + assert search_edit.clear_button.isHidden(), "Pre condition not met. Button should be hidden." - # THEN: The list of items should contain both strings. - assert self.combo.getItems() == ['test1', 'test2'] + # WHEN: Type something in the search edit. + QtTest.QTest.keyPress(search_edit, QtCore.Qt.Key_A) + QtTest.QTest.keyRelease(search_edit, QtCore.Qt.Key_A) + + # THEN: The clear button should not be hidden any more. + assert not search_edit.clear_button.isHidden(), "The clear button should be visible." + + +def test_press_clear_button(search_edit): + """ + Check if the search edit behaves correctly when pressing the clear button. + """ + # GIVEN: A search edit with text. + QtTest.QTest.keyPress(search_edit, QtCore.Qt.Key_A) + QtTest.QTest.keyRelease(search_edit, QtCore.Qt.Key_A) + + # WHEN: Press the clear button. + QtTest.QTest.mouseClick(search_edit.clear_button, QtCore.Qt.LeftButton) + + # THEN: The search edit text should be cleared and the button be hidden. + assert not search_edit.text(), "The search edit should not have any text." + assert search_edit.clear_button.isHidden(), "The clear button should be hidden." + + +def test_history_combo_get_items(combo): + """ + Test the getItems() method + """ + # GIVEN: The combo. + + # WHEN: Add two items. + combo.addItem('test1') + combo.addItem('test2') + + # THEN: The list of items should contain both strings. + assert combo.getItems() == ['test1', 'test2'] diff --git a/tests/interfaces/openlp_core/widgets/test_views.py b/tests/interfaces/openlp_core/widgets/test_views.py index b1a8980b8..0e72b7e8f 100644 --- a/tests/interfaces/openlp_core/widgets/test_views.py +++ b/tests/interfaces/openlp_core/widgets/test_views.py @@ -21,91 +21,72 @@ """ Package to test the openlp.core.widgets.views. """ -from unittest import TestCase -from unittest.mock import MagicMock, patch +import pytest +from unittest.mock import patch -from PyQt5 import QtGui, QtWidgets +from PyQt5 import QtWidgets from openlp.core.common.registry import Registry -from openlp.core.common.settings import Settings from openlp.core.lib.serviceitem import ServiceItem -from openlp.core.state import State from openlp.core.widgets.views import ListPreviewWidget -from tests.helpers.testmixin import TestMixin from tests.utils.osdinteraction import read_service_from_file -class TestListPreviewWidget(TestCase, TestMixin): +@pytest.fixture() +def preview_widget(settings): + main_window = QtWidgets.QMainWindow() + Registry().register('main_window', main_window) + p_widget = ListPreviewWidget(main_window, 2) + return p_widget - def setUp(self): - """ - Create the UI. - """ - Registry.create() - self.setup_application() - State().load_settings() - State().add_service("media", 0) - State().update_pre_conditions("media", True) - State().flush_preconditions() - self.main_window = QtWidgets.QMainWindow() - self.image = QtGui.QImage(1, 1, QtGui.QImage.Format_RGB32) - self.image_manager = MagicMock() - self.image_manager.get_image.return_value = self.image - Registry().register('image_manager', self.image_manager) - self.preview_widget = ListPreviewWidget(self.main_window, 2) - Registry().register('settings', Settings()) - def tearDown(self): - """ - Delete all the C++ objects at the end so that we don't have a segfault. - """ - del self.preview_widget - del self.main_window +def test_initial_slide_count(preview_widget): + """ + Test the initial slide count . + """ + # GIVEN: A new ListPreviewWidget instance. + # WHEN: No SlideItem has been added yet. + # THEN: The count of items should be zero. + assert preview_widget.slide_count() == 0, 'The slide list should be empty.' - def test_initial_slide_count(self): - """ - Test the initial slide count . - """ - # GIVEN: A new ListPreviewWidget instance. - # WHEN: No SlideItem has been added yet. - # THEN: The count of items should be zero. - assert self.preview_widget.slide_count() == 0, 'The slide list should be empty.' - def test_initial_slide_number(self): - """ - Test the initial current slide number. - """ - # GIVEN: A new ListPreviewWidget instance. - # WHEN: No SlideItem has been added yet. - # THEN: The number of the current item should be -1. - assert self.preview_widget.current_slide_number() == -1, 'The slide number should be -1.' +def test_initial_slide_number(preview_widget): + """ + Test the initial current slide number. + """ + # GIVEN: A new ListPreviewWidget instance. + # WHEN: No SlideItem has been added yet. + # THEN: The number of the current item should be -1. + assert preview_widget.current_slide_number() == -1, 'The slide number should be -1.' - def test_replace_service_item(self): - """ - Test item counts and current number with a service item. - """ - # GIVEN: A ServiceItem with two frames. - service_item = ServiceItem(None) - service = read_service_from_file('serviceitem_image_3.osj') - with patch('os.path.exists'): - service_item.set_from_service(service[0]) - # WHEN: Added to the preview widget. - self.preview_widget.replace_service_item(service_item, 1, 1) - # THEN: The slide count and number should fit. - assert self.preview_widget.slide_count() == 2, 'The slide count should be 2.' - assert self.preview_widget.current_slide_number() == 1, 'The current slide number should be 1.' - def test_change_slide(self): - """ - Test the change_slide method. - """ - # GIVEN: A ServiceItem with two frames content. - service_item = ServiceItem(None) - service = read_service_from_file('serviceitem_image_3.osj') - with patch('os.path.exists'): - service_item.set_from_service(service[0]) - # WHEN: Added to the preview widget and switched to the second frame. - self.preview_widget.replace_service_item(service_item, 1, 0) - self.preview_widget.change_slide(1) - # THEN: The current_slide_number should reflect the change. - assert self.preview_widget.current_slide_number() == 1, 'The current slide number should be 1.' +def test_replace_service_item(preview_widget, state_media): + """ + Test item counts and current number with a service item. + """ + # GIVEN: A ServiceItem with two frames. + service_item = ServiceItem(None) + service = read_service_from_file('serviceitem_image_3.osj') + with patch('os.path.exists'): + service_item.set_from_service(service[0]) + # WHEN: Added to the preview widget. + preview_widget.replace_service_item(service_item, 1, 1) + # THEN: The slide count and number should fit. + assert preview_widget.slide_count() == 2, 'The slide count should be 2.' + assert preview_widget.current_slide_number() == 1, 'The current slide number should be 1.' + + +def test_change_slide(preview_widget, state_media): + """ + Test the change_slide method. + """ + # GIVEN: A ServiceItem with two frames content. + service_item = ServiceItem(None) + service = read_service_from_file('serviceitem_image_3.osj') + with patch('os.path.exists'): + service_item.set_from_service(service[0]) + # WHEN: Added to the preview widget and switched to the second frame. + preview_widget.replace_service_item(service_item, 1, 0) + preview_widget.change_slide(1) + # THEN: The current_slide_number should reflect the change. + assert preview_widget.current_slide_number() == 1, 'The current slide number should be 1.'