Merge branch 'tests_plugin_5' into 'master'

Tests plugin 5

See merge request openlp/openlp!157
This commit is contained in:
Tim Bentley 2020-03-11 21:53:41 +00:00
commit 73afe240dc
23 changed files with 782 additions and 1076 deletions

View File

@ -96,3 +96,10 @@ def mock_settings(qapp, registry):
def state(): def state():
yield State().load_settings() yield State().load_settings()
State._instances = {} State._instances = {}
@pytest.fixture()
def state_media(state):
State().add_service("media", 0)
State().update_pre_conditions("media", True)
State().flush_preconditions()

View File

@ -26,7 +26,6 @@ import pytest
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, MagicMock, patch 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 import ThemeLevel, md5_hash
from openlp.core.common.enum import ServiceItemType from openlp.core.common.enum import ServiceItemType
from openlp.core.common.registry import Registry from openlp.core.common.registry import Registry
@ -62,13 +61,6 @@ FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456']
TEST_PATH = RESOURCE_PATH / 'service' 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() @pytest.fixture()
def service_item_env(state): def service_item_env(state):
# Mock the renderer and its format_slide method # 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' 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 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 # WHEN: We add a custom from a saved serviceand set the media state
line = convert_file_service_item(TEST_PATH, 'serviceitem_custom_1.osj') 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) service_item.set_from_service(line)
# THEN: We should get back a valid service item # 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' 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 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.os.path.exists')
@patch('openlp.core.lib.serviceitem.AppLocation.get_section_data_path') @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 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' # 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 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' 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 Test the Service Item - adding a song slide from a saved service
""" """

View File

@ -31,25 +31,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'chordpro'
def test_chordpro(mock_settings): def test_chordpro(mock_settings):
class TestChordProFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('ChordProImport', 'chordpro')
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.setUp() 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() test_file_import.tearDown()

View File

@ -30,23 +30,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'easyslides'
def test_easyslides(mock_settings): def test_easyslides(mock_settings):
class TestEasySlidesFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('EasySlidesImport', 'easyslides')
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.setUp() 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() test_file_import.tearDown()

View File

@ -21,88 +21,68 @@
""" """
This module contains tests for the lib submodule of the Songs plugin. 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 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 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): # GIVEN: A song edit form and some mocked stuff
""" mocked_class = MagicMock()
Set up the components need for all tests. mocked_class.name = 'Author'
""" mocked_combo = MagicMock()
Registry.create() mocked_combo.count.return_value = 0
Registry().register('service_list', MagicMock()) mocked_cache = MagicMock()
Registry().register('main_window', MagicMock()) mocked_object = MagicMock()
self.setup_application() mocked_object.name = 'Charles'
self.build_settings() mocked_object.id = 1
Registry().register('settings', self.setting) mocked_manager = MagicMock()
with patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__', return_value=None): mocked_manager.get_all_objects.return_value = [mocked_object]
self.edit_song_form = EditSongForm(None, MagicMock(), MagicMock()) edit_song_form.manager = mocked_manager
QtCore.QLocale.setDefault(QtCore.QLocale('en_GB'))
def tearDown(self): # WHEN: _load_objects() is called
""" edit_song_form._load_objects(mocked_class, mocked_combo, mocked_cache)
Delete all the C++ objects at the end so that we don't have a segfault
"""
self.destroy_settings()
def test_validate_matching_tags(self): # THEN: All the correct methods should have been called
# Given a set of tags edit_song_form.manager.get_all_objects.assert_called_once_with(mocked_class)
tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{su}', '{/su}'] mocked_combo.clear.assert_called_once_with()
mocked_combo.count.assert_called_once_with()
# WHEN we validate them mocked_combo.addItem.assert_called_once_with('Charles')
valid = self.edit_song_form._validate_tags(tags) mocked_cache.append.assert_called_once_with('Charles')
mocked_combo.setItemData.assert_called_once_with(0, 1)
# THEN they should be valid mocked_set_case_insensitive_completer.assert_called_once_with(mocked_cache, mocked_combo)
assert valid is True, "The tags list should be valid" mocked_combo.setCurrentIndex.assert_called_once_with(-1)
mocked_combo.setCurrentText.assert_called_once_with('')
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('')

