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,62 +21,42 @@
""" """
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():
Test the functions in the :mod:`lib` module.
"""
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): with patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__', return_value=None):
self.edit_song_form = EditSongForm(None, MagicMock(), MagicMock()) return EditSongForm(None, MagicMock(), MagicMock())
QtCore.QLocale.setDefault(QtCore.QLocale('en_GB'))
def tearDown(self):
"""
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): def test_validate_matching_tags(edit_song_form):
# Given a set of tags # Given a set of tags
tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{su}', '{/su}'] tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{su}', '{/su}']
# WHEN we validate them # WHEN we validate them
valid = self.edit_song_form._validate_tags(tags) valid = edit_song_form._validate_tags(tags)
# THEN they should be valid # THEN they should be valid
assert valid is True, "The tags list should be valid" assert valid is True, "The tags list should be valid"
def test_validate_nonmatching_tags(self):
def test_validate_nonmatching_tags(edit_song_form):
# Given a set of tags # Given a set of tags
tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{br}', '{su}', '{/su}'] tags = ['{r}', '{/r}', '{bl}', '{/bl}', '{br}', '{su}', '{/su}']
# WHEN we validate them # WHEN we validate them
valid = self.edit_song_form._validate_tags(tags) valid = edit_song_form._validate_tags(tags)
# THEN they should be valid # THEN they should be valid
assert valid is True, "The tags list should be valid" assert valid is True, "The tags list should be valid"
@patch('openlp.plugins.songs.forms.editsongform.set_case_insensitive_completer') @patch('openlp.plugins.songs.forms.editsongform.set_case_insensitive_completer')
def test_load_objects(self, mocked_set_case_insensitive_completer): def test_load_objects(mocked_set_case_insensitive_completer, edit_song_form, settings):
""" """
Test the _load_objects() method Test the _load_objects() method
""" """
@ -91,13 +71,13 @@ class TestEditSongForm(TestCase, TestMixin):
mocked_object.id = 1 mocked_object.id = 1
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_manager.get_all_objects.return_value = [mocked_object] mocked_manager.get_all_objects.return_value = [mocked_object]
self.edit_song_form.manager = mocked_manager edit_song_form.manager = mocked_manager
# WHEN: _load_objects() is called # WHEN: _load_objects() is called
self.edit_song_form._load_objects(mocked_class, mocked_combo, mocked_cache) edit_song_form._load_objects(mocked_class, mocked_combo, mocked_cache)
# THEN: All the correct methods should have been called # THEN: All the correct methods should have been called
self.edit_song_form.manager.get_all_objects.assert_called_once_with(mocked_class) edit_song_form.manager.get_all_objects.assert_called_once_with(mocked_class)
mocked_combo.clear.assert_called_once_with() mocked_combo.clear.assert_called_once_with()
mocked_combo.count.assert_called_once_with() mocked_combo.count.assert_called_once_with()
mocked_combo.addItem.assert_called_once_with('Charles') mocked_combo.addItem.assert_called_once_with('Charles')

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):
Test the functions in the :mod:`lib` module. return EditVerseForm(None)
"""
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'))
def tearDown(self):
"""
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): def test_update_suggested_verse_number_has_no_effect(edit_verse_form):
""" """
Test that update_suggested_verse_number() has no effect when editing a single verse Test that update_suggested_verse_number() has no effect when editing a single verse
""" """
# GIVEN some input values # GIVEN some input values
self.edit_verse_form.has_single_verse = True edit_verse_form.has_single_verse = True
self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=0) edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=0)
self.edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text')
self.edit_verse_form.verse_number_box.setValue(3) edit_verse_form.verse_number_box.setValue(3)
# WHEN the method is called # WHEN the method is called
self.edit_verse_form.update_suggested_verse_number() edit_verse_form.update_suggested_verse_number()
# THEN the verse number must not be changed # THEN the verse number must not be changed
assert 3 == self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3' assert 3 == edit_verse_form.verse_number_box.value(), 'The verse number should be 3'
def test_update_suggested_verse_number_different_type(self):
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 Test that update_suggested_verse_number() returns 0 when editing a second verse of a different type
""" """
# GIVEN some input values # GIVEN some input values
self.edit_verse_form.has_single_verse = False edit_verse_form.has_single_verse = False
self.edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=2) edit_verse_form.verse_type_combo_box.currentIndex = MagicMock(return_value=2)
self.edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text') edit_verse_form.verse_text_edit.toPlainText = MagicMock(return_value='Text')
self.edit_verse_form.verse_number_box.setValue(3) edit_verse_form.verse_number_box.setValue(3)
# WHEN the method is called # WHEN the method is called
self.edit_verse_form.update_suggested_verse_number() edit_verse_form.update_suggested_verse_number()
# THEN the verse number must be changed to 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' assert 1 == 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):
def test_on_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_overflow_split_button_clicked() edit_verse_form.on_overflow_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'

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')
test_file_import.setUp()
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 \ with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \
mocked_retrieve_windows_encoding: mocked_retrieve_windows_encoding:
mocked_retrieve_windows_encoding.return_value = 'cp1252' mocked_retrieve_windows_encoding.return_value = 'cp1252'
self.file_import([TEST_PATH / 'Amazing Grace.ptf'], test_file_import.file_import([TEST_PATH / 'Amazing Grace.ptf'],
self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) test_file_import.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
test_file_import = TestSundayPlusFileImport()
test_file_import.setUp()
test_file_import.test_song_import()
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
"""
del self.form
del self.main_window
def test_basic_display(self):
""" """
Test Service Note form functionality Test Service Note form functionality
""" """
# GIVEN: A dialog with an empty text box # GIVEN: A dialog with an empty text box
self.form.text_edit.setPlainText('') form.text_edit.setPlainText('')
# WHEN displaying the UI and pressing enter # WHEN displaying the UI and pressing enter
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.Save) ok_widget = form.button_box.button(form.button_box.Save)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following input text is returned # THEN the following input text is returned
assert self.form.text_edit.toPlainText() == '', 'The returned text should be empty' assert form.text_edit.toPlainText() == '', 'The returned text should be empty'
# WHEN displaying the UI, having set the text and pressing enter # WHEN displaying the UI, having set the text and pressing enter
text = 'OpenLP is the best worship software' text = 'OpenLP is the best worship software'
self.form.text_edit.setPlainText(text) form.text_edit.setPlainText(text)
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.Save) ok_widget = form.button_box.button(form.button_box.Save)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following text is returned # THEN the following text is returned
assert self.form.text_edit.toPlainText() == text, 'The text originally entered should still be there' assert form.text_edit.toPlainText() == text, 'The text originally entered should still be there'
# WHEN displaying the UI, having set the text and pressing enter # WHEN displaying the UI, having set the text and pressing enter
self.form.text_edit.setPlainText('') form.text_edit.setPlainText('')
with patch('PyQt5.QtWidgets.QDialog.exec'): with patch('PyQt5.QtWidgets.QDialog.exec'):
self.form.exec() form.exec()
self.form.text_edit.setPlainText(text) form.text_edit.setPlainText(text)
ok_widget = self.form.button_box.button(self.form.button_box.Save) ok_widget = form.button_box.button(form.button_box.Save)
QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton)
# THEN the following text is returned # THEN the following text is returned
assert self.form.text_edit.toPlainText() == text, 'The new text should be returned' assert form.text_edit.toPlainText() == text, 'The new text should be returned'

View File

@ -21,53 +21,27 @@
""" """
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():
Test the PluginManager class return MagicMock(), MagicMock(), MagicMock()
"""
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()
def tearDown(self): def test_basic_cancel(form):
"""
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 Test running the settings form and pressing Cancel
""" """
@ -75,13 +49,14 @@ class TestSettingsForm(TestCase, TestMixin):
# WHEN displaying the UI and pressing cancel # WHEN displaying the UI and pressing cancel
with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject: with patch('PyQt5.QtWidgets.QDialog.reject') as mocked_reject:
cancel_widget = self.form.button_box.button(self.form.button_box.Cancel) cancel_widget = form.button_box.button(form.button_box.Cancel)
QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(cancel_widget, QtCore.Qt.LeftButton)
# THEN the dialog reject should have been called # THEN the dialog reject should have been called
assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called' assert mocked_reject.call_count == 1, 'The QDialog.reject should have been called'
def test_basic_accept(self):
def test_basic_accept(form):
""" """
Test running the settings form and pressing Ok Test running the settings form and pressing Ok
""" """
@ -89,104 +64,109 @@ class TestSettingsForm(TestCase, TestMixin):
# WHEN displaying the UI and pressing Ok # WHEN displaying the UI and pressing Ok
with patch('PyQt5.QtWidgets.QDialog.accept') as mocked_accept: with patch('PyQt5.QtWidgets.QDialog.accept') as mocked_accept:
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 dialog reject should have been called # THEN the dialog reject should have been called
assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called' assert mocked_accept.call_count == 1, 'The QDialog.accept should have been called'
def test_basic_register(self):
def test_basic_register(form):
""" """
Test running the settings form and adding a single function Test running the settings form and adding a single function
""" """
# GIVEN: An initial form add a register function # GIVEN: An initial form add a register function
self.form.register_post_process('function1') form.register_post_process('function1')
# WHEN displaying the UI and pressing Ok # WHEN displaying the UI and pressing Ok
with patch('PyQt5.QtWidgets.QDialog.accept'): with patch('PyQt5.QtWidgets.QDialog.accept'):
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 processing stack should be empty # THEN the processing stack should be empty
assert len(self.form.processes) == 0, 'The one requested process should have been removed from the stack' assert len(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):
def test_register_image_manager_trigger_one(form, dummy):
""" """
Test the triggering of the image manager rebuild event from image background change Test the triggering of the image manager rebuild event from image background change
""" """
# GIVEN: Three functions registered to be call # GIVEN: Three functions registered to be call
Registry().register_function('images_config_updated', self.dummy1) Registry().register_function('images_config_updated', dummy[0])
Registry().register_function('config_screen_changed', self.dummy2) Registry().register_function('config_screen_changed', dummy[1])
Registry().register_function('images_regenerate', self.dummy3) Registry().register_function('images_regenerate', dummy[2])
# WHEN: The Images have been changed and the form submitted # WHEN: The Images have been changed and the form submitted
self.form.register_post_process('images_config_updated') form.register_post_process('images_config_updated')
self.form.accept() form.accept()
# THEN: images_regenerate should have been added. # THEN: images_regenerate should have been added.
assert self.dummy1.call_count == 1, 'dummy1 should have been called once' assert dummy[0].call_count == 1, 'dummy1 should have been called once'
assert self.dummy2.call_count == 0, 'dummy2 should not have been called at all' assert dummy[1].call_count == 0, 'dummy2 should not have been called at all'
assert self.dummy3.call_count == 1, 'dummy3 should have been called once' assert dummy[2].call_count == 1, 'dummy3 should have been called once'
def test_register_image_manager_trigger_two(self):
def test_register_image_manager_trigger_two(form, dummy):
""" """
Test the triggering of the image manager rebuild event from screen dimension change Test the triggering of the image manager rebuild event from screen dimension change
""" """
# GIVEN: Three functions registered to be call # GIVEN: Three functions registered to be call
Registry().register_function('images_config_updated', self.dummy1) Registry().register_function('images_config_updated', dummy[0])
Registry().register_function('config_screen_changed', self.dummy2) Registry().register_function('config_screen_changed', dummy[1])
Registry().register_function('images_regenerate', self.dummy3) Registry().register_function('images_regenerate', dummy[2])
# WHEN: The Images have been changed and the form submitted # WHEN: The Images have been changed and the form submitted
self.form.register_post_process('config_screen_changed') form.register_post_process('config_screen_changed')
self.form.accept() form.accept()
# THEN: images_regenerate should have been added. # THEN: images_regenerate should have been added.
assert self.dummy1.call_count == 0, 'dummy1 should not have been called at all' assert dummy[0].call_count == 0, 'dummy1 should not have been called at all'
assert self.dummy2.call_count == 1, 'dummy2 should have been called once' assert dummy[1].call_count == 1, 'dummy2 should have been called once'
assert self.dummy3.call_count == 1, 'dummy3 should have been called once' assert dummy[2].call_count == 1, 'dummy3 should have been called once'
def test_register_image_manager_trigger_three(self):
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 Test the triggering of the image manager rebuild event from image background change and a change to the
screen dimension. screen dimension.
""" """
# GIVEN: Three functions registered to be call # GIVEN: Three functions registered to be call
Registry().register_function('images_config_updated', self.dummy1) Registry().register_function('images_config_updated', dummy[0])
Registry().register_function('config_screen_changed', self.dummy2) Registry().register_function('config_screen_changed', dummy[1])
Registry().register_function('images_regenerate', self.dummy3) Registry().register_function('images_regenerate', dummy[2])
# WHEN: The Images have been changed and the form submitted # WHEN: The Images have been changed and the form submitted
self.form.register_post_process('config_screen_changed') form.register_post_process('config_screen_changed')
self.form.register_post_process('images_config_updated') form.register_post_process('images_config_updated')
self.form.accept() form.accept()
# THEN: Images_regenerate should have been added. # THEN: Images_regenerate should have been added.
assert self.dummy1.call_count == 1, 'dummy1 should have been called once' assert dummy[0].call_count == 1, 'dummy1 should have been called once'
assert self.dummy2.call_count == 1, 'dummy2 should have been called once' assert dummy[1].call_count == 1, 'dummy2 should have been called once'
assert self.dummy3.call_count == 1, 'dummy3 should have been called once' assert dummy[2].call_count == 1, 'dummy3 should have been called once'

View File

@ -21,36 +21,21 @@
""" """
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
"""
del self.form
del self.main_window
def test_adjust_button(self):
""" """
Test the _adjust_button() method Test the _adjust_button() method
""" """
@ -62,14 +47,15 @@ class TestShortcutform(TestCase, TestMixin):
# WHEN: Call the method. # WHEN: Call the method.
with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method: with patch('PyQt5.QtWidgets.QPushButton.setChecked') as mocked_check_method:
self.form._adjust_button(button, checked, enabled, text) form._adjust_button(button, checked, enabled, text)
# THEN: The button should be changed. # THEN: The button should be changed.
assert button.text() == text, 'The text should match.' assert button.text() == text, 'The text should match.'
mocked_check_method.assert_called_once_with(True) mocked_check_method.assert_called_once_with(True)
assert button.isEnabled() == enabled, 'The button should be disabled.' 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
""" """
@ -78,48 +64,51 @@ class TestShortcutform(TestCase, TestMixin):
mocked_event.key.return_value = QtCore.Qt.Key_Space 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: with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event:
self.form.keyPressEvent(mocked_event) 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):
def test_primary_push_button_checked_key_press_event(form):
""" """
Test the keyPressEvent when the primary push button is checked Test the keyPressEvent when the primary push button is checked
""" """
# GIVEN: The primary push button is checked # GIVEN: The primary push button is checked
with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event, \ with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event, \
patch.object(self.form.primary_push_button, 'isChecked') as mocked_is_checked: patch.object(form.primary_push_button, 'isChecked') as mocked_is_checked:
mocked_is_checked.return_value = True mocked_is_checked.return_value = True
mocked_event = MagicMock() mocked_event = MagicMock()
# WHEN: The event is handled # WHEN: The event is handled
self.form.keyPressEvent(mocked_event) 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_alternate_push_button_checked_key_press_event(self):
def test_alternate_push_button_checked_key_press_event(form):
""" """
Test the keyPressEvent when the alternate push button is checked Test the keyPressEvent when the alternate push button is checked
""" """
# GIVEN: The primary push button is checked # GIVEN: The primary push button is checked
with patch.object(self.form, 'keyReleaseEvent') as mocked_key_release_event, \ with patch.object(form, 'keyReleaseEvent') as mocked_key_release_event, \
patch.object(self.form.alternate_push_button, 'isChecked') as mocked_is_checked: patch.object(form.alternate_push_button, 'isChecked') as mocked_is_checked:
mocked_is_checked.return_value = True mocked_is_checked.return_value = True
mocked_event = MagicMock() mocked_event = MagicMock()
# WHEN: The event is handled # WHEN: The event is handled
self.form.keyPressEvent(mocked_event) 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_escape_key_press_event(self):
def test_escape_key_press_event(form):
""" """
Test the keyPressEvent when the escape key was pressed Test the keyPressEvent when the escape key was pressed
""" """
@ -128,52 +117,55 @@ class TestShortcutform(TestCase, TestMixin):
mocked_event.key.return_value = QtCore.Qt.Key_Escape 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: with patch.object(form, 'close') as mocked_close:
self.form.keyPressEvent(mocked_event) form.keyPressEvent(mocked_event)
# THEN: The key should be released # THEN: The key should be released
mocked_event.accept.assert_called_with() mocked_event.accept.assert_called_with()
mocked_close.assert_called_with() mocked_close.assert_called_with()
def test_on_default_radio_button_not_toggled(self):
def test_on_default_radio_button_not_toggled(form):
""" """
Test that the default radio button method exits early when the button is not toggled Test that the default radio button method exits early when the button is not toggled
""" """
# GIVEN: A not-toggled custom radio button # GIVEN: A not-toggled custom radio button
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:
# WHEN: The clicked method is called # WHEN: The clicked method is called
self.form.on_default_radio_button_clicked(False) form.on_default_radio_button_clicked(False)
# 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 assert 0 == mocked_current_item_action.call_count
def test_on_default_radio_button_clicked_no_action(self):
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 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 # 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(self.form, '_action_shortcuts') as mocked_action_shortcuts: patch.object(form, '_action_shortcuts') as mocked_action_shortcuts:
mocked_current_item_action.return_value = None mocked_current_item_action.return_value = None
# WHEN: The default radio button is clicked # WHEN: The default radio button is clicked
self.form.on_default_radio_button_clicked(True) 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)
mocked_current_item_action.assert_called_with() mocked_current_item_action.assert_called_with()
assert 0 == mocked_action_shortcuts.call_count assert 0 == mocked_action_shortcuts.call_count
def test_on_default_radio_button_clicked(self):
def test_on_default_radio_button_clicked(form):
""" """
Test that the values are copied across correctly when the default radio button is selected 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 # 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(self.form, '_action_shortcuts') as mocked_action_shortcuts, \ patch.object(form, '_action_shortcuts') as mocked_action_shortcuts, \
patch.object(self.form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ patch.object(form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \
patch.object(self.form, 'get_shortcut_string') as mocked_get_shortcut_string, \ patch.object(form, 'get_shortcut_string') as mocked_get_shortcut_string, \
patch.object(self.form.primary_push_button, 'setText') as mocked_set_text: patch.object(form.primary_push_button, 'setText') as mocked_set_text:
mocked_action = MagicMock() mocked_action = MagicMock()
mocked_action.default_shortcuts = [QtCore.Qt.Key_Escape] mocked_action.default_shortcuts = [QtCore.Qt.Key_Escape]
mocked_current_item_action.return_value = mocked_action mocked_current_item_action.return_value = mocked_action
@ -181,7 +173,7 @@ class TestShortcutform(TestCase, TestMixin):
mocked_get_shortcut_string.return_value = 'Esc' mocked_get_shortcut_string.return_value = 'Esc'
# WHEN: The default radio button is clicked # WHEN: The default radio button is clicked
self.form.on_default_radio_button_clicked(True) form.on_default_radio_button_clicked(True)
# THEN: The shorcuts should be copied across # THEN: The shorcuts should be copied across
mocked_current_item_action.assert_called_with() mocked_current_item_action.assert_called_with()
@ -189,36 +181,38 @@ class TestShortcutform(TestCase, TestMixin):
mocked_refresh_shortcut_list.assert_called_with() mocked_refresh_shortcut_list.assert_called_with()
mocked_set_text.assert_called_with('Esc') mocked_set_text.assert_called_with('Esc')
def test_on_custom_radio_button_not_toggled(self):
def test_on_custom_radio_button_not_toggled(form):
""" """
Test that the custom radio button method exits early when the button is not toggled Test that the custom radio button method exits early when the button is not toggled
""" """
# GIVEN: A not-toggled custom radio button # GIVEN: A not-toggled custom radio button
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:
# WHEN: The clicked method is called # WHEN: The clicked method is called
self.form.on_custom_radio_button_clicked(False) form.on_custom_radio_button_clicked(False)
# 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 assert 0 == mocked_current_item_action.call_count
def test_on_custom_radio_button_clicked(self):
def test_on_custom_radio_button_clicked(form):
""" """
Test that the values are copied across correctly when the custom radio button is selected 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 # 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(self.form, '_action_shortcuts') as mocked_action_shortcuts, \ patch.object(form, '_action_shortcuts') as mocked_action_shortcuts, \
patch.object(self.form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \ patch.object(form, 'refresh_shortcut_list') as mocked_refresh_shortcut_list, \
patch.object(self.form, 'get_shortcut_string') as mocked_get_shortcut_string, \ patch.object(form, 'get_shortcut_string') as mocked_get_shortcut_string, \
patch.object(self.form.primary_push_button, 'setText') as mocked_set_text: patch.object(form.primary_push_button, 'setText') as mocked_set_text:
mocked_action = MagicMock() mocked_action = MagicMock()
mocked_current_item_action.return_value = mocked_action mocked_current_item_action.return_value = mocked_action
mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape] mocked_action_shortcuts.return_value = [QtCore.Qt.Key_Escape]
mocked_get_shortcut_string.return_value = 'Esc' mocked_get_shortcut_string.return_value = 'Esc'
# WHEN: The custom radio button is clicked # WHEN: The custom radio button is clicked
self.form.on_custom_radio_button_clicked(True) form.on_custom_radio_button_clicked(True)
# THEN: The shorcuts should be copied across # THEN: The shorcuts should be copied across
mocked_current_item_action.assert_called_with() mocked_current_item_action.assert_called_with()

View File

@ -21,59 +21,45 @@
""" """
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
"""
del self.form
del self.main_window
def test_ui_defaults(self):
""" """
Test StartTimeDialog are defaults correct Test StartTimeDialog are defaults correct
""" """
assert self.form.hour_spin_box.minimum() == 0, 'The minimum hour should stay the same as the dialog' assert 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 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 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 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 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 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, \ assert form.hour_finish_spin_box.minimum() == 0, \
'The minimum finish hour should stay the same as the dialog' 'The minimum finish hour should stay the same as the dialog'
assert self.form.hour_finish_spin_box.maximum() == 4, \ assert form.hour_finish_spin_box.maximum() == 4, \
'The maximum finish hour should stay the same as the dialog' 'The maximum finish hour should stay the same as the dialog'
assert self.form.minute_finish_spin_box.minimum() == 0, \ assert form.minute_finish_spin_box.minimum() == 0, \
'The minimum finish minute should stay the same as the dialog' 'The minimum finish minute should stay the same as the dialog'
assert self.form.minute_finish_spin_box.maximum() == 59, \ assert form.minute_finish_spin_box.maximum() == 59, \
'The maximum finish minute should stay the same as the dialog' 'The maximum finish minute should stay the same as the dialog'
assert self.form.second_finish_spin_box.minimum() == 0, \ assert form.second_finish_spin_box.minimum() == 0, \
'The minimum finish second should stay the same as the dialog' 'The minimum finish second should stay the same as the dialog'
assert self.form.second_finish_spin_box.maximum() == 59, \ assert form.second_finish_spin_box.maximum() == 59, \
'The maximum finish second should stay the same as the dialog' '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
""" """
@ -84,29 +70,29 @@ class TestStartTimeDialog(TestCase, TestMixin):
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,57 +21,41 @@
""" """
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):
Test the functions in the ThemeManager module thm = ThemeManager()
""" return thm
def setUp(self):
"""
Create the UI
"""
self.setup_application()
self.build_settings()
Registry.create()
Registry().register('settings', Settings())
self.theme_manager = ThemeManager()
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
def test_initialise(self): def test_theme_manager_initialise(theme_manager):
""" """
Test the thememanager initialise - basic test Test the thememanager initialise - basic test
""" """
# GIVEN: A new a call to initialise # GIVEN: A new a call to initialise
self.theme_manager.setup_ui = MagicMock() theme_manager.setup_ui = MagicMock()
self.theme_manager.build_theme_path = MagicMock() theme_manager.build_theme_path = MagicMock()
Settings().setValue('themes/global theme', 'my_theme') Settings().setValue('themes/global theme', 'my_theme')
# WHEN: the initialisation is run # WHEN: the initialisation is run
self.theme_manager.bootstrap_initialise() theme_manager.bootstrap_initialise()
# THEN: # THEN:
self.theme_manager.setup_ui.assert_called_once_with(self.theme_manager) theme_manager.setup_ui.assert_called_once_with(theme_manager)
assert self.theme_manager.global_theme == 'my_theme' assert theme_manager.global_theme == 'my_theme'
self.theme_manager.build_theme_path.assert_called_once_with() theme_manager.build_theme_path.assert_called_once_with()
@patch('openlp.core.ui.thememanager.create_paths') @patch('openlp.core.ui.thememanager.create_paths')
@patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path') @patch('openlp.core.ui.thememanager.AppLocation.get_section_data_path')
def test_build_theme_path(self, mocked_get_section_data_path, mocked_create_paths): def test_build_theme_path(mocked_get_section_data_path, mocked_create_paths, theme_manager):
""" """
Test the thememanager build_theme_path Test the thememanager build_theme_path
""" """
@ -79,58 +63,61 @@ class TestThemeManager(TestCase, TestMixin):
mocked_get_section_data_path.return_value = Path('tests/my_theme') mocked_get_section_data_path.return_value = Path('tests/my_theme')
# WHEN: the build_theme_path is run # WHEN: the build_theme_path is run
self.theme_manager.build_theme_path() theme_manager.build_theme_path()
# THEN: The theme path and the thumb path should be correct # THEN: The theme path and the thumb path should be correct
assert self.theme_manager.theme_path == Path('tests/my_theme') assert theme_manager.theme_path == Path('tests/my_theme')
assert self.theme_manager.thumb_path == Path('tests/my_theme/thumbnails') 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')) 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.themeform.ThemeForm._setup')
@patch('openlp.core.ui.filerenameform.FileRenameForm._setup') @patch('openlp.core.ui.filerenameform.FileRenameForm._setup')
def test_bootstrap_post(self, mocked_rename_form, mocked_theme_form): def test_bootstrap_post(mocked_rename_form, mocked_theme_form, theme_manager):
""" """
Test the functions of bootstrap_post_setup are called. Test the functions of bootstrap_post_setup are called.
""" """
# GIVEN: # GIVEN:
self.theme_manager.theme_path = MagicMock() theme_manager.theme_path = MagicMock()
# WHEN: # WHEN:
with patch('openlp.core.ui.thememanager.ThemeProgressForm'): with patch('openlp.core.ui.thememanager.ThemeProgressForm'):
self.theme_manager.bootstrap_post_set_up() theme_manager.bootstrap_post_set_up()
# THEN: # THEN:
assert self.theme_manager.progress_form is not None assert theme_manager.progress_form is not None
assert self.theme_manager.theme_form is not None assert theme_manager.theme_form is not None
assert self.theme_manager.file_rename_form is not None assert theme_manager.file_rename_form is not None
def test_bootstrap_completion(self):
def test_bootstrap_completion(theme_manager):
""" """
Test the functions of bootstrap_post_setup are called. Test the functions of bootstrap_post_setup are called.
""" """
# GIVEN: # GIVEN:
self.theme_manager.load_themes = MagicMock() theme_manager.load_themes = MagicMock()
self.theme_manager.upgrade_themes = MagicMock() theme_manager.upgrade_themes = MagicMock()
# WHEN: # WHEN:
self.theme_manager.bootstrap_completion() theme_manager.bootstrap_completion()
# THEN: # THEN:
self.theme_manager.upgrade_themes.assert_called_once() theme_manager.upgrade_themes.assert_called_once()
self.theme_manager.load_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,32 +43,28 @@ 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):
Test the EditCustomForm. main_window = QtWidgets.QMainWindow()
""" Registry().register('main_window', main_window)
def setUp(self): Registry().remove('settings')
"""
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})) Registry().register('settings', MagicMock(**{'value.return_value': SearchTypes.First}))
self.search_edit = SearchEdit(self.main_window, 'settings_section') s_edit = SearchEdit(main_window, 'settings_section')
# To complete set up we have to set the search types. # To complete set up we have to set the search types.
self.search_edit.set_search_types(SEARCH_TYPES) s_edit.set_search_types(SEARCH_TYPES)
return s_edit
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): @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 setting the search types of the search edit. Test setting the search types of the search edit.
""" """
@ -80,84 +75,69 @@ class TestSearchEdit(TestCase, TestMixin):
# THEN: The first search type should be the first one in the list. The selected type should be saved in the # THEN: The first search type should be the first one in the list. The selected type should be saved in the
# settings # settings
assert self.search_edit.current_search_type() == SearchTypes.First, \ assert search_edit.current_search_type() == SearchTypes.First, \
"The first search type should be selected." "The first search type should be selected."
Registry().get('settings').setValue.assert_called_once_with('settings_section/last used search type', 0) Registry().get('settings').setValue.assert_called_once_with('settings_section/last used search type', 0)
def test_set_current_search_type(self):
def test_set_current_search_type(search_edit):
""" """
Test if changing the search type works. Test if changing the search type works.
""" """
# GIVEN: # GIVEN:
# WHEN: Change the search type # WHEN: Change the search type
result = self.search_edit.set_current_search_type(SearchTypes.Second) result = search_edit.set_current_search_type(SearchTypes.Second)
# THEN: # THEN:
assert result is True, "The call should return success (True)." assert result is True, "The call should return success (True)."
assert self.search_edit.current_search_type() == SearchTypes.Second, \ assert search_edit.current_search_type() == SearchTypes.Second, \
"The search type should be SearchTypes.Second" "The search type should be SearchTypes.Second"
assert self.search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \ assert search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \
"The correct placeholder text should be 'Second Placeholder Text'." "The correct placeholder text should be 'Second Placeholder Text'."
Registry().get('settings').setValue.assert_has_calls( Registry().get('settings').setValue.assert_has_calls(
[call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)]) [call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)])
def test_clear_button_visibility(self):
def test_clear_button_visibility(search_edit):
""" """
Test if the clear button is hidden/shown correctly. Test if the clear button is hidden/shown correctly.
""" """
# GIVEN: Everything is left to its defaults (hidden). # GIVEN: Everything is left to its defaults (hidden).
assert self.search_edit.clear_button.isHidden(), "Pre condition not met. Button should be hidden." assert search_edit.clear_button.isHidden(), "Pre condition not met. Button should be hidden."
# WHEN: Type something in the search edit. # WHEN: Type something in the search edit.
QtTest.QTest.keyPress(self.search_edit, QtCore.Qt.Key_A) QtTest.QTest.keyPress(search_edit, QtCore.Qt.Key_A)
QtTest.QTest.keyRelease(self.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. # THEN: The clear button should not be hidden any more.
assert not self.search_edit.clear_button.isHidden(), "The clear button should be visible." assert not search_edit.clear_button.isHidden(), "The clear button should be visible."
def test_press_clear_button(self):
def test_press_clear_button(search_edit):
""" """
Check if the search edit behaves correctly when pressing the clear button. Check if the search edit behaves correctly when pressing the clear button.
""" """
# GIVEN: A search edit with text. # GIVEN: A search edit with text.
QtTest.QTest.keyPress(self.search_edit, QtCore.Qt.Key_A) QtTest.QTest.keyPress(search_edit, QtCore.Qt.Key_A)
QtTest.QTest.keyRelease(self.search_edit, QtCore.Qt.Key_A) QtTest.QTest.keyRelease(search_edit, QtCore.Qt.Key_A)
# WHEN: Press the clear button. # WHEN: Press the clear button.
QtTest.QTest.mouseClick(self.search_edit.clear_button, QtCore.Qt.LeftButton) QtTest.QTest.mouseClick(search_edit.clear_button, QtCore.Qt.LeftButton)
# THEN: The search edit text should be cleared and the button be hidden. # 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 not search_edit.text(), "The search edit should not have any text."
assert self.search_edit.clear_button.isHidden(), "The clear button should be hidden." assert search_edit.clear_button.isHidden(), "The clear button should be hidden."
class TestHistoryComboBox(TestCase, TestMixin): def test_history_combo_get_items(combo):
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 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
def test_get_items(self):
""" """
Test the getItems() method Test the getItems() method
""" """
# GIVEN: The combo. # GIVEN: The combo.
# WHEN: Add two items. # WHEN: Add two items.
self.combo.addItem('test1') combo.addItem('test1')
self.combo.addItem('test2') combo.addItem('test2')
# THEN: The list of items should contain both strings. # THEN: The list of items should contain both strings.
assert self.combo.getItems() == ['test1', 'test2'] assert combo.getItems() == ['test1', 'test2']

View File

@ -21,66 +21,46 @@
""" """
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.
"""
del self.preview_widget
del self.main_window
def test_initial_slide_count(self):
""" """
Test the initial slide count . Test the initial slide count .
""" """
# 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 count of items should be zero. # THEN: The count of items should be zero.
assert self.preview_widget.slide_count() == 0, 'The slide list should be empty.' assert 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):
def test_replace_service_item(preview_widget, state_media):
""" """
Test item counts and current number with a service item. Test item counts and current number with a service item.
""" """
@ -90,12 +70,13 @@ class TestListPreviewWidget(TestCase, TestMixin):
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. # WHEN: Added to the preview widget.
self.preview_widget.replace_service_item(service_item, 1, 1) preview_widget.replace_service_item(service_item, 1, 1)
# THEN: The slide count and number should fit. # THEN: The slide count and number should fit.
assert self.preview_widget.slide_count() == 2, 'The slide count should be 2.' 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(self):
def test_change_slide(preview_widget, state_media):
""" """
Test the change_slide method. Test the change_slide method.
""" """
@ -105,7 +86,7 @@ class TestListPreviewWidget(TestCase, TestMixin):
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 and switched to the second frame.
self.preview_widget.replace_service_item(service_item, 1, 0) preview_widget.replace_service_item(service_item, 1, 0)
self.preview_widget.change_slide(1) preview_widget.change_slide(1)
# THEN: The current_slide_number should reflect the change. # THEN: The current_slide_number should reflect the change.
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.'