forked from openlp/openlp
392 lines
22 KiB
Python
392 lines
22 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
##########################################################################
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
# ---------------------------------------------------------------------- #
|
|
# Copyright (c) 2008-2020 OpenLP Developers #
|
|
# ---------------------------------------------------------------------- #
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# This program is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
##########################################################################
|
|
"""
|
|
Package to test the openlp.plugins.planningcenter.forms.selectplanform package.
|
|
"""
|
|
import os
|
|
import re
|
|
from datetime import date, datetime
|
|
from unittest import TestCase, skip
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from PyQt5 import QtWidgets, QtTest, QtCore
|
|
|
|
from openlp.core.common.registry import Registry
|
|
from openlp.core.common.settings import Settings
|
|
from openlp.core.state import State
|
|
from openlp.core.ui.servicemanager import ServiceManager
|
|
from openlp.core.ui.settingsform import SettingsForm
|
|
from openlp.core.ui.thememanager import ThemeManager
|
|
from openlp.plugins.bibles.bibleplugin import BiblePlugin
|
|
from openlp.plugins.bibles.lib.mediaitem import BibleMediaItem
|
|
from openlp.plugins.custom.customplugin import CustomPlugin
|
|
from openlp.plugins.custom.lib.mediaitem import CustomMediaItem
|
|
from openlp.plugins.planningcenter.forms.selectplanform import SelectPlanForm
|
|
from openlp.plugins.planningcenter.planningcenterplugin import PlanningCenterPlugin
|
|
from openlp.plugins.songs.lib.mediaitem import SongMediaItem
|
|
from openlp.plugins.songs.songsplugin import SongsPlugin
|
|
from tests.helpers.testmixin import TestMixin
|
|
|
|
TEST_PATH = os.path.abspath(
|
|
os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'resources', 'planningcenter'))
|
|
|
|
|
|
class TestSelectPlanForm(TestCase, TestMixin):
|
|
"""
|
|
Test the SelectPlanForm class
|
|
"""
|
|
|
|
def setUp(self):
|
|
"""
|
|
Create the UI
|
|
"""
|
|
self.registry = Registry()
|
|
Registry.create()
|
|
self.setup_application()
|
|
self.build_settings()
|
|
State().load_settings()
|
|
Registry().register('settings', Settings())
|
|
Registry().register('main_window', MagicMock(service_manager_settings_section='servicemanager'))
|
|
self.application_id = 'abc'
|
|
self.secret = '123'
|
|
Settings().setValue('planningcenter/application_id', self.application_id)
|
|
Settings().setValue('planningcenter/secret', self.secret)
|
|
# init the planning center plugin so we have default values defined for Settings()
|
|
self.planning_center_plugin = PlanningCenterPlugin()
|
|
# setup our form
|
|
self.form = SelectPlanForm()
|
|
self.form.planning_center_api.airplane_mode = True
|
|
self.form.planning_center_api.airplane_mode_directory = TEST_PATH
|
|
self.theme_manager = ThemeManager(None)
|
|
self.theme_manager.get_theme_names = MagicMock()
|
|
self.theme_manager.get_theme_names.return_value = ['themeA', 'themeB']
|
|
|
|
def tearDown(self):
|
|
"""
|
|
Delete all the C++ objects at the end so that we don't have a segfault
|
|
"""
|
|
del self.form
|
|
del self.planning_center_plugin
|
|
del self.theme_manager
|
|
del self.registry
|
|
self.destroy_settings()
|
|
|
|
def test_initial_defaults(self):
|
|
"""
|
|
Test that the SelectPlanForm displays with correct defaults
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# a theme manager with mocked themes, and a fake date = Sunday (7/29/2018)
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/29/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 29)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
# WHEN: The form is shown
|
|
self.form.exec()
|
|
# THEN: The correct count of service types show up in the combo box
|
|
combo_box_count = self.form.service_type_combo_box.count()
|
|
self.assertEqual(combo_box_count, 2,
|
|
'The service_type_combo_box contains 2 items')
|
|
# The first service type is selected
|
|
self.assertEqual(self.form.service_type_combo_box.currentText(), 'gbf',
|
|
'The service_type_combo_box defaults to "gbf"')
|
|
# the selected plan is today (the mocked date is a Sunday). Set to lowercase beacuse in some locales
|
|
# months is not capitalized.
|
|
self.assertEqual(self.form.plan_selection_combo_box.currentText().lower(),
|
|
date.strftime(mock_date.today.return_value, '%B %d, %Y').lower(),
|
|
'Incorrect default date selected for Plan Date')
|
|
# count the number of themes listed and make sure it matches expected value
|
|
self.assertEqual(self.form.song_theme_selection_combo_box.count(),
|
|
2, 'Count of song themes is incorrect')
|
|
self.assertEqual(self.form.slide_theme_selection_combo_box.count(),
|
|
2, 'Count of custom slide themes is incorrect')
|
|
|
|
def test_warning_messagebox_shown_for_bad_credentials(self):
|
|
"""
|
|
Test that if we don't have good credentials, then it will show a QMessageBox with a warning in it
|
|
"""
|
|
# GIVEN: A SelectPlanForm instance with airplane mode enabled, resources, available,
|
|
# mocked check_credentials function to return ''
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch.object(self.form.planning_center_api, 'check_credentials', return_value=''), \
|
|
patch('PyQt5.QtWidgets.QMessageBox.warning') as mock_warning:
|
|
# WHEN: form is displayed
|
|
self.form.exec()
|
|
# THEN: we should have called a warning messagebox
|
|
mock_warning.assert_called_once()
|
|
|
|
def test_disable_import_buttons(self):
|
|
"""
|
|
Test that the import buttons are disabled when the "Select Plan Date" element in the
|
|
Plan Selection List is selected.
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available, and the form
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'):
|
|
self.form.exec()
|
|
# WHEN: The Select Plan combo box is set to "Select Plan Date"
|
|
index = self.form.plan_selection_combo_box.findText('Select Plan Date')
|
|
self.form.plan_selection_combo_box.setCurrentIndex(index)
|
|
# THEN: "Import New" and "Refresh Service" buttons become inactive
|
|
self.assertEqual(self.form.import_as_new_button.isEnabled(), False,
|
|
'"Import as New" button should be disabled')
|
|
self.assertEqual(self.form.update_existing_button.isEnabled(), False,
|
|
'"Refresh Service" button should be disabled')
|
|
|
|
def test_default_plan_date_is_next_sunday(self):
|
|
"""
|
|
Test that the SelectPlanForm displays Next Sunday's Date by Default
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# a theme manager with mocked themes, and a fake date = (9/24/2019)
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/24/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 24)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
self.form.exec()
|
|
# WHEN: The second (index=1) service type is selected
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
# THEN: The plan selection date is 9/29 (the following Sunday)
|
|
self.assertEqual(self.form.plan_selection_combo_box.currentText(), 'September 29, 2019',
|
|
'The next Sunday\'s Date is not selected in the plan_selection_combo_box')
|
|
|
|
def test_service_type_changed_called_when_service_type_combo_changed(self):
|
|
"""
|
|
Test that the "on_service_type_combobox_changed" function is executed when the
|
|
service_type_combobox is changed
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'):
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
# THEN: The on_service_type_combobox_changed function is called
|
|
assert self.form.plan_selection_combo_box.count() > 0, 'Plan Selection Combo Box is not empty'
|
|
assert self.form.plan_selection_combo_box.itemText(0) == 'Select Plan Date', 'Plan Combo Box has default text'
|
|
|
|
def test_plan_selection_changed_called_when_plan_selection_combo_changed(self):
|
|
"""
|
|
Test that the "on_plan_selection_combobox_changed" function is executed when the
|
|
plan_selection_combobox is changed
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'):
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
self.form.plan_selection_combo_box.setCurrentIndex(1)
|
|
# THEN: The import and update buttons should be enabled
|
|
assert self.form.import_as_new_button.isEnabled() is True, 'Import button should be enabled'
|
|
assert self.form.update_existing_button.isEnabled() is True, 'Update button should be enabled'
|
|
|
|
def test_settings_tab_displayed_when_edit_auth_button_clicked(self):
|
|
"""
|
|
Test that the settings dialog is displayed when the edit_auth_button is clicked
|
|
"""
|
|
# GIVEN: A SelectPlanForm instance with airplane mode enabled and resources available
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.core.ui.settingsform.SettingsForm.exec') as mock_settings_form:
|
|
SettingsForm()
|
|
self.form.exec()
|
|
# WHEN: the edit_auth_button is clicked
|
|
QtTest.QTest.mouseClick(self.form.edit_auth_button, QtCore.Qt.LeftButton)
|
|
self.assertEqual(mock_settings_form.called, 1, "Settings Form opened when edit_auth_button clicked")
|
|
|
|
def test_import_function_called_when_import_button_clicked(self):
|
|
"""
|
|
Test that the "on_import_as_new_button_clicked" function is executed when the
|
|
"Import New" button is clicked
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.SelectPlanForm._do_import') \
|
|
as mock_do_import:
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1 and the Select Plan combo box is set
|
|
# to index 1 and the "Import New" button is clicked
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
self.form.plan_selection_combo_box.setCurrentIndex(4)
|
|
QtTest.QTest.mouseClick(self.form.import_as_new_button, QtCore.Qt.LeftButton)
|
|
# THEN: The on_import_as_new_button_cliced function is called
|
|
mock_do_import.assert_called_with(update=False)
|
|
|
|
def test_service_imported_when_import_button_clicked(self):
|
|
"""
|
|
Test that a service is imported when the "Import New" button is clicked
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# mocked out "on_new_service_clicked"
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.core.common.registry.Registry.get'), \
|
|
patch('openlp.plugins.planningcenter.lib.songimport.PlanningCenterSongImport.finish') \
|
|
as mock_song_import, \
|
|
patch('openlp.plugins.planningcenter.lib.customimport.CustomSlide') as mock_custom_slide_import, \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.parse_reference') as mock_bible_import, \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/29/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 29)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1 and the Select Plan combo box is set to
|
|
# index 1 and the "Import New" button is clicked
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
QtTest.QTest.mouseClick(self.form.import_as_new_button, QtCore.Qt.LeftButton)
|
|
# THEN: There should be 5 service items added, 1 song, 3 custom slides (one is a bible
|
|
# title slide), and 1 bible verse
|
|
self.assertEqual(mock_song_import.call_count, 1, '1 song added via song_media_item')
|
|
self.assertEqual(mock_custom_slide_import.call_count, 4, '4 custom slide added via custom_media_item')
|
|
self.assertEqual(mock_bible_import.call_count, 2, '2 bible verses submitted for parsing')
|
|
|
|
def test_service_refreshed_when_refresh_button_clicked(self):
|
|
"""
|
|
Test that a service is refreshed when the "Refresh Service" button is clicked
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# mocked out "on_new_service_clicked"
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.core.common.registry.Registry.get'), \
|
|
patch('openlp.plugins.planningcenter.lib.songimport.PlanningCenterSongImport.finish') \
|
|
as mock_song_import, \
|
|
patch('openlp.plugins.planningcenter.lib.customimport.CustomSlide') as mock_custom_slide_import, \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.parse_reference') as mock_bible_import, \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/29/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 29)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1 and the Select Plan combo box is
|
|
# set to index 1 and the "Update" button is clicked
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
QtTest.QTest.mouseClick(self.form.update_existing_button, QtCore.Qt.LeftButton)
|
|
# THEN: There should be 5 service items added, 1 song, 3 custom slides (one is a bible
|
|
# title slide), and 1 bible verse
|
|
self.assertEqual(mock_song_import.call_count, 1, '1 song added via song_media_item')
|
|
self.assertEqual(mock_custom_slide_import.call_count, 4, '4 custom slide added via custom_media_item')
|
|
self.assertEqual(mock_bible_import.call_count, 2, '2 bible verses submitted for parsing')
|
|
|
|
def test_other_bible_is_used_when_bible_gui_form_is_blank(self):
|
|
"""
|
|
Test that an other bible is used when the GUI has an empty string for current selected bible
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# mocked out "on_new_service_clicked"
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.core.common.registry.Registry.get') as mock_get, \
|
|
patch('openlp.plugins.planningcenter.lib.songimport.PlanningCenterSongImport.finish'), \
|
|
patch('openlp.plugins.planningcenter.lib.customimport.CustomSlide'), \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.parse_reference') as mock_bible_import, \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/29/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 29)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
mock_bibles = {}
|
|
mock_bibles['other_bible'] = MagicMock()
|
|
mock_get.return_value.plugin.manager.get_bibles.return_value = mock_bibles
|
|
mock_get.return_value.version_combo_box.currentText.return_value = ''
|
|
self.form.exec()
|
|
# WHEN: The Service Type combo is set to index 1 and the Select Plan combo box
|
|
# is set to index 1 and the "Import New" button is clicked
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
QtTest.QTest.mouseClick(self.form.import_as_new_button, QtCore.Qt.LeftButton)
|
|
# THEN: There should be 2 bible verse parse attempts
|
|
self.assertEqual(mock_bible_import.call_count, 2, '2 bible verses submitted for parsing')
|
|
|
|
def _create_mock_action(self, name, **kwargs):
|
|
"""
|
|
Create a fake action with some "real" attributes for Service Manager
|
|
"""
|
|
action = QtWidgets.QAction(self.service_manager)
|
|
action.setObjectName(name)
|
|
if kwargs.get('triggers'):
|
|
action.triggered.connect(kwargs.pop('triggers'))
|
|
self.service_manager.toolbar.actions[name] = action
|
|
return action
|
|
|
|
@skip("fails to run when executed with all other openlp tests. awaiting pytest fixtures to enable again")
|
|
def test_less_mocking_service_refreshed_when_refresh_button_clicked_test(self):
|
|
"""
|
|
Test that a service is refreshed when the "Refresh Service" button is clicked
|
|
"""
|
|
# GIVEN: An SelectPlanForm instance with airplane mode enabled, resources available,
|
|
# mocked out "on_new_service_clicked"
|
|
with patch('PyQt5.QtWidgets.QDialog.exec'), \
|
|
patch('openlp.plugins.planningcenter.forms.selectplanform.date') as mock_date:
|
|
# need to always return 9/29/2019 for date.today()
|
|
mock_date.today.return_value = date(2019, 9, 29)
|
|
mock_date.side_effect = lambda *args, **kw: date(*args, **kw)
|
|
# init ServiceManager
|
|
Registry().register('plugin_manager', MagicMock())
|
|
Registry().register('application', MagicMock())
|
|
Registry().register('renderer', MagicMock())
|
|
self.service_manager = ServiceManager()
|
|
self.service_manager.setup_ui(self.service_manager)
|
|
# init songs plugin
|
|
with patch('openlp.plugins.songs.lib.mediaitem.EditSongForm'), \
|
|
patch('openlp.plugins.custom.lib.mediaitem.EditCustomForm'), \
|
|
patch('openlp.core.lib.mediamanageritem.create_widget_action'), \
|
|
patch('openlp.core.widgets.toolbar.create_widget_action'):
|
|
# init songs plugin
|
|
songs_plugin = SongsPlugin()
|
|
song_media_item = SongMediaItem(None, songs_plugin)
|
|
song_media_item.search_text_edit = MagicMock()
|
|
song_media_item.settings_section = 'songs'
|
|
song_media_item.initialise()
|
|
# init custom plugin
|
|
custom_plugin = CustomPlugin()
|
|
CustomMediaItem(None, custom_plugin)
|
|
# init bible plugin
|
|
bible_plugin = BiblePlugin()
|
|
bible_media_item = BibleMediaItem(None, bible_plugin)
|
|
bible_media_item.build_display_results = MagicMock()
|
|
self.form.exec()
|
|
# WHEN:
|
|
# The Service Type combo is set to index 1 and "Import New" button is clicked
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
QtTest.QTest.mouseClick(self.form.import_as_new_button, QtCore.Qt.LeftButton)
|
|
# make changes to the now imported service items
|
|
# first, for serviceitem[0] update last_updated in xml_string and change "sweet" to "sublime"
|
|
old_match = re.search('modifiedDate="(.+?)Z*"',
|
|
self.service_manager.service_items[0]['service_item'].xml_version)
|
|
old_string = old_match.group(1)
|
|
now_string = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
|
|
self.service_manager.service_items[0]['service_item'].xml_version = \
|
|
self.service_manager.service_items[0]['service_item'].xml_version.replace(old_string, now_string)
|
|
self.service_manager.service_items[0]['service_item'].xml_version = \
|
|
self.service_manager.service_items[0]['service_item'].xml_version.replace("sweet", "sublime")
|
|
# second, add the word modified to the slide text for serviceitem[1]
|
|
self.service_manager.service_items[1]['service_item'].slides[0]['text'] = \
|
|
self.service_manager.service_items[1]['service_item'].slides[0]['text'].replace("Test", "Modified Test")
|
|
# third, delete serviceitems[2] and serviceitem[3]
|
|
del self.service_manager.service_items[3]
|
|
del self.service_manager.service_items[2]
|
|
# last, draw the form again and request refresh
|
|
self.form.exec()
|
|
self.form.service_type_combo_box.setCurrentIndex(1)
|
|
QtTest.QTest.mouseClick(self.form.update_existing_button, QtCore.Qt.LeftButton)
|
|
# THEN:
|
|
# There should be 4 service items added
|
|
self.assertEqual(len(self.service_manager.service_items), 5, '5 items should be in the ServiceManager')
|
|
# Amazon Grace should still include sublime
|
|
self.assertTrue('sublime' in self.service_manager.service_items[0]['service_item'].xml_version)
|
|
# Slides in service_item[1] should still contain the word "Modified"
|
|
self.assertTrue('Modified' in self.service_manager.service_items[1]['service_item'].slides[0]['text'])
|