View File

@ -21,94 +21,76 @@
""" """
This module contains tests for the editverseform of the Songs plugin. This module contains tests for the editverseform of the Songs plugin.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock 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 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): # GIVEN some input values
""" edit_verse_form.has_single_verse = True
Set up the components need for all tests. edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=0)
""" edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text')
self.setup_application() edit_verse_form.verse_number_box.setValue(3)
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'))
def tearDown(self): # WHEN the method is called
""" edit_verse_form.update_suggested_verse_number()
Delete all the C++ objects at the end so that we don't have a segfault
"""
self.destroy_settings()
def test_update_suggested_verse_number_has_no_effect(self): # THEN the verse number must not be changed
""" assert 3 == edit_verse_form.verse_number_box.value(), 'The verse number should be 3'
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)
# WHEN the method is called
self.edit_verse_form.update_suggested_verse_number()
# THEN the verse number must not be changed def test_update_suggested_verse_number_different_type(edit_verse_form):
assert 3 == self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3' """
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): # WHEN the method is called
""" edit_verse_form.update_suggested_verse_number()
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 # THEN the verse number must be changed to 1
self.edit_verse_form.update_suggested_verse_number() 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): def test_on_divide_split_button_clicked(edit_verse_form):
""" """
Test that divide adds text at the correct position Test that divide adds text at the correct position
""" """
# GIVEN some input values # GIVEN some input values
self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4) edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=4)
self.edit_verse_form.verse_text_edit.setPlainText('Text\n') edit_verse_form.verse_text_edit.setPlainText('Text\n')
# WHEN the method is called # WHEN the method is called
self.edit_verse_form.on_forced_split_button_clicked() edit_verse_form.on_forced_split_button_clicked()
# THEN the verse number must not be changed # THEN the verse number must not be changed
assert '[--}{--]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ assert '[--}{--]\nText\n' == edit_verse_form.verse_text_edit.toPlainText(), \
'The verse number should be [--}{--]\nText\n' '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 def test_on_split_button_clicked(edit_verse_form):
self.edit_verse_form.on_overflow_split_button_clicked() """
# THEN the verse number must not be changed Test that divide adds text at the correct position
assert '[---]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ """
'The verse number should be [---]\nText\n' # 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'

View File

@ -30,25 +30,12 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'lyrix'
def test_Lyrix(mock_settings): def test_Lyrix(mock_settings):
class TestLyrixFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('LyrixImport', 'lyrix')
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.setUp() 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() test_file_import.tearDown()

View File

@ -31,23 +31,10 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'powerpraise'
def test_power_praise(mock_settings): def test_power_praise(mock_settings):
class TestPowerPraiseFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('PowerPraiseImport', 'powerpraise')
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.setUp() 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() test_file_import.tearDown()

View File

@ -21,9 +21,6 @@
""" """
This module contains tests for the PresentationManager song importer. 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.helpers.songfileimport import SongImportTestHelper
from tests.utils.constants import RESOURCE_PATH from tests.utils.constants import RESOURCE_PATH
@ -33,24 +30,11 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'presentationmanager'
def test_presenter_manager(mock_settings): def test_presenter_manager(mock_settings):
class TestPresentationManagerFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('PresentationManagerImport', 'presentationmanager')
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.setUp() 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() test_file_import.tearDown()

View File

@ -31,21 +31,8 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'songpro'
def test_song_pro(mock_settings): def test_song_pro(mock_settings):
class TestSongProFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('SongProImport', 'songpro')
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.setUp() 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() test_file_import.tearDown()

View File

@ -35,29 +35,18 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'songshowplus'
def test_song_show_plus(mock_settings): def test_song_show_plus(mock_settings):
class TestSongShowPlusFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('SongShowPlusImport', 'songshowplus')
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.setUp() 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() test_file_import.tearDown()

View File

@ -32,24 +32,11 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'sundayplus'
def test_sunday_plus(mock_settings): def test_sunday_plus(mock_settings):
class TestSundayPlusFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('SundayPlusImport', 'sundayplus')
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.setUp() 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() test_file_import.tearDown()

View File

@ -31,27 +31,12 @@ TEST_PATH = RESOURCE_PATH / 'songs' / 'videopsalm'
def test_video_psalms(mock_settings): def test_video_psalms(mock_settings):
class TestVideoPsalmFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('VideoPsalmImport', 'videopsalm')
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.setUp() 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() test_file_import.tearDown()

View File

@ -29,26 +29,14 @@ from tests.utils.constants import RESOURCE_PATH
TEST_PATH = RESOURCE_PATH / 'songs' / 'worshipassistant' TEST_PATH = RESOURCE_PATH / 'songs' / 'worshipassistant'
def test_chordpro(mock_settings): def test_worshipassistant(mock_settings):
class TestWorshipAssistantFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('WorshipAssistantImport', 'worshipassistant')
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.setUp() 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() test_file_import.tearDown()

View File

@ -49,20 +49,8 @@ def test_create_importer(registry):
def test_zion_wrox(mock_settings): def test_zion_wrox(mock_settings):
class TestZionWorxFileImport(SongImportTestHelper): test_file_import = SongImportTestHelper('ZionWorxImport', 'zionworx')
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.setUp() 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() test_file_import.tearDown()

View File

@ -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. This class is designed to be a helper class to reduce repetition when testing the import of song files.
""" """
def __init__(self, *args, **kwargs): 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 = __import__('openlp.plugins.songs.lib.importers.%s' %
self.importer_module_name, fromlist=[self.importer_class_name]) self.importer_module_name, fromlist=[self.importer_class_name])
self.importer_class = getattr(self.importer_module, self.importer_class_name) self.importer_class = getattr(self.importer_module, self.importer_class_name)

View File

@ -21,69 +21,54 @@
""" """
Package to test the openlp.core.ui package. Package to test the openlp.core.ui package.
""" """
from unittest import TestCase import pytest
from unittest.mock import patch 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.servicenoteform import ServiceNoteForm
from openlp.core.ui import servicenoteform
from tests.helpers.testmixin import TestMixin
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): def test_basic_display(form):
""" """
Delete all the C++ objects at the end so that we don't have a segfault Test Service Note form functionality
""" """
del self.form # GIVEN: A dialog with an empty text box
del self.main_window form.text_edit.setPlainText('')
def test_basic_display(self): # WHEN displaying the UI and pressing enter
""" with patch('PyQt5.QtWidgets.QDialog.exec'):
Test Service Note form functionality form.exec()
""" ok_widget = form.button_box.button(form.button_box.Save)
# GIVEN: A dialog with an empty text box QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
self.form.text_edit.setPlainText('')
# WHEN displaying the UI and pressing enter # THEN the following input text is returned
with patch('PyQt5.QtWidgets.QDialog.exec'): assert form.text_edit.toPlainText() == '', 'The returned text should be empty'
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 # WHEN displaying the UI, having set the text and pressing enter
assert self.form.text_edit.toPlainText() == '', 'The returned text should be empty' 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 # THEN the following text is returned
text = 'OpenLP is the best worship software' assert form.text_edit.toPlainText() == text, 'The text originally entered should still be there'
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 # WHEN displaying the UI, having set the text and pressing enter
assert self.form.text_edit.toPlainText() == text, 'The text originally entered should still be there' 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 # THEN the following text is returned
self.form.text_edit.setPlainText('') assert form.text_edit.toPlainText() == text, 'The new text should be returned'
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'

View File

@ -21,172 +21,152 @@
""" """
Package to test the openlp.core.lib.settingsform package. Package to test the openlp.core.lib.settingsform package.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtTest from PyQt5 import QtCore, QtTest
from openlp.core.common.registry import Registry from openlp.core.common.registry import Registry
from openlp.core.display.screens import ScreenList from openlp.core.ui.settingsform import SettingsForm
from openlp.core.ui import settingsform
from tests.helpers.testmixin import TestMixin
SCREEN = { @pytest.fixture()
'primary': False, def form(mock_settings):
'number': 1, frm = SettingsForm()
'size': QtCore.QRect(0, 0, 1024, 768) 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): # WHEN displaying the UI and pressing cancel
""" with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject:
Some pre-test setup required. cancel_widget = form.button_box.button(form.button_box.Cancel)
""" QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton)
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()
def tearDown(self): # THEN the dialog reject should have been called
""" assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called'
Delete all the C++ objects at the end so that we don't have a segfault
"""
del self.form
def test_basic_cancel(self):
"""
Test running the settings form and pressing Cancel
"""
# GIVEN: An initial form
# WHEN displaying the UI and pressing cancel def test_basic_accept(form):
with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject: """
cancel_widget = self.form.button_box.button(self.form.button_box.Cancel) Test running the settings form and pressing Ok
QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton) """
# GIVEN: An initial form
# THEN the dialog reject should have been called # WHEN displaying the UI and pressing Ok
assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called' 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): # THEN the dialog reject should have been called
""" assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called'
Test running the settings form and pressing Ok
"""
# GIVEN: An initial form
# 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 def test_basic_register(form):
assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called' """
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): # WHEN displaying the UI and pressing Ok
""" with patch('PyQt5.QtWidgets.QDialog.accept'):
Test running the settings form and adding a single function ok_widget = form.button_box.button(form.button_box.Ok)
""" QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# GIVEN: An initial form add a register function
self.form.register_post_process('function1')
# WHEN displaying the UI and pressing Ok # THEN the processing stack should be empty
with patch('PyQt5.QtWidgets.QDialog.accept'): assert len(form.processes) == 0, 'The one requested process should have been removed from the stack'
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(self.form.processes) == 0, 'The one requested process should have been removed from the stack'
def test_register_multiple_functions(self): def test_register_multiple_functions(form):
""" """
Test running the settings form and adding multiple functions Test running the settings form and adding multiple functions
""" """
# GIVEN: Registering a single function # GIVEN: Registering a single function
self.form.register_post_process('function1') form.register_post_process('function1')
# WHEN testing the processing stack # WHEN testing the processing stack
# THEN the processing stack should have one item # 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' assert len(form.processes) == 1, 'The one requested process should have been added to the stack'
# GIVEN: Registering a new function # GIVEN: Registering a new function
self.form.register_post_process('function2') form.register_post_process('function2')
# WHEN testing the processing stack # WHEN testing the processing stack
# THEN the processing stack should have two items # 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' assert len(form.processes) == 2, 'The two requested processes should have been added to the stack'
# GIVEN: Registering a process for the second time # GIVEN: Registering a process for the second time
self.form.register_post_process('function1') form.register_post_process('function1')
# WHEN testing the processing stack # WHEN testing the processing stack
# THEN the processing stack should still have two items # 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' 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 def test_register_image_manager_trigger_one(form, dummy):
self.form.register_post_process('images_config_updated') """
self.form.accept() 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. # WHEN: The Images have been changed and the form submitted
assert self.dummy1.call_count == 1, 'dummy1 should have been called once' form.register_post_process('images_config_updated')
assert self.dummy2.call_count == 0, 'dummy2 should not have been called at all' form.accept()
assert self.dummy3.call_count == 1, 'dummy3 should have been called once'
def test_register_image_manager_trigger_two(self): # THEN: images_regenerate should have been added.
""" assert dummy[0].call_count == 1, 'dummy1 should have been called once'
Test the triggering of the image manager rebuild event from screen dimension change 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'
# 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('config_screen_changed')
self.form.accept()
# THEN: images_regenerate should have been added. def test_register_image_manager_trigger_two(form, dummy):
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' Test the triggering of the image manager rebuild event from screen dimension change
assert self.dummy3.call_count == 1, 'dummy3 should have been called once' """
# 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): # WHEN: The Images have been changed and the form submitted
""" form.register_post_process('config_screen_changed')
Test the triggering of the image manager rebuild event from image background change and a change to the form.accept()
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 # THEN: images_regenerate should have been added.
self.form.register_post_process('config_screen_changed') assert dummy[0].call_count == 0, 'dummy1 should not have been called at all'
self.form.register_post_process('images_config_updated') assert dummy[1].call_count == 1, 'dummy2 should have been called once'
self.form.accept() 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' def test_register_image_manager_trigger_three(form, dummy):
assert self.dummy2.call_count == 1, 'dummy2 should have been called once' """
assert self.dummy3.call_count == 1, 'dummy3 should have been called once' 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'

View File

@ -21,207 +21,201 @@
""" """
Package to test the openlp.core.ui.shortcutform package. Package to test the openlp.core.ui.shortcutform package.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
from openlp.core.common.registry import Registry
from openlp.core.ui.shortcutlistform import ShortcutListForm 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): def test_adjust_button(form):
""" """
Delete all the C++ objects at the end so that we don't have a segfault Test the _adjust_button() method
""" """
del self.form # GIVEN: A button.
del self.main_window button = QtWidgets.QPushButton()
checked = True
enabled = True
text = 'new!'
def test_adjust_button(self): # WHEN: Call the method.
""" with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method:
Test the _adjust_button() method form._adjust_button(button, checked, enabled, text)
"""
# GIVEN: A button.
button = QtWidgets.QPushButton()
checked = True
enabled = True
text = 'new!'
# WHEN: Call the method. # THEN: The button should be changed.
with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method: assert button.text() == text, 'The text should match.'
self.form._adjust_button(button, checked, enabled, text) 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): def test_space_key_press_event(form):
""" """
Test the keyPressEvent when the spacebar was pressed Test the keyPressEvent when the spacebar was pressed
""" """
# GIVEN: A key event that is a space # 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 = MagicMock()
mocked_event.key.return_value = QtCore.Qt.Key_Space
# WHEN: The event is handled # WHEN: The event is handled
with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event: form.keyPressEvent(mocked_event)
self.form.keyPressEvent(mocked_event)
# THEN: The key should be released # THEN: The key should be released
mocked_key_release_event.assert_called_with(mocked_event) mocked_key_release_event.assert_called_with(mocked_event)
assert 0 == mocked_event.accept.call_count 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 def test_alternate_push_button_checked_key_press_event(form):
self.form.keyPressEvent(mocked_event) """
Test the keyPressEvent when the alternate push button is checked
# THEN: The key should be released """
mocked_key_release_event.assert_called_with(mocked_event) # GIVEN: The primary push button is checked
assert 0 == mocked_event.accept.call_count with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event, \
patch.object(form.alternate_push_button, 'isChecked') as mocked_is_checked:
def test_alternate_push_button_checked_key_press_event(self): mocked_is_checked.return_value = True
"""
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
mocked_event = MagicMock() mocked_event = MagicMock()
mocked_event.key.return_value = QtCore.Qt.Key_Escape
# WHEN: The event is handled # WHEN: The event is handled
with patch.object(self.form, 'close') as mocked_close: form.keyPressEvent(mocked_event)
self.form.keyPressEvent(mocked_event)
# THEN: The key should be released # THEN: The key should be released
mocked_event.accept.assert_called_with() mocked_key_release_event.assert_called_with(mocked_event)
mocked_close.assert_called_with() 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 def test_escape_key_press_event(form):
self.form.on_default_radio_button_clicked(False) """
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) # WHEN: The event is handled
assert 0 == mocked_current_item_action.call_count with patch.object(form, 'close') as mocked_close:
form.keyPressEvent(mocked_event)
def test_on_default_radio_button_clicked_no_action(self): # THEN: The key should be released
""" mocked_event.accept.assert_called_with()
Test that nothing happens when an action hasn't been selected and you click the default radio button mocked_close.assert_called_with()
"""
# 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
# 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) def test_on_default_radio_button_not_toggled(form):
mocked_current_item_action.assert_called_with() """
assert 0 == mocked_action_shortcuts.call_count 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): # WHEN: The clicked method is called
""" form.on_default_radio_button_clicked(False)
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 default radio button is clicked # THEN: The method should exit early (i.e. the rest of the methods are not called)
self.form.on_default_radio_button_clicked(True) 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): def test_on_default_radio_button_clicked_no_action(form):
""" """
Test that the custom radio button method exits early when the button is not toggled Test that nothing happens when an action hasn't been selected and you click the default radio button
""" """
# GIVEN: A not-toggled custom 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: 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 # WHEN: The default radio button is clicked
self.form.on_custom_radio_button_clicked(False) form.on_default_radio_button_clicked(True)
# THEN: The method should exit early (i.e. the rest of the methods are not called) # THEN: The method should exit early (i.e. the rest of the methods are not called)
assert 0 == mocked_current_item_action.call_count 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 def test_on_default_radio_button_clicked(form):
self.form.on_custom_radio_button_clicked(True) """
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 # WHEN: The default radio button is clicked
mocked_current_item_action.assert_called_with() form.on_default_radio_button_clicked(True)
mocked_action_shortcuts.assert_called_with(mocked_action)
mocked_refresh_shortcut_list.assert_called_with() # THEN: The shorcuts should be copied across
mocked_set_text.assert_called_with('Esc') 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')

View File

@ -21,92 +21,78 @@
""" """
Package to test the openlp.core.ui package. Package to test the openlp.core.ui package.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock, patch 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.starttimeform import StartTimeForm
from openlp.core.ui import starttimeform
from tests.helpers.testmixin import TestMixin
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): def test_ui_defaults(form):
""" """
Delete all the C++ objects at the end so that we don't have a segfault Test StartTimeDialog are defaults correct
""" """
del self.form assert form.hour_spin_box.minimum() == 0, 'The minimum hour should stay the same as the dialog'
del self.main_window 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): def test_time_display(form):
""" """
Test StartTimeDialog display functionality Test StartTimeDialog display functionality
""" """
# GIVEN: A service item with with time # GIVEN: A service item with with time
mocked_serviceitem = MagicMock() mocked_serviceitem = MagicMock()
mocked_serviceitem.start_time = 61 mocked_serviceitem.start_time = 61
mocked_serviceitem.end_time = 3701 mocked_serviceitem.end_time = 3701
mocked_serviceitem.media_length = 3701 mocked_serviceitem.media_length = 3701
# WHEN displaying the UI and pressing enter # WHEN displaying the UI and pressing enter
self.form.item = {'service_item': mocked_serviceitem} form.item = {'service_item': mocked_serviceitem}
with patch('PyQt5.QtWidgets.QDialog.exec'): with patch('PyQt5.QtWidgets.QDialog.exec'):
self.form.exec() form.exec()
ok_widget = self.form.button_box.button(self.form.button_box.Ok) ok_widget = form.button_box.button(form.button_box.Ok)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following input values are returned # THEN the following input values are returned
assert self.form.hour_spin_box.value() == 0 assert form.hour_spin_box.value() == 0
assert self.form.minute_spin_box.value() == 1 assert form.minute_spin_box.value() == 1
assert self.form.second_spin_box.value() == 1 assert form.second_spin_box.value() == 1
assert self.form.item['service_item'].start_time == 61, 'The start time should stay the same' 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 # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter
self.form.item = {'service_item': mocked_serviceitem} form.item = {'service_item': mocked_serviceitem}
with patch('PyQt5.QtWidgets.QDialog.exec'): with patch('PyQt5.QtWidgets.QDialog.exec'):
self.form.exec() form.exec()
self.form.minute_spin_box.setValue(2) form.minute_spin_box.setValue(2)
self.form.second_spin_box.setValue(3) form.second_spin_box.setValue(3)
ok_widget = self.form.button_box.button(self.form.button_box.Ok) ok_widget = form.button_box.button(form.button_box.Ok)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following values are returned # THEN the following values are returned
assert self.form.hour_spin_box.value() == 0 assert form.hour_spin_box.value() == 0
assert self.form.minute_spin_box.value() == 2 assert form.minute_spin_box.value() == 2
assert self.form.second_spin_box.value() == 3 assert form.second_spin_box.value() == 3
assert self.form.item['service_item'].start_time == 123, 'The start time should have changed' assert form.item['service_item'].start_time == 123, 'The start time should have changed'

View File

@ -21,116 +21,103 @@
""" """
Interface tests to test the themeManager class and related methods. Interface tests to test the themeManager class and related methods.
""" """
import pytest
from pathlib import Path from pathlib import Path
from unittest import TestCase
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings from openlp.core.common.settings import Settings
from openlp.core.ui.thememanager import ThemeManager 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): # GIVEN: A new a call to initialise
""" theme_manager.setup_ui = MagicMock()
Create the UI theme_manager.build_theme_path = MagicMock()
""" Settings().setValue('themes/global theme', 'my_theme')
self.setup_application()
self.build_settings()
Registry.create()
Registry().register('settings', Settings())
self.theme_manager = ThemeManager()
def tearDown(self): # WHEN: the initialisation is run
""" theme_manager.bootstrap_initialise()
Delete all the C++ objects at the end so that we don't have a segfault
"""
self.destroy_settings()
del self.theme_manager
def test_initialise(self): # THEN:
""" theme_manager.setup_ui.assert_called_once_with(theme_manager)
Test the thememanager initialise - basic test assert theme_manager.global_theme == 'my_theme'
""" theme_manager.build_theme_path.assert_called_once_with()
# 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')
# WHEN: the initialisation is run
self.theme_manager.bootstrap_initialise()
# THEN: @patch('openlp.core.ui.thememanager.create_paths')
self.theme_manager.setup_ui.assert_called_once_with(self.theme_manager) @patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path')
assert self.theme_manager.global_theme == 'my_theme' def test_build_theme_path(mocked_get_section_data_path, mocked_create_paths, theme_manager):
self.theme_manager.build_theme_path.assert_called_once_with() """
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') # WHEN: the build_theme_path is run
@patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path') theme_manager.build_theme_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 # THEN: The theme path and the thumb path should be correct
self.theme_manager.build_theme_path() 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): def test_click_on_new_theme(theme_manager):
""" """
Test the on_add_theme event handler is called by the UI Test the on_add_theme event handler is called by the UI
""" """
# GIVEN: An initial form # GIVEN: An initial form
Settings().setValue('themes/global theme', 'my_theme') Settings().setValue('themes/global theme', 'my_theme')
mocked_event = MagicMock() mocked_event = MagicMock()
self.theme_manager.on_add_theme = mocked_event theme_manager.on_add_theme = mocked_event
self.theme_manager.setup_ui(self.theme_manager) theme_manager.setup_ui(theme_manager)
# WHEN displaying the UI and pressing cancel # WHEN displaying the UI and pressing cancel
new_theme = self.theme_manager.toolbar.actions['newTheme'] new_theme = theme_manager.toolbar.actions['newTheme']
new_theme.trigger() 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: @patch('openlp.core.ui.themeform.ThemeForm._setup')
with patch('openlp.core.ui.thememanager.ThemeProgressForm'): @patch('openlp.core.ui.filerenameform.FileRenameForm._setup')
self.theme_manager.bootstrap_post_set_up() 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: # WHEN:
assert self.theme_manager.progress_form is not None with patch('openlp.core.ui.thememanager.ThemeProgressForm'):
assert self.theme_manager.theme_form is not None theme_manager.bootstrap_post_set_up()
assert self.theme_manager.file_rename_form is not None
def test_bootstrap_completion(self): # THEN:
""" assert theme_manager.progress_form is not None
Test the functions of bootstrap_post_setup are called. assert theme_manager.theme_form is not None
""" assert theme_manager.file_rename_form is not None
# GIVEN:
self.theme_manager.load_themes = MagicMock()
self.theme_manager.upgrade_themes = MagicMock()
# WHEN:
self.theme_manager.bootstrap_completion()
# THEN: def test_bootstrap_completion(theme_manager):
self.theme_manager.upgrade_themes.assert_called_once() """
self.theme_manager.load_themes.assert_called_once() 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()

View File

@ -21,14 +21,13 @@
""" """
Module to test the EditCustomForm. Module to test the EditCustomForm.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock, call from unittest.mock import MagicMock, call
from PyQt5 import QtCore, QtGui, QtTest, QtWidgets from PyQt5 import QtCore, QtGui, QtTest, QtWidgets
from openlp.core.common.registry import Registry from openlp.core.common.registry import Registry
from openlp.core.widgets.edits import HistoryComboBox, SearchEdit from openlp.core.widgets.edits import HistoryComboBox, SearchEdit
from tests.helpers.testmixin import TestMixin
class SearchTypes(object): 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)] (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): # GIVEN: The search edit with the search types set. NOTE: The set_search_types(types) is called in the setUp()
""" # method!
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}))
self.search_edit = SearchEdit(self.main_window, 'settings_section') # WHEN:
# To complete set up we have to set the search types.
self.search_edit.set_search_types(SEARCH_TYPES)
def tearDown(self): # THEN: The first search type should be the first one in the list. The selected type should be saved in the
""" # settings
Delete all the C++ objects at the end so that we don't have a segfault assert search_edit.current_search_type() == SearchTypes.First, \
""" "The first search type should be selected."
del self.search_edit Registry().get('settings').setValue.assert_called_once_with('settings_section/last used search type', 0)
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."
class TestHistoryComboBox(TestCase, TestMixin): def test_set_current_search_type(search_edit):
def setUp(self): """
""" Test if changing the search type works.
Some pre-test setup required. """
""" # GIVEN:
Registry.create() # WHEN: Change the search type
self.setup_application() result = search_edit.set_current_search_type(SearchTypes.Second)
self.main_window = QtWidgets.QMainWindow()
Registry().register('main_window', self.main_window)
self.combo = HistoryComboBox(self.main_window)
def tearDown(self): # THEN:
""" assert result is True, "The call should return success (True)."
Delete all the C++ objects at the end so that we don't have a segfault assert search_edit.current_search_type() == SearchTypes.Second, \
""" "The search type should be SearchTypes.Second"
del self.combo assert search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \
del self.main_window "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. def test_clear_button_visibility(search_edit):
self.combo.addItem('test1') """
self.combo.addItem('test2') 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. # WHEN: Type something in the search edit.
assert self.combo.getItems() == ['test1', 'test2'] 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']

View File

@ -21,91 +21,72 @@
""" """
Package to test the openlp.core.widgets.views. Package to test the openlp.core.widgets.views.
""" """
from unittest import TestCase import pytest
from unittest.mock import MagicMock, patch 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.registry import Registry
from openlp.core.common.settings import Settings
from openlp.core.lib.serviceitem import ServiceItem from openlp.core.lib.serviceitem import ServiceItem
from openlp.core.state import State
from openlp.core.widgets.views import ListPreviewWidget from openlp.core.widgets.views import ListPreviewWidget
from tests.helpers.testmixin import TestMixin
from tests.utils.osdinteraction import read_service_from_file 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): def test_initial_slide_count(preview_widget):
""" """
Delete all the C++ objects at the end so that we don't have a segfault. Test the initial slide count .
""" """
del self.preview_widget # GIVEN: A new ListPreviewWidget instance.
del self.main_window # 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): def test_initial_slide_number(preview_widget):
""" """
Test the initial current slide number. Test the initial current slide number.
""" """
# GIVEN: A new ListPreviewWidget instance. # GIVEN: A new ListPreviewWidget instance.
# WHEN: No SlideItem has been added yet. # WHEN: No SlideItem has been added yet.
# THEN: The number of the current item should be -1. # THEN: The number of the current item should be -1.
assert self.preview_widget.current_slide_number() == -1, 'The slide number 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): def test_replace_service_item(preview_widget, state_media):
""" """
Test the change_slide method. Test item counts and current number with a service item.
""" """
# GIVEN: A ServiceItem with two frames content. # GIVEN: A ServiceItem with two frames.
service_item = ServiceItem(None) service_item = ServiceItem(None)
service = read_service_from_file('serviceitem_image_3.osj') service = read_service_from_file('serviceitem_image_3.osj')
with patch('os.path.exists'): with patch('os.path.exists'):
service_item.set_from_service(service[0]) service_item.set_from_service(service[0])
# WHEN: Added to the preview widget and switched to the second frame. # WHEN: Added to the preview widget.
self.preview_widget.replace_service_item(service_item, 1, 0) preview_widget.replace_service_item(service_item, 1, 1)
self.preview_widget.change_slide(1) # THEN: The slide count and number should fit.
# THEN: The current_slide_number should reflect the change. assert 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.' 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.'