From 922b65cf182d0d8216f358f896046a68dcaa195d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 18 Feb 2020 08:08:39 +0000 Subject: [PATCH] Fix appvoyer tests - we hope Migrate UI to pytest and fix up all tests. --- tests/conftest.py | 1 + .../openlp_core/ui/test_aboutform.py | 72 +- .../openlp_core/ui/test_advancedtab.py | 59 +- .../openlp_core/ui/test_firsttimeform.py | 476 +++--- .../ui/test_formattingtagscontroller.py | 133 +- .../openlp_core/ui/test_formattingtagsform.py | 98 +- tests/functional/openlp_core/ui/test_icons.py | 29 +- .../openlp_core/ui/test_mainwindow.py | 458 +++--- .../openlp_core/ui/test_servicemanager.py | 1305 +++++++++-------- .../openlp_core/ui/test_settingsform.py | 263 ++-- .../openlp_core/ui/test_slidecontroller.py | 38 +- .../openlp_core/ui/test_splashscreen.py | 26 +- tests/functional/openlp_core/ui/test_style.py | 5 +- .../openlp_core/ui/test_thememanager.py | 637 ++++---- .../openlp_core/widgets/test_views.py | 41 +- 15 files changed, 1802 insertions(+), 1839 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 562173459..76cef2723 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -71,6 +71,7 @@ def settings(qapp, registry): sets = Settings() sets.setValue('themes/global theme', 'my_theme') Registry().register('settings', sets) + Registry().register('application', qapp) qapp.settings = sets yield sets del sets diff --git a/tests/functional/openlp_core/ui/test_aboutform.py b/tests/functional/openlp_core/ui/test_aboutform.py index 7f333c188..b6ab52f6d 100644 --- a/tests/functional/openlp_core/ui/test_aboutform.py +++ b/tests/functional/openlp_core/ui/test_aboutform.py @@ -22,54 +22,52 @@ Package to test the openlp.core.ui.firsttimeform package. """ import datetime -from unittest import TestCase from unittest.mock import patch from openlp.core.ui.aboutform import AboutForm -from tests.helpers.testmixin import TestMixin -class TestAboutForm(TestCase, TestMixin): +@patch('openlp.core.ui.aboutform.webbrowser') +def test_on_contribute_button_clicked(mocked_webbrowser): + """ + Test that clicking on the "Volunteer" button opens a web page. + """ + # GIVEN: A new About dialog and a mocked out webbrowser module + about_form = AboutForm(None) - @patch('openlp.core.ui.aboutform.webbrowser') - def test_on_contribute_button_clicked(self, mocked_webbrowser): - """ - Test that clicking on the "Volunteer" button opens a web page. - """ - # GIVEN: A new About dialog and a mocked out webbrowser module - about_form = AboutForm(None) + # WHEN: The "Volunteer" button is "clicked" + about_form.on_contribute_button_clicked() - # WHEN: The "Volunteer" button is "clicked" - about_form.on_contribute_button_clicked() + # THEN: A web browser is opened + mocked_webbrowser.open_new.assert_called_with('http://openlp.org/contribute') - # THEN: A web browser is opened - mocked_webbrowser.open_new.assert_called_with('http://openlp.org/contribute') - @patch('openlp.core.ui.aboutform.get_version') - def test_about_form_build_number(self, mocked_get_version): - """ - Test that the build number is added to the about form - """ - # GIVEN: A mocked out get_version function - mocked_get_version.return_value = {'version': '3.1.5', 'build': '3000'} +@patch('openlp.core.ui.aboutform.get_version') +def test_about_form_build_number(mocked_get_version): + """ + Test that the build number is added to the about form + """ + # GIVEN: A mocked out get_version function + mocked_get_version.return_value = {'version': '3.1.5', 'build': '3000'} - # WHEN: The about form is created - about_form = AboutForm(None) + # WHEN: The about form is created + about_form = AboutForm(None) - # THEN: The build number should be in the text - assert 'OpenLP 3.1.5 build 3000' in about_form.about_text_edit.toPlainText(), \ - "The build number should be set correctly" + # THEN: The build number should be in the text + assert 'OpenLP 3.1.5 build 3000' in about_form.about_text_edit.toPlainText(), \ + "The build number should be set correctly" - def test_about_form_date(self): - """ - Test that the copyright date is included correctly - """ - # GIVEN: A correct application date - date_string = '2004-{year}'.format(year=datetime.date.today().year) - # WHEN: The about form is created - about_form = AboutForm(None) - about_text = about_form.about_text_edit.toPlainText() +def test_about_form_date(): + """ + Test that the copyright date is included correctly + """ + # GIVEN: A correct application date + date_string = '2004-{year}'.format(year=datetime.date.today().year) - # THEN: The date should be in the text twice. - assert about_text.count(date_string, 0) == 1, "The text string should be added twice to the license string" + # WHEN: The about form is created + about_form = AboutForm(None) + about_text = about_form.about_text_edit.toPlainText() + + # THEN: The date should be in the text twice. + assert about_text.count(date_string, 0) == 1, "The text string should be added twice to the license string" diff --git a/tests/functional/openlp_core/ui/test_advancedtab.py b/tests/functional/openlp_core/ui/test_advancedtab.py index 28b10aa16..74ecfc863 100644 --- a/tests/functional/openlp_core/ui/test_advancedtab.py +++ b/tests/functional/openlp_core/ui/test_advancedtab.py @@ -21,49 +21,36 @@ """ Package to test the openlp.core.ui.advancedtab package. """ -from unittest import TestCase - -from openlp.core.common.registry import Registry -from openlp.core.common.settings import Settings from openlp.core.ui.advancedtab import AdvancedTab from openlp.core.ui.settingsform import SettingsForm -from tests.helpers.testmixin import TestMixin -class TestAdvancedTab(TestCase, TestMixin): +def test_creation(settings): + """ + Test that Advanced Tab is created. + """ + # GIVEN: A new Advanced Tab + settings_form = SettingsForm(None) - def setUp(self): - """ - Set up a few things for the tests - """ - Registry.create() - Registry().register('settings', Settings()) + # WHEN: I create an advanced tab + advanced_tab = AdvancedTab(settings_form) - def test_creation(self): - """ - Test that Advanced Tab is created. - """ - # GIVEN: A new Advanced Tab - settings_form = SettingsForm(None) + # THEN: + assert "Advanced" == advanced_tab.tab_title, 'The tab title should be Advanced' - # WHEN: I create an advanced tab - advanced_tab = AdvancedTab(settings_form) - # THEN: - assert "Advanced" == advanced_tab.tab_title, 'The tab title should be Advanced' +def test_change_search_as_type(settings): + """ + Test that when search as type is changed custom and song configs are updated + """ + # GIVEN: A new Advanced Tab + settings_form = SettingsForm(None) + advanced_tab = AdvancedTab(settings_form) - def test_change_search_as_type(self): - """ - Test that when search as type is changed custom and song configs are updated - """ - # GIVEN: A new Advanced Tab - settings_form = SettingsForm(None) - advanced_tab = AdvancedTab(settings_form) + # WHEN: I change search as type check box + advanced_tab.on_search_as_type_check_box_changed(True) - # WHEN: I change search as type check box - advanced_tab.on_search_as_type_check_box_changed(True) - - # THEN: we should have two post save processed to run - assert 2 == len(settings_form.processes), 'Two post save processes should be created' - assert "songs_config_updated" in settings_form.processes, 'The songs plugin should be called' - assert "custom_config_updated" in settings_form.processes, 'The custom plugin should be called' + # THEN: we should have two post save processed to run + assert 2 == len(settings_form.processes), 'Two post save processes should be created' + assert "songs_config_updated" in settings_form.processes, 'The songs plugin should be called' + assert "custom_config_updated" in settings_form.processes, 'The custom plugin should be called' diff --git a/tests/functional/openlp_core/ui/test_firsttimeform.py b/tests/functional/openlp_core/ui/test_firsttimeform.py index 6f8221b22..c1a2d422a 100644 --- a/tests/functional/openlp_core/ui/test_firsttimeform.py +++ b/tests/functional/openlp_core/ui/test_firsttimeform.py @@ -21,17 +21,14 @@ """ Package to test the openlp.core.ui.firsttimeform package. """ -import os -import tempfile +import pytest from pathlib import Path -from unittest import TestCase, SkipTest from unittest.mock import MagicMock, call, patch, DEFAULT from PyQt5 import QtWidgets from openlp.core.common.registry import Registry from openlp.core.ui.firsttimeform import FirstTimeForm, ThemeListWidgetItem -from tests.helpers.testmixin import TestMixin INVALID_CONFIG = """ @@ -41,281 +38,280 @@ INVALID_CONFIG = """ } """ +sample_theme_data = {'file_name': 'BlueBurst.otz', 'sha256': 'sha_256_hash', + 'thumbnail': 'BlueBurst.png', 'title': 'Blue Burst'} -class TestThemeListWidgetItem(TestCase): + +@pytest.fixture() +def ftf_app(registry, qapp): + Registry().register('application', qapp) + + +@pytest.yield_fixture() +def download_env(registry): + download_worker_patcher = patch('openlp.core.ui.firsttimeform.DownloadWorker') + run_thread_patcher = patch('openlp.core.ui.firsttimeform.run_thread') + mocked_download_worker = download_worker_patcher.start() + mocked_run_thread = run_thread_patcher.start() + yield mocked_download_worker, mocked_run_thread + download_worker_patcher.stop() + run_thread_patcher.stop() + + +def test_init_sample_data(download_env): """ - Test the :class:`ThemeListWidgetItem` class + Test that the theme data is loaded correctly in to a ThemeListWidgetItem object when instantiated """ + # GIVEN: A sample theme dictionary object + # WHEN: Creating an instance of `ThemeListWidgetItem` + mocked_download_worker = download_env[0] + instance = ThemeListWidgetItem('url', sample_theme_data, MagicMock()) - def setUp(self): - self.sample_theme_data = {'file_name': 'BlueBurst.otz', 'sha256': 'sha_256_hash', - 'thumbnail': 'BlueBurst.png', 'title': 'Blue Burst'} - download_worker_patcher = patch('openlp.core.ui.firsttimeform.DownloadWorker') - self.addCleanup(download_worker_patcher.stop) - self.mocked_download_worker = download_worker_patcher.start() - run_thread_patcher = patch('openlp.core.ui.firsttimeform.run_thread') - self.addCleanup(run_thread_patcher.stop) - self.mocked_run_thread = run_thread_patcher.start() - - def test_init_sample_data(self): - """ - Test that the theme data is loaded correctly in to a ThemeListWidgetItem object when instantiated - """ - # GIVEN: A sample theme dictionary object - # WHEN: Creating an instance of `ThemeListWidgetItem` - instance = ThemeListWidgetItem('url', self.sample_theme_data, MagicMock()) - - # THEN: The data should have been set correctly - assert instance.file_name == 'BlueBurst.otz' - assert instance.sha256 == 'sha_256_hash' - assert instance.text() == 'Blue Burst' - assert instance.toolTip() == 'Blue Burst' - self.mocked_download_worker.assert_called_once_with('url', 'BlueBurst.png') - - def test_init_download_worker(self): - """ - Test that the `DownloadWorker` worker is set up correctly and that the thread is started. - """ - # GIVEN: A sample theme dictionary object - mocked_ftw = MagicMock(spec=FirstTimeForm) - mocked_ftw.thumbnail_download_threads = [] - - # WHEN: Creating an instance of `ThemeListWidgetItem` - instance = ThemeListWidgetItem('url', self.sample_theme_data, mocked_ftw) - - # THEN: The `DownloadWorker` should have been set up with the appropriate data - self.mocked_download_worker.assert_called_once_with('url', 'BlueBurst.png') - self.mocked_download_worker.download_failed.connect.called_once_with(instance._on_download_failed()) - self.mocked_download_worker.download_succeeded.connect.called_once_with(instance._on_thumbnail_downloaded) - self.mocked_run_thread.assert_called_once_with( - self.mocked_download_worker(), 'thumbnail_download_BlueBurst.png') - assert mocked_ftw.thumbnail_download_threads == ['thumbnail_download_BlueBurst.png'] + # THEN: The data should have been set correctly + assert instance.file_name == 'BlueBurst.otz' + assert instance.sha256 == 'sha_256_hash' + assert instance.text() == 'Blue Burst' + assert instance.toolTip() == 'Blue Burst' + mocked_download_worker.assert_called_once_with('url', 'BlueBurst.png') -class TestFirstTimeForm(TestCase, TestMixin): +def test_init_download_worker(download_env): + """ + Test that the `DownloadWorker` worker is set up correctly and that the thread is started. + """ + # GIVEN: A sample theme dictionary object + mocked_download_worker = download_env[0] + mocked_run_thread = download_env[1] + mocked_ftw = MagicMock(spec=FirstTimeForm) + mocked_ftw.thumbnail_download_threads = [] - def setUp(self): - self.setup_application() - self.app.setApplicationVersion('0.0') - # Set up a fake "set_normal_cursor" method since we're not dealing with an actual OpenLP application object - self.app.set_normal_cursor = lambda: None - self.app.process_events = lambda: None - Registry.create() - Registry().register('application', self.app) - Registry().register('settings', MagicMock) - self.tempfile = os.path.join(tempfile.gettempdir(), 'testfile') + # WHEN: Creating an instance of `ThemeListWidgetItem` + instance = ThemeListWidgetItem('url', sample_theme_data, mocked_ftw) - def tearDown(self): - if os.path.isfile(self.tempfile): - os.remove(self.tempfile) + # THEN: The `DownloadWorker` should have been set up with the appropriate data + mocked_download_worker.assert_called_once_with('url', 'BlueBurst.png') + mocked_download_worker.download_failed.connect.called_once_with(instance._on_download_failed()) + mocked_download_worker.download_succeeded.connect.called_once_with(instance._on_thumbnail_downloaded) + mocked_run_thread.assert_called_once_with(mocked_download_worker(), 'thumbnail_download_BlueBurst.png') + assert mocked_ftw.thumbnail_download_threads == ['thumbnail_download_BlueBurst.png'] - def test_initialise(self): - """ - Test if we can intialise the FirstTimeForm - """ - # GIVEN: A First Time Wizard and an expected screen object - frw = FirstTimeForm(None) - expected_screens = MagicMock() - # WHEN: The First Time Wizard is initialised - frw.initialize(expected_screens) +def test_firsttimeform_initialise(): + """ + Test if we can intialise the FirstTimeForm + """ + # GIVEN: A First Time Wizard and an expected screen object + frw = FirstTimeForm(None) + expected_screens = MagicMock() - # THEN: The screens should be set up, and the default values initialised - assert expected_screens == frw.screens, 'The screens should be correct' - assert frw.has_web_access is True, 'The default value of self.web_access should be True' - assert [] == frw.thumbnail_download_threads, 'The list of threads should be empty' - assert frw.has_run_wizard is False, 'has_run_wizard should be False' + # WHEN: The First Time Wizard is initialised + frw.initialize(expected_screens) - @patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.exec') - def test_exec(self, mocked_qwizard_exec): + # THEN: The screens should be set up, and the default values initialised + assert expected_screens == frw.screens, 'The screens should be correct' + assert frw.has_web_access is True, 'The default value of self.web_access should be True' + assert [] == frw.thumbnail_download_threads, 'The list of threads should be empty' + assert frw.has_run_wizard is False, 'has_run_wizard should be False' - # GIVEN: An instance of FirstTimeForm - frw = FirstTimeForm(None) - with patch.object(frw, 'set_defaults') as mocked_set_defaults: - # WHEN: exec is called - frw.exec() +@patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.exec') +def test_firsttimeform_exec(mocked_qwizard_exec): - # THEN: The wizard should be reset and the exec methon on the super class should have been called - mocked_set_defaults.assert_called_once() - mocked_qwizard_exec.assert_called_once() + # GIVEN: An instance of FirstTimeForm + frw = FirstTimeForm(None) + with patch.object(frw, 'set_defaults') as mocked_set_defaults: - @SkipTest - def test_set_defaults(self): - """ - Test that the default values are set when set_defaults() is run - """ - # GIVEN: An initialised FRW and a whole lot of stuff mocked out - frw = FirstTimeForm(None) - frw.initialize(MagicMock()) - mocked_settings = MagicMock() - mocked_settings.value.side_effect = lambda key: {'core/has run wizard': False}[key] - with patch.object(frw, 'restart') as mocked_restart, \ - patch.object(frw, 'currentIdChanged') as mocked_currentIdChanged, \ - patch.object(frw, 'theme_combo_box') as mocked_theme_combo_box, \ - patch.object(frw, 'songs_check_box') as mocked_songs_check_box, \ - patch.object(Registry, 'register_function') as mocked_register_function, \ - patch('openlp.core.ui.firsttimeform.Settings', return_value=mocked_settings), \ - patch('openlp.core.ui.firsttimeform.gettempdir', return_value='temp') as mocked_gettempdir, \ - patch('openlp.core.ui.firsttimeform.create_paths') as mocked_create_paths, \ - patch.object(frw.application, 'set_normal_cursor'): - mocked_theme_manager = MagicMock() - Registry().register('theme_manager', mocked_theme_manager) + # WHEN: exec is called + frw.exec() - # WHEN: The set_defaults() method is run - frw.set_defaults() + # THEN: The wizard should be reset and the exec methon on the super class should have been called + mocked_set_defaults.assert_called_once() + mocked_qwizard_exec.assert_called_once() - # THEN: The default values should have been set - mocked_restart.assert_called_once() - assert 'https://get.openlp.org/ftw/' == frw.web, 'The default URL should be set' - mocked_currentIdChanged.connect.assert_called_once_with(frw.on_current_id_changed) - mocked_register_function.assert_called_once_with('config_screen_changed', frw.screen_selection_widget.load) - mocked_settings.value.assert_has_calls([call('core/has run wizard')]) - mocked_gettempdir.assert_called_once() - mocked_create_paths.assert_called_once_with(Path('temp', 'openlp')) - mocked_theme_combo_box.clear.assert_called_once() - mocked_theme_manager.assert_not_called() - mocked_songs_check_box.assert_not_called() - @patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.accept') - def test_accept_method(self, mocked_qwizard_accept, *args): - """ - Test the FirstTimeForm.accept method - """ - # GIVEN: An instance of FirstTimeForm - frw = FirstTimeForm(None) - with patch.object(frw, '_set_plugin_status') as mocked_set_plugin_status, \ - patch.multiple(frw, songs_check_box=DEFAULT, bible_check_box=DEFAULT, presentation_check_box=DEFAULT, - image_check_box=DEFAULT, media_check_box=DEFAULT, custom_check_box=DEFAULT, - song_usage_check_box=DEFAULT, alert_check_box=DEFAULT) as mocked_check_boxes, \ - patch.object(frw, 'screen_selection_widget') as mocked_screen_selection_widget: +def test_set_defaults(mock_settings, ftf_app): + """ + Test that the default values are set when set_defaults() is run + """ + # GIVEN: An initialised FRW and a whole lot of stuff mocked out + frw = FirstTimeForm(None) + frw.initialize(MagicMock()) + mocked_settings = MagicMock() + mocked_settings.value.side_effect = lambda key: {'core/has run wizard': False}[key] + with patch.object(frw, 'restart') as mocked_restart, \ + patch.object(frw, 'currentIdChanged') as mocked_currentIdChanged, \ + patch.object(frw, 'theme_combo_box') as mocked_theme_combo_box, \ + patch.object(frw, 'songs_check_box') as mocked_songs_check_box, \ + patch.object(Registry, 'register_function') as mocked_register_function, \ + patch('openlp.core.ui.firsttimeform.gettempdir', return_value='temp') as mocked_gettempdir, \ + patch('openlp.core.ui.firsttimeform.create_paths') as mocked_create_paths, \ + patch.object(frw.application, 'set_normal_cursor'): + mocked_theme_manager = MagicMock() + Registry().register('theme_manager', mocked_theme_manager) + Registry().remove('settings') + Registry().register('settings', mocked_settings) - # WHEN: Calling accept - frw.accept() + # WHEN: The set_defaults() method is run + frw.set_defaults() - # THEN: The selected plugins should be enabled, the screen selection saved and the super method called - mocked_set_plugin_status.assert_has_calls([ - call(mocked_check_boxes['songs_check_box'], 'songs/status'), - call(mocked_check_boxes['bible_check_box'], 'bibles/status'), - call(mocked_check_boxes['presentation_check_box'], 'presentations/status'), - call(mocked_check_boxes['image_check_box'], 'images/status'), - call(mocked_check_boxes['media_check_box'], 'media/status'), - call(mocked_check_boxes['custom_check_box'], 'custom/status'), - call(mocked_check_boxes['song_usage_check_box'], 'songusage/status'), - call(mocked_check_boxes['alert_check_box'], 'alerts/status')]) - mocked_screen_selection_widget.save.assert_called_once() - mocked_qwizard_accept.assert_called_once() + # THEN: The default values should have been set + mocked_restart.assert_called_once() + assert 'https://get.openlp.org/ftw/' == frw.web, 'The default URL should be set' + mocked_currentIdChanged.connect.assert_called_once_with(frw.on_current_id_changed) + mocked_register_function.assert_called_once_with('config_screen_changed', frw.screen_selection_widget.load) + mocked_settings.value.assert_has_calls([call('core/has run wizard')]) + mocked_gettempdir.assert_called_once() + mocked_create_paths.assert_called_once_with(Path('temp', 'openlp')) + mocked_theme_combo_box.clear.assert_called_once() + mocked_theme_manager.assert_not_called() + mocked_songs_check_box.assert_not_called() - def test_accept_method_theme_not_selected(self): - """ - Test the FirstTimeForm.accept method when there is no default theme selected - """ - # GIVEN: An instance of FirstTimeForm - mocked_settings = Registry().get('settings') - frw = FirstTimeForm(None) - with patch.object(frw, '_set_plugin_status'), patch.object(frw, 'screen_selection_widget'), \ - patch.object(frw, 'theme_combo_box', **{'currentIndex.return_value': -1}): - # WHEN: Calling accept and the currentIndex method of the theme_combo_box returns -1 - frw.accept() +@patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.accept') +def test_accept_method(mocked_qwizard_accept, registry, *args): + """ + Test the FirstTimeForm.accept method + """ + # GIVEN: An instance of FirstTimeForm + frw = FirstTimeForm(None) + with patch.object(frw, '_set_plugin_status') as mocked_set_plugin_status, \ + patch.multiple(frw, songs_check_box=DEFAULT, bible_check_box=DEFAULT, presentation_check_box=DEFAULT, + image_check_box=DEFAULT, media_check_box=DEFAULT, custom_check_box=DEFAULT, + song_usage_check_box=DEFAULT, alert_check_box=DEFAULT) as mocked_check_boxes, \ + patch.object(frw, 'screen_selection_widget') as mocked_screen_selection_widget: - # THEN: OpenLP should not try to save a theme name - mocked_settings().setValue.assert_not_called() + # WHEN: Calling accept + frw.accept() - @patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.reject') - @patch('openlp.core.ui.firsttimeform.time') - @patch('openlp.core.ui.firsttimeform.get_thread_worker') - @patch('openlp.core.ui.firsttimeform.is_thread_finished') - def test_reject_method( - self, mocked_is_thread_finished, mocked_get_thread_worker, mocked_time, mocked_qwizard_reject): - """ - Test that the reject method shuts down the threads correctly - """ - # GIVEN: A FRW, some mocked threads and workers (that isn't quite done) and other mocked stuff - mocked_worker = MagicMock() - mocked_get_thread_worker.return_value = mocked_worker - mocked_is_thread_finished.side_effect = [False, True] - frw = FirstTimeForm(None) - frw.initialize(MagicMock()) - frw.thumbnail_download_threads = ['test_thread'] - with patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: + # THEN: The selected plugins should be enabled, the screen selection saved and the super method called + mocked_set_plugin_status.assert_has_calls([ + call(mocked_check_boxes['songs_check_box'], 'songs/status'), + call(mocked_check_boxes['bible_check_box'], 'bibles/status'), + call(mocked_check_boxes['presentation_check_box'], 'presentations/status'), + call(mocked_check_boxes['image_check_box'], 'images/status'), + call(mocked_check_boxes['media_check_box'], 'media/status'), + call(mocked_check_boxes['custom_check_box'], 'custom/status'), + call(mocked_check_boxes['song_usage_check_box'], 'songusage/status'), + call(mocked_check_boxes['alert_check_box'], 'alerts/status')]) + mocked_screen_selection_widget.save.assert_called_once() + mocked_qwizard_accept.assert_called_once() - # WHEN: the reject method is called - frw.reject() - # THEN: The right things should be called in the right order - mocked_get_thread_worker.assert_called_once_with('test_thread') - mocked_worker.cancel_download.assert_called_once() - mocked_is_thread_finished.assert_called_with('test_thread') - assert mocked_is_thread_finished.call_count == 2, 'isRunning() should have been called twice' - mocked_time.sleep.assert_called_once_with(0.1) - mocked_set_normal_cursor.assert_called_once() - mocked_qwizard_reject.assert_called_once() +def test_accept_method_theme_not_selected(mock_settings): + """ + Test the FirstTimeForm.accept method when there is no default theme selected + """ + # GIVEN: An instance of FirstTimeForm + mock_settings = Registry().get('settings') + frw = FirstTimeForm(None) + with patch.object(frw, '_set_plugin_status'), patch.object(frw, 'screen_selection_widget'), \ + patch.object(frw, 'theme_combo_box', **{'currentIndex.return_value': -1}): - @patch('openlp.core.ui.firsttimeform.ProxyDialog') - def test_on_custom_button_clicked(self, mocked_proxy_dialog): - """ - Test _on_custom_button when it is called whe the 'internet settings' (CustomButton1) button is not clicked. - """ - # GIVEN: An instance of the FirstTimeForm - frw = FirstTimeForm(None) + # WHEN: Calling accept and the currentIndex method of the theme_combo_box returns -1 + frw.accept() - # WHEN: Calling _on_custom_button_clicked with a different button to the 'internet settings button. - frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton2) + # THEN: OpenLP should not try to save a theme name + mock_settings().setValue.assert_not_called() - # THEN: The ProxyDialog should not be shown. - mocked_proxy_dialog.assert_not_called() - @patch('openlp.core.ui.firsttimeform.ProxyDialog') - def test_on_custom_button_clicked_internet_settings(self, mocked_proxy_dialog): - """ - Test _on_custom_button when it is called when the 'internet settings' (CustomButton1) button is clicked. - """ - # GIVEN: An instance of the FirstTimeForm - frw = FirstTimeForm(None) +@patch('openlp.core.ui.firsttimeform.QtWidgets.QWizard.reject') +@patch('openlp.core.ui.firsttimeform.time') +@patch('openlp.core.ui.firsttimeform.get_thread_worker') +@patch('openlp.core.ui.firsttimeform.is_thread_finished') +def test_reject_method(mocked_is_thread_finished, mocked_get_thread_worker, + mocked_time, mocked_qwizard_reject, ftf_app): + """ + Test that the reject method shuts down the threads correctly + """ + # GIVEN: A FRW, some mocked threads and workers (that isn't quite done) and other mocked stuff + mocked_worker = MagicMock() + mocked_get_thread_worker.return_value = mocked_worker + mocked_is_thread_finished.side_effect = [False, True] + frw = FirstTimeForm(None) + frw.initialize(MagicMock()) + frw.thumbnail_download_threads = ['test_thread'] + with patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: - # WHEN: Calling _on_custom_button_clicked with the constant for the 'internet settings' button (CustomButton1) - frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton1) + # WHEN: the reject method is called + frw.reject() - # THEN: The ProxyDialog should be shown. - mocked_proxy_dialog.assert_called_with(frw) - mocked_proxy_dialog().retranslate_ui.assert_called_once() - mocked_proxy_dialog().exec.assert_called_once() + # THEN: The right things should be called in the right order + mocked_get_thread_worker.assert_called_once_with('test_thread') + mocked_worker.cancel_download.assert_called_once() + mocked_is_thread_finished.assert_called_with('test_thread') + assert mocked_is_thread_finished.call_count == 2, 'isRunning() should have been called twice' + mocked_time.sleep.assert_called_once_with(0.1) + mocked_set_normal_cursor.assert_called_once() + mocked_qwizard_reject.assert_called_once() - @patch('openlp.core.ui.firsttimeform.critical_error_message_box') - def test__parse_config_invalid_config(self, mocked_critical_error_message_box): - """ - Test `FirstTimeForm._parse_config` when called with invalid data - """ - # GIVEN: An instance of `FirstTimeForm` - first_time_form = FirstTimeForm(None) - # WHEN: Calling _parse_config with a string containing invalid data - result = first_time_form._parse_config(INVALID_CONFIG) +@patch('openlp.core.ui.firsttimeform.ProxyDialog') +def test_on_custom_button_clicked(mocked_proxy_dialog): + """ + Test _on_custom_button when it is called whe the 'internet settings' (CustomButton1) button is not clicked. + """ + # GIVEN: An instance of the FirstTimeForm + frw = FirstTimeForm(None) - # THEN: _parse_data should return False and the user should have should have been informed. - assert result is False - mocked_critical_error_message_box.assert_called_once() + # WHEN: Calling _on_custom_button_clicked with a different button to the 'internet settings button. + frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton2) - @patch('openlp.core.ui.firsttimeform.get_web_page') - @patch('openlp.core.ui.firsttimeform.QtWidgets.QMessageBox') - def test_network_error(self, mocked_message_box, mocked_get_web_page): - """ - Test we catch a network error in First Time Wizard - bug 1409627 - """ - # GIVEN: Initial setup and mocks - first_time_form = FirstTimeForm(None) - first_time_form.initialize(MagicMock()) - mocked_get_web_page.side_effect = ConnectionError('') - mocked_message_box.Ok = 'OK' + # THEN: The ProxyDialog should not be shown. + mocked_proxy_dialog.assert_not_called() - # WHEN: the First Time Wizard calls to get the initial configuration - first_time_form._download_index() - # THEN: the critical_error_message_box should have been called - mocked_message_box.critical.assert_called_once_with( - first_time_form, 'Network Error', - 'There was a network error attempting to connect to retrieve initial configuration information', 'OK') +@patch('openlp.core.ui.firsttimeform.ProxyDialog') +def test_on_custom_button_clicked_internet_settings(mocked_proxy_dialog): + """ + Test _on_custom_button when it is called when the 'internet settings' (CustomButton1) button is clicked. + """ + # GIVEN: An instance of the FirstTimeForm + frw = FirstTimeForm(None) + + # WHEN: Calling _on_custom_button_clicked with the constant for the 'internet settings' button (CustomButton1) + frw._on_custom_button_clicked(QtWidgets.QWizard.CustomButton1) + + # THEN: The ProxyDialog should be shown. + mocked_proxy_dialog.assert_called_with(frw) + mocked_proxy_dialog().retranslate_ui.assert_called_once() + mocked_proxy_dialog().exec.assert_called_once() + + +@patch('openlp.core.ui.firsttimeform.critical_error_message_box') +def test__parse_config_invalid_config(mocked_critical_error_message_box): + """ + Test `FirstTimeForm._parse_config` when called with invalid data + """ + # GIVEN: An instance of `FirstTimeForm` + first_time_form = FirstTimeForm(None) + + # WHEN: Calling _parse_config with a string containing invalid data + result = first_time_form._parse_config(INVALID_CONFIG) + + # THEN: _parse_data should return False and the user should have should have been informed. + assert result is False + mocked_critical_error_message_box.assert_called_once() + + +@patch('openlp.core.ui.firsttimeform.get_web_page') +@patch('openlp.core.ui.firsttimeform.QtWidgets.QMessageBox') +def test_network_error(mocked_message_box, mocked_get_web_page, ftf_app): + """ + Test we catch a network error in First Time Wizard - bug 1409627 + """ + # GIVEN: Initial setup and mocks + first_time_form = FirstTimeForm(None) + first_time_form.initialize(MagicMock()) + mocked_get_web_page.side_effect = ConnectionError('') + mocked_message_box.Ok = 'OK' + + # WHEN: the First Time Wizard calls to get the initial configuration + first_time_form._download_index() + + # THEN: the critical_error_message_box should have been called + mocked_message_box.critical.assert_called_once_with( + first_time_form, 'Network Error', + 'There was a network error attempting to connect to retrieve initial configuration information', 'OK') def test_accept_method_theme_selected(mock_settings): diff --git a/tests/functional/openlp_core/ui/test_formattingtagscontroller.py b/tests/functional/openlp_core/ui/test_formattingtagscontroller.py index 5354b9924..c1fb43ca4 100644 --- a/tests/functional/openlp_core/ui/test_formattingtagscontroller.py +++ b/tests/functional/openlp_core/ui/test_formattingtagscontroller.py @@ -21,85 +21,88 @@ """ Package to test the openlp.core.ui.formattingtagscontroller package. """ -from unittest import TestCase +import pytest from openlp.core.ui.formattingtagcontroller import FormattingTagController -class TestFormattingTagController(TestCase): +@pytest.fixture() +def services(registry, qapp): + return FormattingTagController() - def setUp(self): - self.services = FormattingTagController() - def test_strip(self): - """ - Test that the _strip strips the correct chars - """ - # GIVEN: An instance of the Formatting Tag Form and a string containing a tag - tag = '{tag}' +def test_strip(services): + """ + Test that the _strip strips the correct chars + """ + # GIVEN: An instance of the Formatting Tag Form and a string containing a tag + tag = '{tag}' - # WHEN: Calling _strip - result = self.services._strip(tag) + # WHEN: Calling _strip + result = services._strip(tag) - # THEN: The tag should be returned with the wrappers removed. - assert result == 'tag', 'FormattingTagForm._strip should return u\'tag\' when called with u\'{tag}\'' + # THEN: The tag should be returned with the wrappers removed. + assert result == 'tag', 'FormattingTagForm._strip should return u\'tag\' when called with u\'{tag}\'' - def test_end_tag_changed_processes_correctly(self): - """ - Test that the end html tags are generated correctly - """ - # GIVEN: A list of start , end tags and error messages - tests = [] - test = {'start': '', 'end': None, 'gen': '', 'valid': None} - tests.append(test) - test = {'start': '', 'end': '', 'gen': None, 'valid': None} - tests.append(test) - test = {'start': '', 'end': '', 'gen': None, - 'valid': 'End tag does not match end tag for start tag '} - tests.append(test) - # WHEN: Testing each one of them in turn - for test in tests: - error, result = self.services.end_tag_changed(test['start'], test['end']) +def test_end_tag_changed_processes_correctly(services): + """ + Test that the end html tags are generated correctly + """ + # GIVEN: A list of start , end tags and error messages + tests = [] + test = {'start': '', 'end': None, 'gen': '', 'valid': None} + tests.append(test) + test = {'start': '', 'end': '', 'gen': None, 'valid': None} + tests.append(test) + test = {'start': '', 'end': '', 'gen': None, + 'valid': 'End tag does not match end tag for start tag '} + tests.append(test) - # THEN: The result should match the predetermined value. - assert result == test['gen'], \ - 'Function should handle end tag correctly : %s and %s for %s ' % (test['gen'], result, test['start']) - assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error + # WHEN: Testing each one of them in turn + for test in tests: + error, result = services.end_tag_changed(test['start'], test['end']) - def test_start_tag_changed_processes_correctly(self): - """ - Test that the end html tags are generated correctly - """ - # GIVEN: A list of start , end tags and error messages - tests = [] - test = {'start': '', 'end': '', 'gen': '', 'valid': None} - tests.append(test) - test = {'start': '', 'end': '', 'gen': None, 'valid': None} - tests.append(test) - test = {'start': 'superfly', 'end': '', 'gen': None, 'valid': 'Start tag superfly is not valid HTML'} - tests.append(test) + # THEN: The result should match the predetermined value. + assert result == test['gen'], \ + 'Function should handle end tag correctly : %s and %s for %s ' % (test['gen'], result, test['start']) + assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error - # WHEN: Testing each one of them in turn - for test in tests: - error, result = self.services.start_tag_changed(test['start'], test['end']) - # THEN: The result should match the predetermined value. - assert result == test['gen'], \ - 'Function should handle end tag correctly : %s and %s ' % (test['gen'], result) - assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error +def test_start_tag_changed_processes_correctly(services): + """ + Test that the end html tags are generated correctly + """ + # GIVEN: A list of start , end tags and error messages + tests = [] + test = {'start': '', 'end': '', 'gen': '', 'valid': None} + tests.append(test) + test = {'start': '', 'end': '', 'gen': None, 'valid': None} + tests.append(test) + test = {'start': 'superfly', 'end': '', 'gen': None, 'valid': 'Start tag superfly is not valid HTML'} + tests.append(test) - def test_start_html_to_end_html(self): - """ - Test that the end html tags are generated correctly - """ - # GIVEN: A list of valid and invalid tags - tests = {'': '', '': '', 'superfly': '', '': None, - '': ''} + # WHEN: Testing each one of them in turn + for test in tests: + error, result = services.start_tag_changed(test['start'], test['end']) - # WHEN: Testing each one of them - for test1, test2 in tests.items(): - result = self.services.start_html_to_end_html(test1) + # THEN: The result should match the predetermined value. + assert result == test['gen'], \ + 'Function should handle end tag correctly : %s and %s ' % (test['gen'], result) + assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error - # THEN: The result should match the predetermined value. - assert result == test2, 'Calculated end tag should be valid: %s and %s = %s' % (test1, test2, result) + +def test_start_html_to_end_html(services): + """ + Test that the end html tags are generated correctly + """ + # GIVEN: A list of valid and invalid tags + tests = {'': '', '': '', 'superfly': '', '': None, + '': ''} + + # WHEN: Testing each one of them + for test1, test2 in tests.items(): + result = services.start_html_to_end_html(test1) + + # THEN: The result should match the predetermined value. + assert result == test2, 'Calculated end tag should be valid: %s and %s = %s' % (test1, test2, result) diff --git a/tests/functional/openlp_core/ui/test_formattingtagsform.py b/tests/functional/openlp_core/ui/test_formattingtagsform.py index 8a32c9006..bb997a366 100644 --- a/tests/functional/openlp_core/ui/test_formattingtagsform.py +++ b/tests/functional/openlp_core/ui/test_formattingtagsform.py @@ -21,69 +21,63 @@ """ Package to test the openlp.core.ui.formattingtagsform package. """ -from unittest import TestCase +import pytest from unittest.mock import MagicMock, call, patch from openlp.core.ui.formattingtagform import FormattingTagForm -class TestFormattingTagForm(TestCase): +@pytest.yield_fixture() +def tagform_env(registry): + setup_patcher = patch('openlp.core.ui.formattingtagform.FormattingTagForm._setup') + mocked_setup_patcher = setup_patcher.start() + yield mocked_setup_patcher + setup_patcher.stop() - def setUp(self): - """ - Mock out stuff for all the tests - """ - self.setup_patcher = patch('openlp.core.ui.formattingtagform.FormattingTagForm._setup') - self.setup_patcher.start() - def tearDown(self): - """ - Remove the mocks - """ - self.setup_patcher.stop() +def test_on_row_selected(tagform_env): + """ + Test that the appropriate actions are preformed when on_row_selected is called + """ + # GIVEN: An instance of the Formatting Tag Form and a mocked delete_button + form = FormattingTagForm(None) + form.delete_button = MagicMock() - def test_on_row_selected(self): - """ - Test that the appropriate actions are preformed when on_row_selected is called - """ - # GIVEN: An instance of the Formatting Tag Form and a mocked delete_button - form = FormattingTagForm(None) - form.delete_button = MagicMock() + # WHEN: on_row_selected is called + form.on_row_selected() - # WHEN: on_row_selected is called - form.on_row_selected() + # THEN: setEnabled and should have been called on delete_button + form.delete_button.setEnabled.assert_called_with(True) - # THEN: setEnabled and should have been called on delete_button - form.delete_button.setEnabled.assert_called_with(True) - def test_on_new_clicked(self): - """ - Test that clicking the Add a new tag button does the right thing - """ +def test_on_new_clicked(tagform_env): + """ + Test that clicking the Add a new tag button does the right thing + """ - # GIVEN: A formatting tag form and a mocked out tag table widget - form = FormattingTagForm(None) - form.tag_table_widget = MagicMock() - row_count = 5 - form.tag_table_widget.rowCount.return_value = row_count + # GIVEN: A formatting tag form and a mocked out tag table widget + form = FormattingTagForm(None) + form.tag_table_widget = MagicMock() + row_count = 5 + form.tag_table_widget.rowCount.return_value = row_count - # WHEN: on_new_clicked is run (i.e. the Add new button was clicked) - with patch('openlp.core.ui.formattingtagform.QtWidgets.QTableWidgetItem') as MockedQTableWidgetItem: - mocked_table_widget = MagicMock() - MockedQTableWidgetItem.return_value = mocked_table_widget - form.on_new_clicked() + # WHEN: on_new_clicked is run (i.e. the Add new button was clicked) + with patch('openlp.core.ui.formattingtagform.QtWidgets.QTableWidgetItem') as MockedQTableWidgetItem: + mocked_table_widget = MagicMock() + MockedQTableWidgetItem.return_value = mocked_table_widget + form.on_new_clicked() - # THEN: A new row should be added to the table - form.tag_table_widget.rowCount.assert_called_with() - form.tag_table_widget.insertRow.assert_called_with(row_count) - expected_set_item_calls = [ - call(row_count, 0, mocked_table_widget), - call(row_count, 1, mocked_table_widget), - call(row_count, 2, mocked_table_widget), - call(row_count, 3, mocked_table_widget) - ] - assert expected_set_item_calls == form.tag_table_widget.setItem.call_args_list, \ - 'setItem should have been called correctly' - form.tag_table_widget.resizeRowsToContents.assert_called_with() - form.tag_table_widget.scrollToBottom.assert_called_with() - form.tag_table_widget.selectRow.assert_called_with(row_count) + # THEN: A new row should be added to the table + form.tag_table_widget.rowCount.assert_called_with() + form.tag_table_widget.insertRow.assert_called_with(row_count) + expected_set_item_calls = [ + call(row_count, 0, mocked_table_widget), + call(row_count, 1, mocked_table_widget), + call(row_count, 2, mocked_table_widget), + call(row_count, 3, mocked_table_widget) + ] + assert expected_set_item_calls == form.tag_table_widget.setItem.call_args_list, \ + 'setItem should have been called correctly' + form.tag_table_widget.resizeRowsToContents.assert_called_with() + form.tag_table_widget.scrollToBottom.assert_called_with() + form.tag_table_widget.selectRow.assert_called_with(row_count) diff --git a/tests/functional/openlp_core/ui/test_icons.py b/tests/functional/openlp_core/ui/test_icons.py index 22f1c98dd..7ecde1105 100644 --- a/tests/functional/openlp_core/ui/test_icons.py +++ b/tests/functional/openlp_core/ui/test_icons.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - ########################################################################## # OpenLP - Open Source Lyrics Projection # # ---------------------------------------------------------------------- # @@ -21,28 +20,24 @@ """ Package to test the openlp.core.ui.icons package. """ -from unittest import TestCase from unittest.mock import patch from PyQt5 import QtGui from openlp.core.ui.icons import UiIcons -from tests.helpers.testmixin import TestMixin -class TestIcons(TestCase, TestMixin): +@patch('openlp.core.ui.icons.UiIcons.__init__', return_value=None) +def test_simple_icon(_): + # GIVEN: an basic set of icons + icons = UiIcons() + icon_list = { + 'active': {'icon': 'fa.child'} - @patch('openlp.core.ui.icons.UiIcons.__init__', return_value=None) - def test_simple_icon(self, _): - # GIVEN: an basic set of icons - icons = UiIcons() - icon_list = { - 'active': {'icon': 'fa.child'} + } - } - - icons.load_icons(icon_list) - # WHEN: I use the icons - icon_active = UiIcons().active - # THEN: I should have an icon - assert isinstance(icon_active, QtGui.QIcon) + icons.load_icons(icon_list) + # WHEN: I use the icons + icon_active = UiIcons().active + # THEN: I should have an icon + assert isinstance(icon_active, QtGui.QIcon) diff --git a/tests/functional/openlp_core/ui/test_mainwindow.py b/tests/functional/openlp_core/ui/test_mainwindow.py index 6ba542889..a931340e0 100644 --- a/tests/functional/openlp_core/ui/test_mainwindow.py +++ b/tests/functional/openlp_core/ui/test_mainwindow.py @@ -22,293 +22,291 @@ Package to test openlp.core.ui.mainwindow package. """ import os +import pytest from pathlib import Path -from unittest import TestCase from unittest.mock import MagicMock, patch from PyQt5 import QtCore, QtWidgets -from openlp.core.state import State from openlp.core.common.i18n import UiStrings from openlp.core.common.registry import Registry -from openlp.core.common.settings import Settings from openlp.core.display.screens import ScreenList from openlp.core.ui.mainwindow import MainWindow -from tests.helpers.testmixin import TestMixin from tests.utils.constants import TEST_RESOURCES_PATH, RESOURCE_PATH -class TestMainWindow(TestCase, TestMixin): +def _create_mock_action(parent, name, **kwargs): """ - Test the main window + Create a fake action with some "real" attributes """ - def _create_mock_action(self, parent, name, **kwargs): - """ - Create a fake action with some "real" attributes - """ - action = QtWidgets.QAction(parent) - action.setObjectName(name) - if kwargs.get('triggers'): - action.triggered.connect(kwargs.pop('triggers')) - return action + action = QtWidgets.QAction(parent) + action.setObjectName(name) + if kwargs.get('triggers'): + action.triggered.connect(kwargs.pop('triggers')) + return action - def setUp(self): - """ - Set up the objects we need for all of the tests - """ - Registry.create() - self.registry = Registry() - self.setup_application() - # Mock cursor busy/normal methods. - self.app.set_busy_cursor = MagicMock() - self.app.set_normal_cursor = MagicMock() - self.app.process_events = MagicMock() - self.app.args = [] - Registry().register('application', self.app) - Registry().register('settings', Settings()) - Registry().set_flag('no_web_server', True) - self.add_toolbar_action_patcher = patch('openlp.core.ui.mainwindow.create_action') - self.mocked_add_toolbar_action = self.add_toolbar_action_patcher.start() - self.mocked_add_toolbar_action.side_effect = self._create_mock_action - self.renderer_patcher = patch('openlp.core.display.render.Renderer') - self.mocked_renderer = self.renderer_patcher.start() - mocked_desktop = MagicMock() - mocked_desktop.screenCount.return_value = 1 - mocked_desktop.screenGeometry.return_value = QtCore.QRect(0, 0, 1024, 768) - mocked_desktop.primaryScreen.return_value = 1 - ScreenList.create(mocked_desktop) - State().load_settings() - self.main_window = MainWindow() - def tearDown(self): - """ - Delete all the C++ objects and stop all the patchers - """ - del self.main_window - self.renderer_patcher.stop() - self.add_toolbar_action_patcher.stop() +@pytest.yield_fixture() +def main_window(state, settings): + app = Registry().get('application') + app.set_busy_cursor = MagicMock() + app.set_normal_cursor = MagicMock() + app.process_events = MagicMock() + app.args = [] + Registry().set_flag('no_web_server', True) + add_toolbar_action_patcher = patch('openlp.core.ui.mainwindow.create_action') + mocked_add_toolbar_action = add_toolbar_action_patcher.start() + mocked_add_toolbar_action.side_effect = _create_mock_action + renderer_patcher = patch('openlp.core.display.render.Renderer') + renderer_patcher.start() + mocked_desktop = MagicMock() + mocked_desktop.screenCount.return_value = 1 + mocked_desktop.screenGeometry.return_value = QtCore.QRect(0, 0, 1024, 768) + mocked_desktop.primaryScreen.return_value = 1 + ScreenList.create(mocked_desktop) + mainwindow = MainWindow() + yield mainwindow + del mainwindow + renderer_patcher.stop() + add_toolbar_action_patcher.stop() - def test_cmd_line_file(self): - """ - Test that passing a service file from the command line loads the service. - """ - # GIVEN a service as an argument to openlp - service = os.path.join(TEST_RESOURCES_PATH, 'service', 'test.osz') - # WHEN the argument is processed - with patch.object(self.main_window.service_manager, 'load_file') as mocked_load_file: - self.main_window.open_cmd_line_files([service]) +def test_cmd_line_file(main_window): + """ + Test that passing a service file from the command line loads the service. + """ + # GIVEN a service as an argument to openlp + service = os.path.join(TEST_RESOURCES_PATH, 'service', 'test.osz') - # THEN the service from the arguments is loaded - mocked_load_file.assert_called_with(Path(service)) + # WHEN the argument is processed + with patch.object(main_window.service_manager, 'load_file') as mocked_load_file: + main_window.open_cmd_line_files([service]) - @patch('openlp.core.ui.servicemanager.ServiceManager.load_file') - def test_cmd_line_arg(self, mocked_load_file): - """ - Test that passing a non service file does nothing. - """ - # GIVEN a non service file as an argument to openlp - service = 'run_openlp.py' + # THEN the service from the arguments is loaded + mocked_load_file.assert_called_with(Path(service)) - # WHEN the argument is processed - self.main_window.open_cmd_line_files(service) - # THEN the file should not be opened - assert mocked_load_file.called is False, 'load_file should not have been called' +@patch('openlp.core.ui.servicemanager.ServiceManager.load_file') +def test_cmd_line_arg(mocked_load_file, main_window): + """ + Test that passing a non service file does nothing. + """ + # GIVEN a non service file as an argument to openlp + service = 'run_openlp.py' - def test_main_window_title(self): - """ - Test that running a new instance of OpenLP set the window title correctly - """ - # GIVEN a newly opened OpenLP instance + # WHEN the argument is processed + main_window.open_cmd_line_files(service) - # WHEN no changes are made to the service + # THEN the file should not be opened + assert mocked_load_file.called is False, 'load_file should not have been called' - # THEN the main window's title shoud be the same as the OpenLP string in the UiStrings class - assert self.main_window.windowTitle() == UiStrings().OpenLP, \ - 'The main window\'s title should be the same as the OpenLP string in UiStrings class' - def test_set_service_modifed(self): - """ - Test that when setting the service's title the main window's title is set correctly - """ - # GIVEN a newly opened OpenLP instance +def test_main_window_title(main_window): + """ + Test that running a new instance of OpenLP set the window title correctly + """ + # GIVEN a newly opened OpenLP instance - # WHEN set_service_modified is called with with the modified flag set true and a file name - self.main_window.set_service_modified(True, 'test.osz') + # WHEN no changes are made to the service - # THEN the main window's title should be set to the - assert self.main_window.windowTitle(), '%s - %s*' % (UiStrings().OpenLP, 'test.osz') == \ - 'The main window\'s title should be set to " - test.osz*"' + # THEN the main window's title shoud be the same as the OpenLP string in the UiStrings class + assert main_window.windowTitle() == UiStrings().OpenLP, \ + 'The main window\'s title should be the same as the OpenLP string in UiStrings class' - def test_set_service_unmodified(self): - """ - Test that when setting the service's title the main window's title is set correctly - """ - # GIVEN a newly opened OpenLP instance - # WHEN set_service_modified is called with with the modified flag set False and a file name - self.main_window.set_service_modified(False, 'test.osz') +def test_set_service_modifed(main_window): + """ + Test that when setting the service's title the main window's title is set correctly + """ + # GIVEN a newly opened OpenLP instance - # THEN the main window's title should be set to the - assert self.main_window.windowTitle(), '%s - %s' % (UiStrings().OpenLP, 'test.osz') == \ - 'The main window\'s title should be set to " - test.osz"' + # WHEN set_service_modified is called with with the modified flag set true and a file name + main_window.set_service_modified(True, 'test.osz') - def test_mainwindow_configuration(self): - """ - Check that the Main Window initialises the Registry Correctly - """ - # GIVEN: A built main window + # THEN the main window's title should be set to the + assert main_window.windowTitle(), '%s - %s*' % (UiStrings().OpenLP, 'test.osz') == \ + 'The main window\'s title should be set to " - test.osz*"' - # WHEN: you check the started functions - # THEN: the following registry functions should have been registered - expected_service_list = ['application', 'settings', 'main_window', 'http_server', 'authentication_token', - 'settings_form', 'service_manager', 'theme_manager', 'projector_manager'] - expected_functions_list = ['bootstrap_initialise', 'bootstrap_post_set_up', 'bootstrap_completion', - 'theme_update_global', 'config_screen_changed'] - assert list(self.registry.service_list.keys()) == expected_service_list, \ - 'The service list should have been {}'.format(self.registry.service_list.keys()) - assert list(self.registry.functions_list.keys()) == expected_functions_list, \ - 'The function list should have been {}'.format(self.registry.functions_list.keys()) - assert 'application' in self.registry.service_list, 'The application should have been registered.' - assert 'main_window' in self.registry.service_list, 'The main_window should have been registered.' +def test_set_service_unmodified(main_window): + """ + Test that when setting the service's title the main window's title is set correctly + """ + # GIVEN a newly opened OpenLP instance - def test_projector_manager_hidden_on_startup(self): - """ - Test that the projector manager is hidden on startup - """ - # GIVEN: A built main window - # WHEN: OpenLP is started - # THEN: The projector manager should be hidden - assert self.main_window.projector_manager_dock.isVisible() is False + # WHEN set_service_modified is called with with the modified flag set False and a file name + main_window.set_service_modified(False, 'test.osz') - def test_on_search_shortcut_triggered_shows_media_manager(self): - """ - Test that the media manager is made visible when the search shortcut is triggered - """ - # GIVEN: A build main window set up for testing - with patch.object(self.main_window, 'media_manager_dock') as mocked_media_manager_dock, \ - patch.object(self.main_window, 'media_tool_box') as mocked_media_tool_box: - mocked_media_manager_dock.isVisible.return_value = False - mocked_media_tool_box.currentWidget.return_value = None + # THEN the main window's title should be set to the + assert main_window.windowTitle(), '%s - %s' % (UiStrings().OpenLP, 'test.osz') == \ + 'The main window\'s title should be set to " - test.osz"' - # WHEN: The search shortcut is triggered - self.main_window.on_search_shortcut_triggered() - # THEN: The media manager dock is made visible - mocked_media_manager_dock.setVisible.assert_called_with(True) +def test_mainwindow_configuration(main_window): + """ + Check that the Main Window initialises the Registry Correctly + """ + # GIVEN: A built main window - def test_on_search_shortcut_triggered_focuses_widget(self): - """ - Test that the focus is set on the widget when the search shortcut is triggered - """ - # GIVEN: A build main window set up for testing - with patch.object(self.main_window, 'media_manager_dock') as mocked_media_manager_dock, \ - patch.object(self.main_window, 'media_tool_box') as mocked_media_tool_box: - mocked_media_manager_dock.isVisible.return_value = True - mocked_widget = MagicMock() - mocked_media_tool_box.currentWidget.return_value = mocked_widget + # WHEN: you check the started functions - # WHEN: The search shortcut is triggered - self.main_window.on_search_shortcut_triggered() + # THEN: the following registry functions should have been registered + expected_service_list = ['settings', 'application', 'main_window', 'http_server', 'authentication_token', + 'settings_form', 'service_manager', 'theme_manager', 'projector_manager'] + expected_functions_list = ['bootstrap_initialise', 'bootstrap_post_set_up', 'bootstrap_completion', + 'theme_update_global', 'config_screen_changed'] + assert list(Registry().service_list.keys()) == expected_service_list, \ + 'The service list should have been {}'.format(Registry().service_list.keys()) + assert list(Registry().functions_list.keys()) == expected_functions_list, \ + 'The function list should have been {}'.format(Registry().functions_list.keys()) + assert 'application' in Registry().service_list, 'The application should have been registered.' + assert 'main_window' in Registry().service_list, 'The main_window should have been registered.' + assert 'settings' in Registry().service_list, 'The settings should have been registered.' - # THEN: The media manager dock is made visible - assert 0 == mocked_media_manager_dock.setVisible.call_count - mocked_widget.on_focus.assert_called_with() - @patch('openlp.core.ui.mainwindow.FirstTimeForm') - @patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning') - def test_on_first_time_wizard_clicked_show_projectors_after(self, mocked_warning, MockWizard): - """Test that the projector manager is shown after the FTW is run""" - # GIVEN: Main_window, patched things, patched "Yes" as confirmation to re-run wizard, settings to True. - mocked_warning.return_value = QtWidgets.QMessageBox.Yes - MockWizard.return_value.was_cancelled = False - self.main_window.settings.setValue('projector/show after wizard', True) +def test_projector_manager_hidden_on_startup(main_window): + """ + Test that the projector manager is hidden on startup + """ + # GIVEN: A built main window + # WHEN: OpenLP is started + # THEN: The projector manager should be hidden + assert main_window.projector_manager_dock.isVisible() is False - with patch.object(self.main_window, 'projector_manager_dock') as mocked_dock, \ - patch.object(self.registry, 'execute'), patch.object(self.main_window, 'theme_manager_contents'): - # WHEN: on_first_time_wizard_clicked is called - self.main_window.on_first_time_wizard_clicked() - # THEN: projector_manager_dock.setVisible should had been called once - mocked_dock.setVisible.assert_called_once_with(True) +def test_on_search_shortcut_triggered_shows_media_manager(main_window): + """ + Test that the media manager is made visible when the search shortcut is triggered + """ + # GIVEN: A build main window set up for testing + with patch.object(main_window, 'media_manager_dock') as mocked_media_manager_dock, \ + patch.object(main_window, 'media_tool_box') as mocked_media_tool_box: + mocked_media_manager_dock.isVisible.return_value = False + mocked_media_tool_box.currentWidget.return_value = None - @patch('openlp.core.ui.mainwindow.FirstTimeForm') - @patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning') - def test_on_first_time_wizard_clicked_hide_projectors_after(self, mocked_warning, MockWizard): - """Test that the projector manager is hidden after the FTW is run""" - # GIVEN: Main_window, patched things, patched "Yes" as confirmation to re-run wizard, settings to False. - mocked_warning.return_value = QtWidgets.QMessageBox.Yes - MockWizard.return_value.was_cancelled = False - self.main_window.settings.setValue('projector/show after wizard', False) + # WHEN: The search shortcut is triggered + main_window.on_search_shortcut_triggered() + # THEN: The media manager dock is made visible + mocked_media_manager_dock.setVisible.assert_called_with(True) + + +def test_on_search_shortcut_triggered_focuses_widget(main_window): + """ + Test that the focus is set on the widget when the search shortcut is triggered + """ + # GIVEN: A build main window set up for testing + with patch.object(main_window, 'media_manager_dock') as mocked_media_manager_dock, \ + patch.object(main_window, 'media_tool_box') as mocked_media_tool_box: + mocked_media_manager_dock.isVisible.return_value = True + mocked_widget = MagicMock() + mocked_media_tool_box.currentWidget.return_value = mocked_widget + + # WHEN: The search shortcut is triggered + main_window.on_search_shortcut_triggered() + + # THEN: The media manager dock is made visible + assert 0 == mocked_media_manager_dock.setVisible.call_count + mocked_widget.on_focus.assert_called_with() + + +@patch('openlp.core.ui.mainwindow.FirstTimeForm') +@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning') +def test_on_first_time_wizard_clicked_show_projectors_after(mocked_warning, MockWizard, main_window): + """Test that the projector manager is shown after the FTW is run""" + # GIVEN: Main_window, patched things, patched "Yes" as confirmation to re-run wizard, settings to True. + mocked_warning.return_value = QtWidgets.QMessageBox.Yes + MockWizard.return_value.was_cancelled = False + main_window.settings.setValue('projector/show after wizard', True) + + with patch.object(main_window, 'projector_manager_dock') as mocked_dock, \ + patch.object(Registry(), 'execute'), patch.object(main_window, 'theme_manager_contents'): # WHEN: on_first_time_wizard_clicked is called - with patch.object(self.main_window, 'projector_manager_dock') as mocked_dock, \ - patch.object(self.registry, 'execute'), patch.object(self.main_window, 'theme_manager_contents'): - self.main_window.on_first_time_wizard_clicked() + main_window.on_first_time_wizard_clicked() - # THEN: projector_manager_dock.setVisible should had been called once - mocked_dock.setVisible.assert_called_once_with(False) + # THEN: projector_manager_dock.setVisible should had been called once + mocked_dock.setVisible.assert_called_once_with(True) - def test_increment_progress_bar_default_increment(self): - """ - Test that increment_progress_bar increments the progress bar by 1 when called without the `increment` arg. - """ - # GIVEN: A mocked progress bar - with patch.object(self.main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar: - # WHEN: Calling increment_progress_bar without the `increment` arg - self.main_window.increment_progress_bar() +@patch('openlp.core.ui.mainwindow.FirstTimeForm') +@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning') +def test_on_first_time_wizard_clicked_hide_projectors_after(mocked_warning, MockWizard, main_window): + """Test that the projector manager is hidden after the FTW is run""" + # GIVEN: Main_window, patched things, patched "Yes" as confirmation to re-run wizard, settings to False. + mocked_warning.return_value = QtWidgets.QMessageBox.Yes + MockWizard.return_value.was_cancelled = False + main_window.settings.setValue('projector/show after wizard', False) - # THEN: The progress bar value should have been incremented by 1 - mocked_progress_bar.setValue.assert_called_once_with(1) + # WHEN: on_first_time_wizard_clicked is called + with patch.object(main_window, 'projector_manager_dock') as mocked_dock, \ + patch.object(Registry(), 'execute'), patch.object(main_window, 'theme_manager_contents'): + main_window.on_first_time_wizard_clicked() - def test_increment_progress_bar_custom_increment(self): - """ - Test that increment_progress_bar increments the progress bar by the `increment` arg when called with the - `increment` arg with a set value. - """ - # GIVEN: A mocked progress bar - with patch.object(self.main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar: + # THEN: projector_manager_dock.setVisible should had been called once + mocked_dock.setVisible.assert_called_once_with(False) - # WHEN: Calling increment_progress_bar with `increment` set to 10 - self.main_window.increment_progress_bar(increment=10) - # THEN: The progress bar value should have been incremented by 10 - mocked_progress_bar.setValue.assert_called_once_with(10) +def test_increment_progress_bar_default_increment(main_window): + """ + Test that increment_progress_bar increments the progress bar by 1 when called without the `increment` arg. + """ + # GIVEN: A mocked progress bar + with patch.object(main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar: - def test_eventFilter(self): - """ - Test the reimplemented event method - """ - # GIVEN: A file path and a QEvent. - file_path = str(RESOURCE_PATH / 'church.jpg') - mocked_file_method = MagicMock(return_value=file_path) - event = QtCore.QEvent(QtCore.QEvent.FileOpen) - event.file = mocked_file_method + # WHEN: Calling increment_progress_bar without the `increment` arg + main_window.increment_progress_bar() - # WHEN: Call the vent method. - result = self.main_window.eventFilter(MagicMock(), event) + # THEN: The progress bar value should have been incremented by 1 + mocked_progress_bar.setValue.assert_called_once_with(1) - # THEN: The path should be inserted. - assert result is True, "The method should have returned True." - mocked_file_method.assert_called_once_with() - assert self.app.args[0] == file_path, "The path should be in args." - @patch('openlp.core.ui.mainwindow.is_macosx') - def test_application_activate_event(self, mocked_is_macosx): - """ - Test that clicking on the dock icon on Mac OS X restores the main window if it is minimized - """ - # GIVEN: Mac OS X and an ApplicationActivate event - mocked_is_macosx.return_value = True - event = QtCore.QEvent(QtCore.QEvent.ApplicationActivate) - self.main_window.showMinimized() +def test_increment_progress_bar_custom_increment(main_window): + """ + Test that increment_progress_bar increments the progress bar by the `increment` arg when called with the + `increment` arg with a set value. + """ + # GIVEN: A mocked progress bar + with patch.object(main_window, 'load_progress_bar', **{'value.return_value': 0}) as mocked_progress_bar: - # WHEN: The icon in the dock is clicked - result = self.main_window.eventFilter(MagicMock(), event) + # WHEN: Calling increment_progress_bar with `increment` set to 10 + main_window.increment_progress_bar(increment=10) - # THEN: - assert result is True, "The method should have returned True." - assert self.main_window.isMinimized() is False + # THEN: The progress bar value should have been incremented by 10 + mocked_progress_bar.setValue.assert_called_once_with(10) + + +def test_eventFilter(main_window): + """ + Test the reimplemented event method + """ + # GIVEN: A file path and a QEvent. + file_path = str(RESOURCE_PATH / 'church.jpg') + mocked_file_method = MagicMock(return_value=file_path) + event = QtCore.QEvent(QtCore.QEvent.FileOpen) + event.file = mocked_file_method + + # WHEN: Call the vent method. + result = main_window.eventFilter(MagicMock(), event) + + # THEN: The path should be inserted. + assert result is True, "The method should have returned True." + mocked_file_method.assert_called_once_with() + assert Registry().get('application').args[0] == file_path, "The path should be in args." + + +@patch('openlp.core.ui.mainwindow.is_macosx') +def test_application_activate_event(mocked_is_macosx, main_window): + """ + Test that clicking on the dock icon on Mac OS X restores the main window if it is minimized + """ + # GIVEN: Mac OS X and an ApplicationActivate event + mocked_is_macosx.return_value = True + event = QtCore.QEvent(QtCore.QEvent.ApplicationActivate) + main_window.showMinimized() + + # WHEN: The icon in the dock is clicked + result = main_window.eventFilter(MagicMock(), event) + + # THEN: + assert result is True, "The method should have returned True." + assert main_window.isMinimized() is False diff --git a/tests/functional/openlp_core/ui/test_servicemanager.py b/tests/functional/openlp_core/ui/test_servicemanager.py index f08dbbc21..31e18d731 100644 --- a/tests/functional/openlp_core/ui/test_servicemanager.py +++ b/tests/functional/openlp_core/ui/test_servicemanager.py @@ -21,7 +21,6 @@ """ Package to test the openlp.core.ui.slidecontroller package. """ -from unittest import TestCase from unittest.mock import MagicMock, patch import PyQt5 @@ -34,682 +33,690 @@ from openlp.core.ui.servicemanager import ServiceManager from openlp.core.widgets.toolbar import OpenLPToolbar -class TestServiceManager(TestCase): +def test_initial_service_manager(registry): """ - Test the service manager + Test the initial of service manager. """ + # GIVEN: A new service manager instance. + ServiceManager(None) + # WHEN: the default service manager is built. + # THEN: The the controller should be registered in the registry. + assert Registry().get('service_manager') is not None, 'The base service manager should be registered' - def setUp(self): - """ - Create the UI - """ - Registry.create() - def test_initial_service_manager(self): - """ - Test the initial of service manager. - """ - # GIVEN: A new service manager instance. - ServiceManager(None) - # WHEN: the default service manager is built. - # THEN: The the controller should be registered in the registry. - assert Registry().get('service_manager') is not None, 'The base service manager should be registered' +def test_create_basic_service(registry): + """ + Test the create basic service array + """ + # GIVEN: A new service manager instance. + service_manager = ServiceManager(None) + # WHEN: when the basic service array is created. + service_manager._save_lite = False + service_manager.service_theme = 'test_theme' + service = service_manager.create_basic_service()[0] + # THEN: The controller should be registered in the registry. + assert service is not None, 'The base service should be created' + assert service['openlp_core']['service-theme'] == 'test_theme', 'The test theme should be saved' + assert service['openlp_core']['lite-service'] is False, 'The lite service should be saved' - def test_create_basic_service(self): - """ - Test the create basic service array - """ - # GIVEN: A new service manager instance. - service_manager = ServiceManager(None) - # WHEN: when the basic service array is created. - service_manager._save_lite = False - service_manager.service_theme = 'test_theme' - service = service_manager.create_basic_service()[0] - # THEN: The controller should be registered in the registry. - assert service is not None, 'The base service should be created' - assert service['openlp_core']['service-theme'] == 'test_theme', 'The test theme should be saved' - assert service['openlp_core']['lite-service'] is False, 'The lite service should be saved' - def test_supported_suffixes(self): - """ - Test the create basic service array - """ - # GIVEN: A new service manager instance. - service_manager = ServiceManager(None) - # WHEN: a suffix is added as an individual or a list. - service_manager.supported_suffixes('txt') - service_manager.supported_suffixes(['pptx', 'ppt']) - # THEN: The suffixes should be available to test. - assert 'txt' in service_manager.suffixes, 'The suffix txt should be in the list' - assert 'ppt' in service_manager.suffixes, 'The suffix ppt should be in the list' - assert 'pptx' in service_manager.suffixes, 'The suffix pptx should be in the list' +def test_supported_suffixes(registry): + """ + Test the create basic service array + """ + # GIVEN: A new service manager instance. + service_manager = ServiceManager(None) + # WHEN: a suffix is added as an individual or a list. + service_manager.supported_suffixes('txt') + service_manager.supported_suffixes(['pptx', 'ppt']) + # THEN: The suffixes should be available to test. + assert 'txt' in service_manager.suffixes, 'The suffix txt should be in the list' + assert 'ppt' in service_manager.suffixes, 'The suffix ppt should be in the list' + assert 'pptx' in service_manager.suffixes, 'The suffix pptx should be in the list' - def test_build_context_menu(self): - """ - Test the creation of a context menu from a null service item. - """ - # GIVEN: A new service manager instance and a default service item. - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.rename_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have been called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have been called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ - 'Should have been called once' - def test_build_song_context_menu(self): - """ - Test the creation of a context menu from service item of type text from Songs. - """ - # GIVEN: A new service manager instance and a default service item. - mocked_renderer = MagicMock() - mocked_renderer.theme_level = ThemeLevel.Song - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', mocked_renderer) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - for capability in [ItemCapabilities.CanEdit, ItemCapabilities.CanPreview, ItemCapabilities.CanLoop, - ItemCapabilities.OnLoadUpdate, ItemCapabilities.AddIfNewItem, - ItemCapabilities.CanSoftBreak]: - service_item.add_capability(capability) - service_item.service_item_type = ServiceItemType.Text - service_item.edit_id = 1 - service_item._display_slides = [] - service_item._display_slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - # THEN we add a 2nd display frame - service_item._display_slides.append(MagicMock()) - service_manager.context_menu(1) - # THEN the following additional calls should have occurred. - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' +def test_build_context_menu(registry): + """ + Test the creation of a context menu from a null service item. + """ + # GIVEN: A new service manager instance and a default service item. + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have been called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have been called once' - def test_build_bible_context_menu(self): - """ - Test the creation of a context menu from service item of type text from Bibles. - """ - # GIVEN: A new service manager instance and a default service item. - mocked_renderer = MagicMock() - mocked_renderer.theme_level = ThemeLevel.Song - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', mocked_renderer) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - for capability in [ItemCapabilities.NoLineBreaks, ItemCapabilities.CanPreview, - ItemCapabilities.CanLoop, ItemCapabilities.CanWordSplit, - ItemCapabilities.CanEditTitle]: - service_item.add_capability(capability) - service_item.service_item_type = ServiceItemType.Text - service_item.edit_id = 1 - service_item._display_slides = [] - service_item._display_slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - # THEN we add a 2nd display frame - service_item._display_slides.append(MagicMock()) - service_manager.context_menu(1) - # THEN the following additional calls should have occurred. - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - def test_build_custom_context_menu(self): - """ - Test the creation of a context menu from service item of type text from Custom. - """ - # GIVEN: A new service manager instance and a default service item. - mocked_renderer = MagicMock() - mocked_renderer.theme_level = ThemeLevel.Song - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', mocked_renderer) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_item.add_capability(ItemCapabilities.CanEdit) - service_item.add_capability(ItemCapabilities.CanPreview) - service_item.add_capability(ItemCapabilities.CanLoop) - service_item.add_capability(ItemCapabilities.CanSoftBreak) - service_item.add_capability(ItemCapabilities.OnLoadUpdate) - service_item.service_item_type = ServiceItemType.Text - service_item.edit_id = 1 - service_item._display_slides = [] - service_item._display_slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - # THEN we add a 2nd display frame - service_item._display_slides.append(MagicMock()) - service_manager.context_menu(1) - # THEN the following additional calls should have occurred. - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' +def test_build_song_context_menu(registry, state): + """ + Test the creation of a context menu from service item of type text from Songs. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + for capability in [ItemCapabilities.CanEdit, ItemCapabilities.CanPreview, ItemCapabilities.CanLoop, + ItemCapabilities.OnLoadUpdate, ItemCapabilities.AddIfNewItem, + ItemCapabilities.CanSoftBreak]: + service_item.add_capability(capability) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_slides = [] + service_item._display_slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + # THEN we add a 2nd display frame + service_item._display_slides.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - def test_build_image_context_menu(self): - """ - Test the creation of a context menu from service item of type Image from Image. - """ - # GIVEN: A new service manager instance and a default service item. - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', MagicMock()) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_item.add_capability(ItemCapabilities.CanMaintain) - service_item.add_capability(ItemCapabilities.CanPreview) - service_item.add_capability(ItemCapabilities.CanLoop) - service_item.add_capability(ItemCapabilities.CanAppend) - service_item.add_capability(ItemCapabilities.CanEditTitle) - service_item.service_item_type = ServiceItemType.Image - service_item.edit_id = 1 - service_item.slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - # THEN we add a 2nd display frame and regenerate the menu. - service_item.slides.append(MagicMock()) - service_manager.context_menu(1) - # THEN the following additional calls should have occurred. - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ - 'Should have be called twice' - assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' - assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - def test_build_media_context_menu(self): - """ - Test the creation of a context menu from service item of type Command from Media. - """ - # GIVEN: A new service manager instance and a default service item. - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', MagicMock()) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_item.add_capability(ItemCapabilities.CanAutoStartForLive) - service_item.add_capability(ItemCapabilities.CanEditTitle) - service_item.add_capability(ItemCapabilities.RequiresMedia) - service_item.service_item_type = ServiceItemType.Command - service_item.edit_id = 1 - service_item.slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - # THEN I change the length of the media and regenerate the menu. - service_item.set_media_length(5) - service_manager.context_menu(1) - # THEN the following additional calls should have occurred. - assert service_manager.time_action.setVisible.call_count == 3, 'Should have be called three times' +def test_build_bible_context_menu(registry, state): + """ + Test the creation of a context menu from service item of type text from Bibles. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + for capability in [ItemCapabilities.NoLineBreaks, ItemCapabilities.CanPreview, + ItemCapabilities.CanLoop, ItemCapabilities.CanWordSplit, + ItemCapabilities.CanEditTitle]: + service_item.add_capability(capability) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_slides = [] + service_item._display_slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + # THEN we add a 2nd display frame + service_item._display_slides.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - def test_build_presentation_pdf_context_menu(self): - """ - Test the creation of a context menu from service item of type Command with PDF from Presentation. - """ - # GIVEN: A new service manager instance and a default service item. - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', MagicMock()) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_item.add_capability(ItemCapabilities.CanMaintain) - service_item.add_capability(ItemCapabilities.CanPreview) - service_item.add_capability(ItemCapabilities.CanLoop) - service_item.add_capability(ItemCapabilities.CanAppend) - service_item.service_item_type = ServiceItemType.Command - service_item.edit_id = 1 - service_item.slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - def test_build_presentation_non_pdf_context_menu(self): - """ - Test the creation of a context menu from service item of type Command with Impress from Presentation. - """ - # GIVEN: A new service manager instance and a default service item. - Registry().register('plugin_manager', MagicMock()) - Registry().register('renderer', MagicMock()) - service_manager = ServiceManager(None) - item = MagicMock() - item.parent.return_value = False - item.data.return_value = 0 - service_manager.service_manager_list = MagicMock() - service_manager.service_manager_list.itemAt.return_value = item - service_item = ServiceItem(None) - service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) - service_item.service_item_type = ServiceItemType.Command - service_item.edit_id = 1 - service_item.slides.append(MagicMock()) - service_manager.service_items.insert(1, {'service_item': service_item}) - service_manager.edit_action = MagicMock() - service_manager.rename_action = MagicMock() - service_manager.create_custom_action = MagicMock() - service_manager.maintain_action = MagicMock() - service_manager.notes_action = MagicMock() - service_manager.time_action = MagicMock() - service_manager.auto_start_action = MagicMock() - service_manager.auto_play_slides_menu = MagicMock() - service_manager.auto_play_slides_once = MagicMock() - service_manager.auto_play_slides_loop = MagicMock() - service_manager.timed_slide_interval = MagicMock() - service_manager.theme_menu = MagicMock() - service_manager.menu = MagicMock() - # WHEN I define a context menu - service_manager.context_menu(1) - # THEN the following calls should have occurred. - assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' - assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' - assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' - assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' - assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' - assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ - 'Should have be called once' +def test_build_custom_context_menu(registry, state): + """ + Test the creation of a context menu from service item of type text from Custom. + """ + # GIVEN: A new service manager instance and a default service item. + mocked_renderer = MagicMock() + mocked_renderer.theme_level = ThemeLevel.Song + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', mocked_renderer) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanEdit) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanSoftBreak) + service_item.add_capability(ItemCapabilities.OnLoadUpdate) + service_item.service_item_type = ServiceItemType.Text + service_item.edit_id = 1 + service_item._display_slides = [] + service_item._display_slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + # THEN we add a 2nd display frame + service_item._display_slides.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - @patch('PyQt5.QtCore.QTimer.singleShot') - def test_single_click_preview_true(self, mocked_singleShot): - """ - Test that when "Preview items when clicked in Service Manager" enabled the preview timer starts - """ - # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. - mocked_settings = MagicMock() - mocked_settings.value.return_value = True - Registry().register('settings', mocked_settings) - service_manager = ServiceManager(None) - # WHEN: on_single_click_preview() is called - service_manager.on_single_click_preview() - # THEN: timer should have been started - mocked_singleShot.assert_called_with(PyQt5.QtWidgets.QApplication.instance().doubleClickInterval(), - service_manager.on_single_click_preview_timeout) - @patch('PyQt5.QtCore.QTimer.singleShot') - def test_single_click_preview_false(self, mocked_singleShot): - """ - Test that when "Preview items when clicked in Service Manager" disabled the preview timer doesn't start - """ - # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. - mocked_settings = MagicMock() - mocked_settings.value.return_value = False - Registry().register('settings', mocked_settings) - service_manager = ServiceManager(None) - # WHEN: on_single_click_preview() is called - service_manager.on_single_click_preview() - # THEN: timer should not be started - assert mocked_singleShot.call_count == 0, 'Should not be called' +def test_build_image_context_menu(registry): + """ + Test the creation of a context menu from service item of type Image from Image. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanMaintain) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanAppend) + service_item.add_capability(ItemCapabilities.CanEditTitle) + service_item.service_item_type = ServiceItemType.Image + service_item.edit_id = 1 + service_item.slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + # THEN we add a 2nd display frame and regenerate the menu. + service_item.slides.append(MagicMock()) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' - @patch('PyQt5.QtCore.QTimer.singleShot') - @patch('openlp.core.ui.servicemanager.ServiceManager.make_live') - def test_single_click_preview_double(self, mocked_make_live, mocked_singleShot): - """ - Test that when a double click has registered the preview timer doesn't start - """ - # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. - mocked_settings = MagicMock() - mocked_settings.value.return_value = True - Registry().register('settings', mocked_settings) - service_manager = ServiceManager(None) - # WHEN: on_single_click_preview() is called following a double click - service_manager.on_double_click_live() - service_manager.on_single_click_preview() - # THEN: timer should not be started - mocked_make_live.assert_called_with() - assert mocked_singleShot.call_count == 0, 'Should not be called' - @patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') - def test_single_click_timeout_single(self, mocked_make_preview): - """ - Test that when a single click has been registered, the item is sent to preview - """ - # GIVEN: A service manager. - service_manager = ServiceManager(None) - # WHEN: on_single_click_preview() is called - service_manager.on_single_click_preview_timeout() - # THEN: make_preview() should have been called - assert mocked_make_preview.call_count == 1, 'ServiceManager.make_preview() should have been called once' +def test_build_media_context_menu(registry): + """ + Test the creation of a context menu from service item of type Command from Media. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanAutoStartForLive) + service_item.add_capability(ItemCapabilities.CanEditTitle) + service_item.add_capability(ItemCapabilities.RequiresMedia) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item.slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + # THEN I change the length of the media and regenerate the menu. + service_item.set_media_length(5) + service_manager.context_menu(1) + # THEN the following additional calls should have occurred. + assert service_manager.time_action.setVisible.call_count == 3, 'Should have be called three times' - @patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') - @patch('openlp.core.ui.servicemanager.ServiceManager.make_live') - def test_single_click_timeout_double(self, mocked_make_live, mocked_make_preview): - """ - Test that when a double click has been registered, the item does not goes to preview - """ - # GIVEN: A service manager. - service_manager = ServiceManager(None) - # WHEN: on_single_click_preview() is called after a double click - service_manager.on_double_click_live() - service_manager.on_single_click_preview_timeout() - # THEN: make_preview() should not have been called - assert mocked_make_preview.call_count == 0, 'ServiceManager.make_preview() should not be called' - @patch('openlp.core.ui.servicemanager.zipfile') - @patch('openlp.core.ui.servicemanager.ServiceManager.save_file_as') - @patch('openlp.core.ui.servicemanager.os') - def test_save_file_raises_permission_error(self, mocked_os, mocked_save_file_as, mocked_zipfile): - """ - Test that when a PermissionError is raised when trying to save a file, it is handled correctly - """ - # GIVEN: A service manager, a service to save - mocked_main_window = MagicMock() - mocked_main_window.service_manager_settings_section = 'servicemanager' - Registry().register('main_window', mocked_main_window) - Registry().register('application', MagicMock()) - service_manager = ServiceManager(None) - service_manager._service_path = MagicMock() - service_manager._save_lite = False - service_manager.service_items = [] - service_manager.service_theme = 'Default' - service_manager.service_manager_list = MagicMock() - mocked_save_file_as.return_value = True - mocked_zipfile.ZipFile.return_value = MagicMock() - mocked_os.link.side_effect = PermissionError +def test_build_presentation_pdf_context_menu(registry): + """ + Test the creation of a context menu from service item of type Command with PDF from Presentation. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.CanMaintain) + service_item.add_capability(ItemCapabilities.CanPreview) + service_item.add_capability(ItemCapabilities.CanLoop) + service_item.add_capability(ItemCapabilities.CanAppend) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item.slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' - # WHEN: The service is saved and a PermissionError is raised - result = service_manager.save_file() - # THEN: The "save_as" method is called to save the service - assert result is True - mocked_save_file_as.assert_called_with() +def test_build_presentation_non_pdf_context_menu(registry): + """ + Test the creation of a context menu from service item of type Command with Impress from Presentation. + """ + # GIVEN: A new service manager instance and a default service item. + Registry().register('plugin_manager', MagicMock()) + Registry().register('renderer', MagicMock()) + service_manager = ServiceManager(None) + item = MagicMock() + item.parent.return_value = False + item.data.return_value = 0 + service_manager.service_manager_list = MagicMock() + service_manager.service_manager_list.itemAt.return_value = item + service_item = ServiceItem(None) + service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) + service_item.service_item_type = ServiceItemType.Command + service_item.edit_id = 1 + service_item.slides.append(MagicMock()) + service_manager.service_items.insert(1, {'service_item': service_item}) + service_manager.edit_action = MagicMock() + service_manager.rename_action = MagicMock() + service_manager.create_custom_action = MagicMock() + service_manager.maintain_action = MagicMock() + service_manager.notes_action = MagicMock() + service_manager.time_action = MagicMock() + service_manager.auto_start_action = MagicMock() + service_manager.auto_play_slides_menu = MagicMock() + service_manager.auto_play_slides_once = MagicMock() + service_manager.auto_play_slides_loop = MagicMock() + service_manager.timed_slide_interval = MagicMock() + service_manager.theme_menu = MagicMock() + service_manager.menu = MagicMock() + # WHEN I define a context menu + service_manager.context_menu(1) + # THEN the following calls should have occurred. + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' - @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') - def test_theme_change_global(self, mocked_regenerate_service_items): - """ - Test that when a Toolbar theme combobox displays correctly when the theme is set to Global - """ - # GIVEN: A service manager, a service to display with a theme level in the renderer - mocked_renderer = MagicMock() - service_manager = ServiceManager(None) - Registry().register('renderer', mocked_renderer) - service_manager.toolbar = OpenLPToolbar(None) - service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) - service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) - # WHEN: The service manager has a Global theme - mocked_renderer.theme_level = ThemeLevel.Global - service_manager.theme_change() +@patch('PyQt5.QtCore.QTimer.singleShot') +def test_single_click_preview_true(mocked_singleShot, registry): + """ + Test that when "Preview items when clicked in Service Manager" enabled the preview timer starts + """ + # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. + mocked_settings = MagicMock() + mocked_settings.value.return_value = True + Registry().register('settings', mocked_settings) + service_manager = ServiceManager(None) + # WHEN: on_single_click_preview() is called + service_manager.on_single_click_preview() + # THEN: timer should have been started + mocked_singleShot.assert_called_with(PyQt5.QtWidgets.QApplication.instance().doubleClickInterval(), + service_manager.on_single_click_preview_timeout) - # THEN: The the theme toolbar should not be visible - assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is False, \ - 'The visibility should be False' - @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') - def test_theme_change_service(self, mocked_regenerate_service_items): - """ - Test that when a Toolbar theme combobox displays correctly when the theme is set to Theme - """ - # GIVEN: A service manager, a service to display with a theme level in the renderer - mocked_renderer = MagicMock() - service_manager = ServiceManager(None) - Registry().register('renderer', mocked_renderer) - service_manager.toolbar = OpenLPToolbar(None) - service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) - service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) +@patch('PyQt5.QtCore.QTimer.singleShot') +def test_single_click_preview_false(mocked_singleShot, registry): + """ + Test that when "Preview items when clicked in Service Manager" disabled the preview timer doesn't start + """ + # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. + mocked_settings = MagicMock() + mocked_settings.value.return_value = False + Registry().register('settings', mocked_settings) + service_manager = ServiceManager(None) + # WHEN: on_single_click_preview() is called + service_manager.on_single_click_preview() + # THEN: timer should not be started + assert mocked_singleShot.call_count == 0, 'Should not be called' - # WHEN: The service manager has a Service theme - mocked_renderer.theme_level = ThemeLevel.Service - service_manager.theme_change() - # THEN: The the theme toolbar should be visible - assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ - 'The visibility should be True' +@patch('PyQt5.QtCore.QTimer.singleShot') +@patch('openlp.core.ui.servicemanager.ServiceManager.make_live') +def test_single_click_preview_double(mocked_make_live, mocked_singleShot, registry): + """ + Test that when a double click has registered the preview timer doesn't start + """ + # GIVEN: A setting to enable "Preview items when clicked in Service Manager" and a service manager. + mocked_settings = MagicMock() + mocked_settings.value.return_value = True + Registry().register('settings', mocked_settings) + service_manager = ServiceManager(None) + # WHEN: on_single_click_preview() is called following a double click + service_manager.on_double_click_live() + service_manager.on_single_click_preview() + # THEN: timer should not be started + mocked_make_live.assert_called_with() + assert mocked_singleShot.call_count == 0, 'Should not be called' - @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') - def test_theme_change_song(self, mocked_regenerate_service_items): - """ - Test that when a Toolbar theme combobox displays correctly when the theme is set to Song - """ - # GIVEN: A service manager, a service to display with a theme level in the renderer - mocked_renderer = MagicMock() - service_manager = ServiceManager(None) - Registry().register('renderer', mocked_renderer) - service_manager.toolbar = OpenLPToolbar(None) - service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) - service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) - # WHEN: The service manager has a Song theme - mocked_renderer.theme_level = ThemeLevel.Song - service_manager.theme_change() +@patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') +def test_single_click_timeout_single(mocked_make_preview, registry): + """ + Test that when a single click has been registered, the item is sent to preview + """ + # GIVEN: A service manager. + service_manager = ServiceManager(None) + # WHEN: on_single_click_preview() is called + service_manager.on_single_click_preview_timeout() + # THEN: make_preview() should have been called + assert mocked_make_preview.call_count == 1, 'ServiceManager.make_preview() should have been called once' - # THEN: The the theme toolbar should be visible - assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ - 'The visibility should be True' + +@patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') +@patch('openlp.core.ui.servicemanager.ServiceManager.make_live') +def test_single_click_timeout_double(mocked_make_live, mocked_make_preview, registry): + """ + Test that when a double click has been registered, the item does not goes to preview + """ + # GIVEN: A service manager. + service_manager = ServiceManager(None) + # WHEN: on_single_click_preview() is called after a double click + service_manager.on_double_click_live() + service_manager.on_single_click_preview_timeout() + # THEN: make_preview() should not have been called + assert mocked_make_preview.call_count == 0, 'ServiceManager.make_preview() should not be called' + + +@patch('openlp.core.ui.servicemanager.zipfile') +@patch('openlp.core.ui.servicemanager.ServiceManager.save_file_as') +@patch('openlp.core.ui.servicemanager.os') +def test_save_file_raises_permission_error(mocked_os, mocked_save_file_as, mocked_zipfile, registry): + """ + Test that when a PermissionError is raised when trying to save a file, it is handled correctly + """ + # GIVEN: A service manager, a service to save + mocked_main_window = MagicMock() + mocked_main_window.service_manager_settings_section = 'servicemanager' + Registry().register('main_window', mocked_main_window) + Registry().register('application', MagicMock()) + service_manager = ServiceManager(None) + service_manager._service_path = MagicMock() + service_manager._save_lite = False + service_manager.service_items = [] + service_manager.service_theme = 'Default' + service_manager.service_manager_list = MagicMock() + mocked_save_file_as.return_value = True + mocked_zipfile.ZipFile.return_value = MagicMock() + mocked_os.link.side_effect = PermissionError + + # WHEN: The service is saved and a PermissionError is raised + result = service_manager.save_file() + + # THEN: The "save_as" method is called to save the service + assert result is True + mocked_save_file_as.assert_called_with() + + +@patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') +def test_theme_change_global(mocked_regenerate_service_items, registry): + """ + Test that when a Toolbar theme combobox displays correctly when the theme is set to Global + """ + # GIVEN: A service manager, a service to display with a theme level in the renderer + mocked_renderer = MagicMock() + service_manager = ServiceManager(None) + Registry().register('renderer', mocked_renderer) + service_manager.toolbar = OpenLPToolbar(None) + service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) + service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) + + # WHEN: The service manager has a Global theme + mocked_renderer.theme_level = ThemeLevel.Global + service_manager.theme_change() + + # THEN: The the theme toolbar should not be visible + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is False, \ + 'The visibility should be False' + + +@patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') +def test_theme_change_service(mocked_regenerate_service_items, registry): + """ + Test that when a Toolbar theme combobox displays correctly when the theme is set to Theme + """ + # GIVEN: A service manager, a service to display with a theme level in the renderer + mocked_renderer = MagicMock() + service_manager = ServiceManager(None) + Registry().register('renderer', mocked_renderer) + service_manager.toolbar = OpenLPToolbar(None) + service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) + service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) + + # WHEN: The service manager has a Service theme + mocked_renderer.theme_level = ThemeLevel.Service + service_manager.theme_change() + + # THEN: The the theme toolbar should be visible + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ + 'The visibility should be True' + + +@patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') +def test_theme_change_song(mocked_regenerate_service_items, registry): + """ + Test that when a Toolbar theme combobox displays correctly when the theme is set to Song + """ + # GIVEN: A service manager, a service to display with a theme level in the renderer + mocked_renderer = MagicMock() + service_manager = ServiceManager(None) + Registry().register('renderer', mocked_renderer) + service_manager.toolbar = OpenLPToolbar(None) + service_manager.toolbar.add_toolbar_action('theme_combo_box', triggers=MagicMock()) + service_manager.toolbar.add_toolbar_action('theme_label', triggers=MagicMock()) + + # WHEN: The service manager has a Song theme + mocked_renderer.theme_level = ThemeLevel.Song + service_manager.theme_change() + + # THEN: The the theme toolbar should be visible + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ + 'The visibility should be True' diff --git a/tests/functional/openlp_core/ui/test_settingsform.py b/tests/functional/openlp_core/ui/test_settingsform.py index 2f9dfcb08..55282f1a4 100644 --- a/tests/functional/openlp_core/ui/test_settingsform.py +++ b/tests/functional/openlp_core/ui/test_settingsform.py @@ -21,154 +21,149 @@ """ Package to test the openlp.core.ui.settingsform package. """ -from unittest import TestCase from unittest.mock import MagicMock, patch from PyQt5 import QtWidgets -from openlp.core.common.registry import Registry from openlp.core.ui.settingsform import SettingsForm -class TestSettingsForm(TestCase): +def test_insert_tab_visible(registry): + """ + Test that the insert_tab() method works correctly when a visible tab is inserted + """ + # GIVEN: A mocked tab and a Settings Form + settings_form = SettingsForm(None) + general_tab = MagicMock() + general_tab.tab_title = 'mock' + general_tab.tab_title_visible = 'Mock' + general_tab.icon_path = ':/icon/openlp-logo.svg' - def setUp(self): - """ - Set up a few things for the tests - """ - Registry.create() - - def test_insert_tab_visible(self): - """ - Test that the insert_tab() method works correctly when a visible tab is inserted - """ - # GIVEN: A mocked tab and a Settings Form - settings_form = SettingsForm(None) - general_tab = MagicMock() - general_tab.tab_title = 'mock' - general_tab.tab_title_visible = 'Mock' - general_tab.icon_path = ':/icon/openlp-logo.svg' - - # WHEN: We insert the general tab - with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \ - patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item: - settings_form.insert_tab(general_tab, is_visible=True) - - # THEN: The general tab should have been inserted into the stacked layout and an item inserted into the list - mocked_add_widget.assert_called_with(general_tab) - assert 1 == mocked_add_item.call_count, 'addItem should have been called' - - def test_insert_tab_not_visible(self): - """ - Test that the insert_tab() method works correctly when a tab that should not be visible is inserted - """ - # GIVEN: A general tab and a Settings Form - settings_form = SettingsForm(None) - general_tab = MagicMock() - general_tab.tab_title = 'mock' - - # WHEN: We insert the general tab - with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \ - patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item: - settings_form.insert_tab(general_tab, is_visible=False) - - # THEN: The general tab should have been inserted, but no list item should have been inserted into the list - mocked_add_widget.assert_called_with(general_tab) - assert 0 == mocked_add_item.call_count, 'addItem should not have been called' - - def test_accept_with_inactive_plugins(self): - """ - Test that the accept() method works correctly when some of the plugins are inactive - """ - # GIVEN: A visible general tab and an invisible theme tab in a Settings Form - settings_form = SettingsForm(None) - general_tab = QtWidgets.QWidget(None) - general_tab.tab_title = 'mock-general' - general_tab.tab_title_visible = 'Mock General' - general_tab.icon_path = ':/icon/openlp-logo.svg' - mocked_general_save = MagicMock() - general_tab.save = mocked_general_save - mocked_general_load = MagicMock() - general_tab.load = mocked_general_load - settings_form.insert_tab(general_tab, is_visible=True) - themes_tab = QtWidgets.QWidget(None) - themes_tab.tab_title = 'mock-themes' - themes_tab.tab_title_visible = 'Mock Themes' - themes_tab.icon_path = ':/icon/openlp-logo.svg' - mocked_theme_save = MagicMock() - themes_tab.save = mocked_theme_save - mocked_theme_load = MagicMock() - themes_tab.load = mocked_theme_load - settings_form.insert_tab(themes_tab, is_visible=False) - - # WHEN: The accept() method is called - settings_form.accept() - - # THEN: The general tab's save() method should have been called, but not the themes tab - mocked_general_save.assert_called_with() - assert 0 == mocked_theme_save.call_count, 'The Themes tab\'s save() should not have been called' - - def test_list_item_changed_invalid_item(self): - """ - Test that the list_item_changed() slot handles a non-existent item - """ - # GIVEN: A mocked tab inserted into a Settings Form - settings_form = SettingsForm(None) - general_tab = QtWidgets.QWidget(None) - general_tab.tab_title = 'mock' - general_tab.tab_title_visible = 'Mock' - general_tab.icon_path = ':/icon/openlp-logo.svg' - mocked_general_load = MagicMock() - general_tab.load = mocked_general_load + # WHEN: We insert the general tab + with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \ + patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item: settings_form.insert_tab(general_tab, is_visible=True) - with patch.object(settings_form.stacked_layout, 'count') as mocked_count: - # WHEN: The list_item_changed() slot is called with an invalid item index - settings_form.list_item_changed(100) + # THEN: The general tab should have been inserted into the stacked layout and an item inserted into the list + mocked_add_widget.assert_called_with(general_tab) + assert 1 == mocked_add_item.call_count, 'addItem should have been called' - # THEN: The rest of the method should not have been called - assert 0 == mocked_count.call_count, 'The count method of the stacked layout should not be called' - def test_reject_with_inactive_items(self): - """ - Test that the reject() method works correctly when some of the plugins are inactive - """ - # GIVEN: A visible general tab and an invisible theme tab in a Settings Form - settings_form = SettingsForm(None) - general_tab = QtWidgets.QWidget(None) - general_tab.tab_title = 'mock-general' - general_tab.tab_title_visible = 'Mock General' - general_tab.icon_path = ':/icon/openlp-logo.svg' - mocked_general_cancel = MagicMock() - general_tab.cancel = mocked_general_cancel - mocked_general_load = MagicMock() - general_tab.load = mocked_general_load - settings_form.insert_tab(general_tab, is_visible=True) - themes_tab = QtWidgets.QWidget(None) - themes_tab.tab_title = 'mock-themes' - themes_tab.tab_title_visible = 'Mock Themes' - themes_tab.icon_path = ':/icon/openlp-logo.svg' - mocked_theme_cancel = MagicMock() - themes_tab.cancel = mocked_theme_cancel - settings_form.insert_tab(themes_tab, is_visible=False) +def test_insert_tab_not_visible(registry): + """ + Test that the insert_tab() method works correctly when a tab that should not be visible is inserted + """ + # GIVEN: A general tab and a Settings Form + settings_form = SettingsForm(None) + general_tab = MagicMock() + general_tab.tab_title = 'mock' - # WHEN: The reject() method is called - settings_form.reject() + # WHEN: We insert the general tab + with patch.object(settings_form.stacked_layout, 'addWidget') as mocked_add_widget, \ + patch.object(settings_form.setting_list_widget, 'addItem') as mocked_add_item: + settings_form.insert_tab(general_tab, is_visible=False) - # THEN: The general tab's cancel() method should have been called, but not the themes tab - mocked_general_cancel.assert_called_with() - assert 0 == mocked_theme_cancel.call_count, 'The Themes tab\'s cancel() should not have been called' + # THEN: The general tab should have been inserted, but no list item should have been inserted into the list + mocked_add_widget.assert_called_with(general_tab) + assert 0 == mocked_add_item.call_count, 'addItem should not have been called' - def test_register_post_process(self): - """ - Test that the register_post_process() method works correctly - """ - # GIVEN: A settings form instance - settings_form = SettingsForm(None) - fake_function = MagicMock() - # WHEN: register_post_process() is called - settings_form.register_post_process(fake_function) +def test_accept_with_inactive_plugins(registry): + """ + Test that the accept() method works correctly when some of the plugins are inactive + """ + # GIVEN: A visible general tab and an invisible theme tab in a Settings Form + settings_form = SettingsForm(None) + general_tab = QtWidgets.QWidget(None) + general_tab.tab_title = 'mock-general' + general_tab.tab_title_visible = 'Mock General' + general_tab.icon_path = ':/icon/openlp-logo.svg' + mocked_general_save = MagicMock() + general_tab.save = mocked_general_save + mocked_general_load = MagicMock() + general_tab.load = mocked_general_load + settings_form.insert_tab(general_tab, is_visible=True) + themes_tab = QtWidgets.QWidget(None) + themes_tab.tab_title = 'mock-themes' + themes_tab.tab_title_visible = 'Mock Themes' + themes_tab.icon_path = ':/icon/openlp-logo.svg' + mocked_theme_save = MagicMock() + themes_tab.save = mocked_theme_save + mocked_theme_load = MagicMock() + themes_tab.load = mocked_theme_load + settings_form.insert_tab(themes_tab, is_visible=False) - # THEN: The fake function should be in the settings form's list - assert fake_function in settings_form.processes + # WHEN: The accept() method is called + settings_form.accept() + + # THEN: The general tab's save() method should have been called, but not the themes tab + mocked_general_save.assert_called_with() + assert 0 == mocked_theme_save.call_count, 'The Themes tab\'s save() should not have been called' + + +def test_list_item_changed_invalid_item(registry): + """ + Test that the list_item_changed() slot handles a non-existent item + """ + # GIVEN: A mocked tab inserted into a Settings Form + settings_form = SettingsForm(None) + general_tab = QtWidgets.QWidget(None) + general_tab.tab_title = 'mock' + general_tab.tab_title_visible = 'Mock' + general_tab.icon_path = ':/icon/openlp-logo.svg' + mocked_general_load = MagicMock() + general_tab.load = mocked_general_load + settings_form.insert_tab(general_tab, is_visible=True) + + with patch.object(settings_form.stacked_layout, 'count') as mocked_count: + # WHEN: The list_item_changed() slot is called with an invalid item index + settings_form.list_item_changed(100) + + # THEN: The rest of the method should not have been called + assert 0 == mocked_count.call_count, 'The count method of the stacked layout should not be called' + + +def test_reject_with_inactive_items(registry): + """ + Test that the reject() method works correctly when some of the plugins are inactive + """ + # GIVEN: A visible general tab and an invisible theme tab in a Settings Form + settings_form = SettingsForm(None) + general_tab = QtWidgets.QWidget(None) + general_tab.tab_title = 'mock-general' + general_tab.tab_title_visible = 'Mock General' + general_tab.icon_path = ':/icon/openlp-logo.svg' + mocked_general_cancel = MagicMock() + general_tab.cancel = mocked_general_cancel + mocked_general_load = MagicMock() + general_tab.load = mocked_general_load + settings_form.insert_tab(general_tab, is_visible=True) + themes_tab = QtWidgets.QWidget(None) + themes_tab.tab_title = 'mock-themes' + themes_tab.tab_title_visible = 'Mock Themes' + themes_tab.icon_path = ':/icon/openlp-logo.svg' + mocked_theme_cancel = MagicMock() + themes_tab.cancel = mocked_theme_cancel + settings_form.insert_tab(themes_tab, is_visible=False) + + # WHEN: The reject() method is called + settings_form.reject() + + # THEN: The general tab's cancel() method should have been called, but not the themes tab + mocked_general_cancel.assert_called_with() + assert 0 == mocked_theme_cancel.call_count, 'The Themes tab\'s cancel() should not have been called' + + +def test_register_post_process(registry): + """ + Test that the register_post_process() method works correctly + """ + # GIVEN: A settings form instance + settings_form = SettingsForm(None) + fake_function = MagicMock() + + # WHEN: register_post_process() is called + settings_form.register_post_process(fake_function) + + # THEN: The fake function should be in the settings form's list + assert fake_function in settings_form.processes diff --git a/tests/functional/openlp_core/ui/test_slidecontroller.py b/tests/functional/openlp_core/ui/test_slidecontroller.py index 1df07e436..f7b227316 100644 --- a/tests/functional/openlp_core/ui/test_slidecontroller.py +++ b/tests/functional/openlp_core/ui/test_slidecontroller.py @@ -212,7 +212,7 @@ def test_toggle_display_show(): mocked_on_hide_display.assert_called_once_with(False) -def test_on_go_live_preview_controller(): +def test_on_go_live_preview_controller(registry): """ Test that when the on_go_preview() method is called the message is sent to the preview controller and focus is set correctly. @@ -226,7 +226,6 @@ def test_on_go_live_preview_controller(): mocked_preview_widget.current_slide_number.return_value = 1 mocked_preview_widget.slide_count = MagicMock(return_value=2) mocked_preview_controller.preview_widget = MagicMock() - Registry.create() Registry().register('preview_controller', mocked_preview_controller) slide_controller = SlideController(None) slide_controller.service_item = mocked_service_item @@ -240,7 +239,7 @@ def test_on_go_live_preview_controller(): mocked_preview_controller.preview_widget.setFocus.assert_called_once_with() -def test_on_go_live_live_controller(): +def test_on_go_live_live_controller(registry): """ Test that when the on_go_live() method is called the message is sent to the live controller and focus is set correctly. @@ -254,7 +253,6 @@ def test_on_go_live_live_controller(): mocked_preview_widget.current_slide_number.return_value = 1 mocked_preview_widget.slide_count = MagicMock(return_value=2) mocked_live_controller.preview_widget = MagicMock() - Registry.create() Registry().register('live_controller', mocked_live_controller) slide_controller = SlideController(None) slide_controller.service_item = mocked_service_item @@ -269,7 +267,7 @@ def test_on_go_live_live_controller(): mocked_live_controller.preview_widget.setFocus.assert_called_once_with() -def test_on_go_live_service_manager(): +def test_on_go_live_service_manager(registry): """ Test that when the on_go_live() method is called the message is sent to the live controller and focus is set correctly. @@ -285,7 +283,6 @@ def test_on_go_live_service_manager(): mocked_preview_widget.current_slide_number.return_value = 1 mocked_preview_widget.slide_count = MagicMock(return_value=2) mocked_live_controller.preview_widget = MagicMock() - Registry.create() Registry().register('live_controller', mocked_live_controller) Registry().register('service_manager', mocked_service_manager) slide_controller = SlideController(None) @@ -603,7 +600,7 @@ def test_on_slide_selected_index_no_service_item(): @patch.object(Registry, 'execute') -def test_on_slide_selected_index_service_item_command(mocked_execute): +def test_on_slide_selected_index_service_item_command(mocked_execute, registry): """ Test that when there is a command service item, the command is executed """ @@ -614,7 +611,6 @@ def test_on_slide_selected_index_service_item_command(mocked_execute): mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() - Registry.create() slide_controller = SlideController(None) slide_controller.service_item = mocked_item slide_controller.update_preview = mocked_update_preview @@ -634,7 +630,7 @@ def test_on_slide_selected_index_service_item_command(mocked_execute): @patch.object(Registry, 'execute') -def test_on_slide_selected_index_service_item_not_command(mocked_execute): +def test_on_slide_selected_index_service_item_not_command(mocked_execute, registry): """ Test that when there is a service item but it's not a command, the preview widget is updated """ @@ -645,7 +641,6 @@ def test_on_slide_selected_index_service_item_not_command(mocked_execute): mocked_update_preview = MagicMock() mocked_preview_widget = MagicMock() mocked_slide_selected = MagicMock() - Registry.create() slide_controller = SlideController(None) slide_controller.service_item = mocked_item slide_controller.update_preview = mocked_update_preview @@ -664,7 +659,7 @@ def test_on_slide_selected_index_service_item_not_command(mocked_execute): @patch.object(Registry, 'execute') -def test_process_item(mocked_execute): +def test_process_item(mocked_execute, registry): """ Test that presentation service-items is closed when followed by a media service-item """ @@ -685,7 +680,6 @@ def test_process_item(mocked_execute): mocked_media_item.from_service = False mocked_media_item.get_frames.return_value = [] mocked_main_window = MagicMock() - Registry.create() Registry().register('main_window', mocked_main_window) Registry().register('media_controller', MagicMock()) slide_controller = SlideController(None) @@ -784,7 +778,7 @@ def test_on_preview_double_click_add_to_service(mock_settings): @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') -def test_update_preview_live(mocked_singleShot, mocked_image_manager): +def test_update_preview_live(mocked_singleShot, mocked_image_manager, registry): """ Test that the preview screen is updated with a screen grab for live service items """ @@ -797,8 +791,6 @@ def test_update_preview_live(mocked_singleShot, mocked_image_manager): mocked_live_item.is_capable.side_effect = [True, True] # Mock image_manager mocked_image_manager.get_image.return_value = QtGui.QImage() - # Mock Registry - Registry.create() mocked_main_window = MagicMock() Registry().register('main_window', mocked_main_window) # Mock SlideController @@ -827,7 +819,7 @@ def test_update_preview_live(mocked_singleShot, mocked_image_manager): @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') -def test_update_preview_pres(mocked_singleShot, mocked_image_manager): +def test_update_preview_pres(mocked_singleShot, mocked_image_manager, registry): """ Test that the preview screen is updated with the correct preview for presentation service items """ @@ -840,8 +832,6 @@ def test_update_preview_pres(mocked_singleShot, mocked_image_manager): mocked_pres_item.is_capable.side_effect = [True, True] # Mock image_manager mocked_image_manager.get_image.return_value = QtGui.QImage() - # Mock Registry - Registry.create() mocked_main_window = MagicMock() Registry().register('main_window', mocked_main_window) # Mock SlideController @@ -869,7 +859,7 @@ def test_update_preview_pres(mocked_singleShot, mocked_image_manager): @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') -def test_update_preview_media(mocked_singleShot, mocked_image_manager): +def test_update_preview_media(mocked_singleShot, mocked_image_manager, registry): """ Test that the preview screen is updated with the correct preview for media service items """ @@ -883,7 +873,6 @@ def test_update_preview_media(mocked_singleShot, mocked_image_manager): # Mock image_manager mocked_image_manager.get_image.return_value = QtGui.QImage() # Mock Registry - Registry.create() mocked_main_window = MagicMock() Registry().register('main_window', mocked_main_window) # Mock SlideController @@ -912,7 +901,7 @@ def test_update_preview_media(mocked_singleShot, mocked_image_manager): @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') -def test_update_preview_image(mocked_singleShot, mocked_image_manager): +def test_update_preview_image(mocked_singleShot, mocked_image_manager, registry): """ Test that the preview screen is updated with the correct preview for image service items """ @@ -926,7 +915,6 @@ def test_update_preview_image(mocked_singleShot, mocked_image_manager): # Mock image_manager mocked_image_manager.get_image.return_value = QtGui.QImage() # Mock Registry - Registry.create() mocked_main_window = MagicMock() Registry().register('main_window', mocked_main_window) # Mock SlideController @@ -1030,12 +1018,11 @@ def test_set_text(mocked_super): mocked_super().setText.assert_called_once_with('Label Text') -def test_initial_live_controller(): +def test_initial_live_controller(registry): """ Test the initial live slide controller state . """ # GIVEN: A new SlideController instance. - Registry.create() live_controller = LiveController(None) # WHEN: the default controller is built. @@ -1043,12 +1030,11 @@ def test_initial_live_controller(): assert live_controller.is_live is True, 'The slide controller should be a live controller' -def test_initial_preview_controller(): +def test_initial_preview_controller(registry): """ Test the initial preview slide controller state. """ # GIVEN: A new SlideController instance. - Registry.create() preview_controller = PreviewController(None) # WHEN: the default controller is built. diff --git a/tests/functional/openlp_core/ui/test_splashscreen.py b/tests/functional/openlp_core/ui/test_splashscreen.py index 13a2593bb..3f6ed137a 100644 --- a/tests/functional/openlp_core/ui/test_splashscreen.py +++ b/tests/functional/openlp_core/ui/test_splashscreen.py @@ -26,21 +26,17 @@ from PyQt5 import QtCore from openlp.core.ui.splashscreen import SplashScreen -class TestSplashScreen(): +def test_splashscreen(): """ - This will test the SplachScreen.py file + Test that the SpashScreen is created correctly """ - def test_SplashScreen(self): - """ - Test that the SpashScreen is created correctly - """ - # GIVEN: the SplashScreen class - # WHEN: An object is created + # GIVEN: the SplashScreen class + # WHEN: An object is created - ss = SplashScreen() - # THEN: Nothing should go wrong and the instance should have the correct values - assert ss.objectName() == 'splashScreen', 'The ObjectName should have be ' \ - 'splashScreen' - assert ss.frameSize() == QtCore.QSize(370, 370), 'The frameSize should be (370, 370)' - assert ss.contextMenuPolicy() == QtCore.Qt.PreventContextMenu, 'The ContextMenuPolicy ' \ - 'should have been QtCore.Qt.PreventContextMenu or 4' + ss = SplashScreen() + # THEN: Nothing should go wrong and the instance should have the correct values + assert ss.objectName() == 'splashScreen', 'The ObjectName should have be ' \ + 'splashScreen' + assert ss.frameSize() == QtCore.QSize(370, 370), 'The frameSize should be (370, 370)' + assert ss.contextMenuPolicy() == QtCore.Qt.PreventContextMenu, 'The ContextMenuPolicy ' \ + 'should have been QtCore.Qt.PreventContextMenu or 4' diff --git a/tests/functional/openlp_core/ui/test_style.py b/tests/functional/openlp_core/ui/test_style.py index 04df3525f..3fe7748c6 100644 --- a/tests/functional/openlp_core/ui/test_style.py +++ b/tests/functional/openlp_core/ui/test_style.py @@ -31,14 +31,13 @@ from openlp.core.ui.style import MEDIA_MANAGER_STYLE, WIN_REPAIR_STYLESHEET, get @skipIf(not hasattr(openlp.core.ui.style, 'qdarkstyle'), 'qdarkstyle is not installed') @patch('openlp.core.ui.style.HAS_DARK_STYLE', True) -@patch('openlp.core.ui.style.Settings') @patch('openlp.core.ui.style.qdarkstyle') -def test_get_application_stylesheet_dark(mocked_qdarkstyle, MockSettings): +def test_get_application_stylesheet_dark(mocked_qdarkstyle, mock_settings): """Test that the dark stylesheet is returned when available and enabled""" # GIVEN: We're on Windows and no dark style is set mocked_settings = MagicMock() mocked_settings.value.return_value = True - MockSettings.return_value = mocked_settings + mock_settings.return_value = mocked_settings mocked_qdarkstyle.load_stylesheet_pyqt5.return_value = 'dark_style' # WHEN: can_show_icon() is called diff --git a/tests/functional/openlp_core/ui/test_thememanager.py b/tests/functional/openlp_core/ui/test_thememanager.py index 449942b0d..d4ddbefe4 100644 --- a/tests/functional/openlp_core/ui/test_thememanager.py +++ b/tests/functional/openlp_core/ui/test_thememanager.py @@ -23,9 +23,9 @@ Package to test the openlp.core.ui.thememanager package. """ import os import shutil +import pytest from pathlib import Path from tempfile import mkdtemp -from unittest import TestCase from unittest.mock import ANY, Mock, MagicMock, patch, call from PyQt5 import QtWidgets @@ -35,341 +35,346 @@ from openlp.core.ui.thememanager import ThemeManager from tests.utils.constants import RESOURCE_PATH -class TestThemeManager(TestCase): +@pytest.yield_fixture() +def temp_folder(): + tmp_folder = mkdtemp() + yield tmp_folder + shutil.rmtree(tmp_folder) - def setUp(self): - """ - Set up the tests - """ - Registry.create() - self.temp_folder = mkdtemp() - def tearDown(self): - """ - Clean up - """ - shutil.rmtree(self.temp_folder) +@patch('openlp.core.ui.thememanager.zipfile.ZipFile.__init__') +@patch('openlp.core.ui.thememanager.zipfile.ZipFile.write') +def test_export_theme(mocked_zipfile_write, mocked_zipfile_init, registry): + """ + Test exporting a theme . + """ + # GIVEN: A new ThemeManager instance. + theme_manager = ThemeManager() + theme_manager.theme_path = RESOURCE_PATH / 'themes' + mocked_zipfile_init.return_value = None - @patch('openlp.core.ui.thememanager.zipfile.ZipFile.__init__') - @patch('openlp.core.ui.thememanager.zipfile.ZipFile.write') - def test_export_theme(self, mocked_zipfile_write, mocked_zipfile_init): - """ - Test exporting a theme . - """ - # GIVEN: A new ThemeManager instance. - theme_manager = ThemeManager() - theme_manager.theme_path = RESOURCE_PATH / 'themes' - mocked_zipfile_init.return_value = None + # WHEN: The theme is exported + theme_manager._export_theme(Path('some', 'path', 'Default.otz'), 'Default') - # WHEN: The theme is exported - theme_manager._export_theme(Path('some', 'path', 'Default.otz'), 'Default') + # THEN: The zipfile should be created at the given path + mocked_zipfile_init.assert_called_with(Path('some', 'path', 'Default.otz'), 'w') + mocked_zipfile_write.assert_called_with(RESOURCE_PATH / 'themes' / 'Default' / 'Default.xml', + Path('Default', 'Default.xml')) - # THEN: The zipfile should be created at the given path - mocked_zipfile_init.assert_called_with(Path('some', 'path', 'Default.otz'), 'w') - mocked_zipfile_write.assert_called_with(RESOURCE_PATH / 'themes' / 'Default' / 'Default.xml', - Path('Default', 'Default.xml')) - def test_initial_theme_manager(self): - """ - Test the instantiation of theme manager. - """ - # GIVEN: A new service manager instance. - ThemeManager(None) +def test_initial_theme_manager(registry): + """ + Test the instantiation of theme manager. + """ + # GIVEN: A new service manager instance. + ThemeManager(None) - # WHEN: the default theme manager is built. - # THEN: The the controller should be registered in the registry. - assert Registry().get('theme_manager') is not None, 'The base theme manager should be registered' + # WHEN: the default theme manager is built. + # THEN: The the controller should be registered in the registry. + assert Registry().get('theme_manager') is not None, 'The base theme manager should be registered' - @patch('openlp.core.ui.thememanager.shutil') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_same_image(self, mocked_create_paths, mocked_shutil): - """ - Test that we don't try to overwrite a theme background image with itself - """ - # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, - # theme, create_paths, thememanager-attributes and background - # .filename path is the same as the source path. + +@patch('openlp.core.ui.thememanager.shutil') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_same_image(mocked_create_paths, mocked_shutil, registry): + """ + Test that we don't try to overwrite a theme background image with itself + """ + # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, + # theme, create_paths, thememanager-attributes and background + # .filename path is the same as the source path. + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = None + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.extract_formatted_xml = MagicMock() + mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() + file_path_1 = RESOURCE_PATH / 'church.jpg' + mocked_theme.background_filename = file_path_1 + mocked_theme.background_source = file_path_1 + + # WHEN: Calling save_theme with both background paths to the same image + theme_manager.save_theme(mocked_theme) + + # THEN: The mocked_copyfile should not have been called + assert mocked_shutil.copyfile.called is False, 'copyfile should not be called' + + +@patch('openlp.core.ui.thememanager.shutil') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_diff_images(mocked_create_paths, mocked_shutil, registry): + """ + Test that we do overwrite a theme background image when a new is submitted + """ + # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, + # theme, create_paths, thememanager-attributes and background + # .filename path is the same as the source path. + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = None + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.background_filename = RESOURCE_PATH / 'church.jpg' + mocked_theme.background_source = RESOURCE_PATH / 'church2.jpg' + + # WHEN: Calling save_theme with both background paths to different images + theme_manager.save_theme(mocked_theme) + + # THEN: The mocked_copyfile should have been called + assert mocked_shutil.copyfile.called is True, 'copyfile should be called' + + +@patch('openlp.core.ui.thememanager.shutil') +@patch('openlp.core.ui.thememanager.delete_file') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_delete_old_image(mocked_create_paths, mocked_delete_file, mocked_shutil, registry): + """ + Test that we do delete a old theme background image when a new is submitted + """ + # GIVEN: A new theme manager instance, with mocked builtins.open, + # theme, create_paths, thememanager-attributes and background + # .filename path is the same as the source path. + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = RESOURCE_PATH / 'old_church.png' + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.background_filename = RESOURCE_PATH / 'church.jpg' + mocked_theme.background_source = RESOURCE_PATH / 'church2.jpg' + + # WHEN: Calling save_theme with both background paths to different images + theme_manager.save_theme(mocked_theme) + + # THEN: The mocked_delete_file should have been called to delete the old cached background + assert mocked_delete_file.called is True, 'delete_file should be called' + + +@patch.object(ThemeManager, 'log_exception') +@patch('openlp.core.ui.thememanager.delete_file') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_missing_original(mocked_paths, mocked_delete, mocked_log_exception, registry): + """ + Test that we revert to the old theme background image if the source is missing + when changing the theme. (User doesn't change background but the original is + missing) + """ + # GIVEN: A new theme manager instance, with invalid files. Setup as if the user + # has left the background the same, or reselected the same path. + # Not using resource dir because I could potentially copy a file + folder_path = Path(mkdtemp()) + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = folder_path / 'old.png' + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.background_filename = folder_path / 'old.png' + mocked_theme.background_source = folder_path / 'non_existent_original.png' + + # WHEN: Calling save_theme with a invalid background_filename + # Although all filenames are considered invalid in this test, + # it is important it reverts to the old background path as this in reality is always + # valid unless someone has messed with the cache. + theme_manager.save_theme(mocked_theme) + + # THEN: The old background should not have bee deleted + # AND the filename should have been replaced with the old cached background + # AND there is no exception + assert mocked_delete.called is False, 'delete_file should not be called' + assert mocked_theme.background_filename == theme_manager.old_background_image_path, \ + 'Background path should be reverted' + assert mocked_log_exception.called is False, \ + 'Should not have been an exception as the file wasn\'t changed' + + +@patch.object(ThemeManager, 'log_warning') +@patch('openlp.core.ui.thememanager.delete_file') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_missing_new(mocked_paths, mocked_delete, mocked_log_warning, registry): + """ + Test that we log a warning if the new background is missing + """ + # GIVEN: A new theme manager instance, with invalid files. Setup as if the user + # has changed the background to a invalid path. + # Not using resource dir because I could potentially copy a file + folder_path = Path(mkdtemp()) + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = folder_path / 'old.png' + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.background_filename = folder_path / 'new_cached.png' + mocked_theme.background_source = folder_path / 'new_original.png' + + # WHEN: Calling save_theme with a invalid background_filename + theme_manager.save_theme(mocked_theme) + + # THEN: A warning should have happened due to attempting to copy a missing file + mocked_log_warning.assert_called_once_with('Background does not exist, retaining cached background') + + +@patch('openlp.core.ui.thememanager.shutil') +@patch('openlp.core.ui.thememanager.delete_file') +@patch('openlp.core.ui.thememanager.create_paths') +def test_save_theme_background_override(mocked_paths, mocked_delete, mocked_shutil, registry): + """ + Test that we log a warning if the new background is missing + """ + # GIVEN: A new theme manager instance, with invalid files. Setup as if the user + # has changed the background to a invalid path. + # Not using resource dir because I could potentially copy a file + folder_path = Path(mkdtemp()) + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = folder_path / 'old.png' + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = MagicMock() + mocked_theme = MagicMock() + mocked_theme.theme_name = 'themename' + mocked_theme.background_filename = folder_path / 'new_cached.png' + # mocked_theme.background_source.exists() will return True + mocked_theme.background_source = MagicMock() + # override_background.exists() will return True + override_background = MagicMock() + + # WHEN: Calling save_theme with a background override + theme_manager.save_theme(mocked_theme, background_override=override_background) + + # THEN: The override_background should have been copied rather than the background_source + mocked_shutil.copyfile.assert_called_once_with(override_background, mocked_theme.background_filename) + + +def test_save_theme_special_char_name(registry, temp_folder): + """ + Test that we can save themes with special characters in the name + """ + # GIVEN: A new theme manager instance, with mocked theme and thememanager-attributes. + theme_manager = ThemeManager(None) + theme_manager.old_background_image_path = None + theme_manager.update_preview_images = MagicMock() + theme_manager.theme_path = Path(temp_folder) + mocked_theme = MagicMock() + mocked_theme.theme_name = 'theme 愛 name' + mocked_theme.export_theme.return_value = "{}" + + # WHEN: Calling save_theme with a theme with a name with special characters in it + theme_manager.save_theme(mocked_theme) + + # THEN: It should have been created + assert os.path.exists(os.path.join(temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \ + 'Theme with special characters should have been created!' + + +@patch('openlp.core.ui.thememanager.QtWidgets.QMessageBox.question', return_value=QtWidgets.QMessageBox.Yes) +@patch('openlp.core.ui.thememanager.translate') +def test_over_write_message_box_yes(mocked_translate, mocked_qmessagebox_question, registry): + """ + Test that theme_manager.over_write_message_box returns True when the user clicks yes. + """ + # GIVEN: A patched QMessageBox.question and an instance of ThemeManager + mocked_translate.side_effect = lambda context, text: text + theme_manager = ThemeManager(None) + + # WHEN: Calling over_write_message_box with 'Theme Name' + result = theme_manager.over_write_message_box('Theme Name') + + # THEN: over_write_message_box should return True and the message box should contain the theme name + assert result is True + mocked_qmessagebox_question.assert_called_once_with( + theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?', + defaultButton=ANY) + + +@patch('openlp.core.ui.thememanager.QtWidgets.QMessageBox.question', return_value=QtWidgets.QMessageBox.No) +@patch('openlp.core.ui.thememanager.translate') +def test_over_write_message_box_no(mocked_translate, mocked_qmessagebox_question, registry): + """ + Test that theme_manager.over_write_message_box returns False when the user clicks no. + """ + # GIVEN: A patched QMessageBox.question and an instance of ThemeManager + mocked_translate.side_effect = lambda context, text: text + theme_manager = ThemeManager(None) + + # WHEN: Calling over_write_message_box with 'Theme Name' + result = theme_manager.over_write_message_box('Theme Name') + + # THEN: over_write_message_box should return False and the message box should contain the theme name + assert result is False + mocked_qmessagebox_question.assert_called_once_with( + theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?', + defaultButton=ANY) + + +def test_unzip_theme(registry): + """ + Test that unzipping of themes works + """ + # GIVEN: A theme file, a output folder and some mocked out internal functions + with patch('openlp.core.ui.thememanager.critical_error_message_box') \ + as mocked_critical_error_message_box: theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = None + theme_manager._create_theme_from_xml = MagicMock() theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.extract_formatted_xml = MagicMock() - mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() - file_path_1 = RESOURCE_PATH / 'church.jpg' - mocked_theme.background_filename = file_path_1 - mocked_theme.background_source = file_path_1 - - # WHEN: Calling save_theme with both background paths to the same image - theme_manager.save_theme(mocked_theme) - - # THEN: The mocked_copyfile should not have been called - assert mocked_shutil.copyfile.called is False, 'copyfile should not be called' - - @patch('openlp.core.ui.thememanager.shutil') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_diff_images(self, mocked_create_paths, mocked_shutil): - """ - Test that we do overwrite a theme background image when a new is submitted - """ - # GIVEN: A new theme manager instance, with mocked builtins.open, copyfile, - # theme, create_paths, thememanager-attributes and background - # .filename path is the same as the source path. - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = None - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.background_filename = RESOURCE_PATH / 'church.jpg' - mocked_theme.background_source = RESOURCE_PATH / 'church2.jpg' - - # WHEN: Calling save_theme with both background paths to different images - theme_manager.save_theme(mocked_theme) - - # THEN: The mocked_copyfile should have been called - assert mocked_shutil.copyfile.called is True, 'copyfile should be called' - - @patch('openlp.core.ui.thememanager.shutil') - @patch('openlp.core.ui.thememanager.delete_file') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_delete_old_image(self, mocked_create_paths, mocked_delete_file, mocked_shutil): - """ - Test that we do delete a old theme background image when a new is submitted - """ - # GIVEN: A new theme manager instance, with mocked builtins.open, - # theme, create_paths, thememanager-attributes and background - # .filename path is the same as the source path. - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = RESOURCE_PATH / 'old_church.png' - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.background_filename = RESOURCE_PATH / 'church.jpg' - mocked_theme.background_source = RESOURCE_PATH / 'church2.jpg' - - # WHEN: Calling save_theme with both background paths to different images - theme_manager.save_theme(mocked_theme) - - # THEN: The mocked_delete_file should have been called to delete the old cached background - assert mocked_delete_file.called is True, 'delete_file should be called' - - @patch.object(ThemeManager, 'log_exception') - @patch('openlp.core.ui.thememanager.delete_file') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_missing_original(self, mocked_paths, mocked_delete, mocked_log_exception): - """ - Test that we revert to the old theme background image if the source is missing - when changing the theme. (User doesn't change background but the original is - missing) - """ - # GIVEN: A new theme manager instance, with invalid files. Setup as if the user - # has left the background the same, or reselected the same path. - # Not using resource dir because I could potentially copy a file + theme_manager.theme_path = None folder_path = Path(mkdtemp()) - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = folder_path / 'old.png' - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.background_filename = folder_path / 'old.png' - mocked_theme.background_source = folder_path / 'non_existent_original.png' + theme_file_path = RESOURCE_PATH / 'themes' / 'Moss_on_tree.otz' - # WHEN: Calling save_theme with a invalid background_filename - # Although all filenames are considered invalid in this test, - # it is important it reverts to the old background path as this in reality is always - # valid unless someone has messed with the cache. - theme_manager.save_theme(mocked_theme) + # WHEN: We try to unzip it + theme_manager.unzip_theme(theme_file_path, folder_path) - # THEN: The old background should not have bee deleted - # AND the filename should have been replaced with the old cached background - # AND there is no exception - assert mocked_delete.called is False, 'delete_file should not be called' - assert mocked_theme.background_filename == theme_manager.old_background_image_path, \ - 'Background path should be reverted' - assert mocked_log_exception.called is False, \ - 'Should not have been an exception as the file wasn\'t changed' + # THEN: Files should be unpacked + assert (folder_path / 'Moss on tree' / 'Moss on tree.xml').exists() is True + assert mocked_critical_error_message_box.call_count == 0, 'No errors should have happened' + shutil.rmtree(folder_path) - @patch.object(ThemeManager, 'log_warning') - @patch('openlp.core.ui.thememanager.delete_file') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_missing_new(self, mocked_paths, mocked_delete, mocked_log_warning): - """ - Test that we log a warning if the new background is missing - """ - # GIVEN: A new theme manager instance, with invalid files. Setup as if the user - # has changed the background to a invalid path. - # Not using resource dir because I could potentially copy a file - folder_path = Path(mkdtemp()) - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = folder_path / 'old.png' - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.background_filename = folder_path / 'new_cached.png' - mocked_theme.background_source = folder_path / 'new_original.png' - # WHEN: Calling save_theme with a invalid background_filename - theme_manager.save_theme(mocked_theme) +def test_unzip_theme_invalid_version(registry): + """ + Test that themes with invalid (< 2.0) or with no version attributes are rejected + """ + # GIVEN: An instance of ThemeManager whilst mocking a theme that returns a theme with no version attribute + with patch('openlp.core.ui.thememanager.zipfile.ZipFile') as mocked_zip_file,\ + patch('openlp.core.ui.thememanager.ElementTree.getroot') as mocked_getroot,\ + patch('openlp.core.ui.thememanager.XML'),\ + patch('openlp.core.ui.thememanager.critical_error_message_box') as mocked_critical_error_message_box: - # THEN: A warning should have happened due to attempting to copy a missing file - mocked_log_warning.assert_called_once_with('Background does not exist, retaining cached background') - - @patch('openlp.core.ui.thememanager.shutil') - @patch('openlp.core.ui.thememanager.delete_file') - @patch('openlp.core.ui.thememanager.create_paths') - def test_save_theme_background_override(self, mocked_paths, mocked_delete, mocked_shutil): - """ - Test that we log a warning if the new background is missing - """ - # GIVEN: A new theme manager instance, with invalid files. Setup as if the user - # has changed the background to a invalid path. - # Not using resource dir because I could potentially copy a file - folder_path = Path(mkdtemp()) - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = folder_path / 'old.png' - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = MagicMock() - mocked_theme = MagicMock() - mocked_theme.theme_name = 'themename' - mocked_theme.background_filename = folder_path / 'new_cached.png' - # mocked_theme.background_source.exists() will return True - mocked_theme.background_source = MagicMock() - # override_background.exists() will return True - override_background = MagicMock() - - # WHEN: Calling save_theme with a background override - theme_manager.save_theme(mocked_theme, background_override=override_background) - - # THEN: The override_background should have been copied rather than the background_source - mocked_shutil.copyfile.assert_called_once_with(override_background, mocked_theme.background_filename) - - def test_save_theme_special_char_name(self): - """ - Test that we can save themes with special characters in the name - """ - # GIVEN: A new theme manager instance, with mocked theme and thememanager-attributes. - theme_manager = ThemeManager(None) - theme_manager.old_background_image_path = None - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = Path(self.temp_folder) - mocked_theme = MagicMock() - mocked_theme.theme_name = 'theme 愛 name' - mocked_theme.export_theme.return_value = "{}" - - # WHEN: Calling save_theme with a theme with a name with special characters in it - theme_manager.save_theme(mocked_theme) - - # THEN: It should have been created - assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \ - 'Theme with special characters should have been created!' - - @patch('openlp.core.ui.thememanager.QtWidgets.QMessageBox.question', return_value=QtWidgets.QMessageBox.Yes) - @patch('openlp.core.ui.thememanager.translate') - def test_over_write_message_box_yes(self, mocked_translate, mocked_qmessagebox_question): - """ - Test that theme_manager.over_write_message_box returns True when the user clicks yes. - """ - # GIVEN: A patched QMessageBox.question and an instance of ThemeManager - mocked_translate.side_effect = lambda context, text: text + mocked_zip_file.return_value = MagicMock(**{'namelist.return_value': [os.path.join('theme', 'theme.xml')]}) + mocked_getroot.return_value = MagicMock(**{'get.return_value': None}) theme_manager = ThemeManager(None) - # WHEN: Calling over_write_message_box with 'Theme Name' - result = theme_manager.over_write_message_box('Theme Name') + # WHEN: unzip_theme is called + theme_manager.unzip_theme(Path('theme.file'), Path('folder')) - # THEN: over_write_message_box should return True and the message box should contain the theme name - assert result is True - mocked_qmessagebox_question.assert_called_once_with( - theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?', - defaultButton=ANY) + # THEN: The critical_error_message_box should have been called + assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once' - @patch('openlp.core.ui.thememanager.QtWidgets.QMessageBox.question', return_value=QtWidgets.QMessageBox.No) - @patch('openlp.core.ui.thememanager.translate') - def test_over_write_message_box_no(self, mocked_translate, mocked_qmessagebox_question): - """ - Test that theme_manager.over_write_message_box returns False when the user clicks no. - """ - # GIVEN: A patched QMessageBox.question and an instance of ThemeManager - mocked_translate.side_effect = lambda context, text: text - theme_manager = ThemeManager(None) - # WHEN: Calling over_write_message_box with 'Theme Name' - result = theme_manager.over_write_message_box('Theme Name') +def test_update_preview_images(registry): + """ + Test that the update_preview_images() method works correctly + """ + # GIVEN: A ThemeManager + def get_theme_data(value): + return '{}_theme_data'.format(value) + theme_manager = ThemeManager(None) + theme_manager.save_preview = MagicMock() + theme_manager._get_theme_data = Mock(side_effect=get_theme_data) + theme_manager.progress_form = MagicMock(**{'get_preview.return_value': 'preview'}) + theme_manager.load_themes = MagicMock() + theme_list = {'Default': get_theme_data('Default'), 'Test': get_theme_data('Test')} - # THEN: over_write_message_box should return False and the message box should contain the theme name - assert result is False - mocked_qmessagebox_question.assert_called_once_with( - theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?', - defaultButton=ANY) + # WHEN: ThemeManager.update_preview_images() is called + theme_manager.update_preview_images(theme_list) - def test_unzip_theme(self): - """ - Test that unzipping of themes works - """ - # GIVEN: A theme file, a output folder and some mocked out internal functions - with patch('openlp.core.ui.thememanager.critical_error_message_box') \ - as mocked_critical_error_message_box: - theme_manager = ThemeManager(None) - theme_manager._create_theme_from_xml = MagicMock() - theme_manager.update_preview_images = MagicMock() - theme_manager.theme_path = None - folder_path = Path(mkdtemp()) - theme_file_path = RESOURCE_PATH / 'themes' / 'Moss_on_tree.otz' - - # WHEN: We try to unzip it - theme_manager.unzip_theme(theme_file_path, folder_path) - - # THEN: Files should be unpacked - assert (folder_path / 'Moss on tree' / 'Moss on tree.xml').exists() is True - assert mocked_critical_error_message_box.call_count == 0, 'No errors should have happened' - shutil.rmtree(folder_path) - - def test_unzip_theme_invalid_version(self): - """ - Test that themes with invalid (< 2.0) or with no version attributes are rejected - """ - # GIVEN: An instance of ThemeManager whilst mocking a theme that returns a theme with no version attribute - with patch('openlp.core.ui.thememanager.zipfile.ZipFile') as mocked_zip_file,\ - patch('openlp.core.ui.thememanager.ElementTree.getroot') as mocked_getroot,\ - patch('openlp.core.ui.thememanager.XML'),\ - patch('openlp.core.ui.thememanager.critical_error_message_box') as mocked_critical_error_message_box: - - mocked_zip_file.return_value = MagicMock(**{'namelist.return_value': [os.path.join('theme', 'theme.xml')]}) - mocked_getroot.return_value = MagicMock(**{'get.return_value': None}) - theme_manager = ThemeManager(None) - - # WHEN: unzip_theme is called - theme_manager.unzip_theme(Path('theme.file'), Path('folder')) - - # THEN: The critical_error_message_box should have been called - assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once' - - def test_update_preview_images(self): - """ - Test that the update_preview_images() method works correctly - """ - # GIVEN: A ThemeManager - def get_theme_data(value): - return '{}_theme_data'.format(value) - theme_manager = ThemeManager(None) - theme_manager.save_preview = MagicMock() - theme_manager._get_theme_data = Mock(side_effect=get_theme_data) - theme_manager.progress_form = MagicMock(**{'get_preview.return_value': 'preview'}) - theme_manager.load_themes = MagicMock() - theme_list = {'Default': get_theme_data('Default'), 'Test': get_theme_data('Test')} - - # WHEN: ThemeManager.update_preview_images() is called - theme_manager.update_preview_images(theme_list) - - # THEN: Things should work right - assert theme_manager.progress_form.theme_list == theme_list - theme_manager.progress_form.show.assert_called_once_with() - assert theme_manager.progress_form.get_preview.call_args_list == [call('Default', get_theme_data('Default')), - call('Test', get_theme_data('Test'))] - assert theme_manager.save_preview.call_args_list == [call('Default', 'preview'), call('Test', 'preview')] - theme_manager.progress_form.close.assert_called_once_with() - theme_manager.load_themes.assert_called_once_with() + # THEN: Things should work right + assert theme_manager.progress_form.theme_list == theme_list + theme_manager.progress_form.show.assert_called_once_with() + assert theme_manager.progress_form.get_preview.call_args_list == [call('Default', get_theme_data('Default')), + call('Test', get_theme_data('Test'))] + assert theme_manager.save_preview.call_args_list == [call('Default', 'preview'), call('Test', 'preview')] + theme_manager.progress_form.close.assert_called_once_with() + theme_manager.load_themes.assert_called_once_with() diff --git a/tests/functional/openlp_core/widgets/test_views.py b/tests/functional/openlp_core/widgets/test_views.py index cab80674a..0168b7bea 100644 --- a/tests/functional/openlp_core/widgets/test_views.py +++ b/tests/functional/openlp_core/widgets/test_views.py @@ -32,7 +32,10 @@ from openlp.core.common.i18n import UiStrings from openlp.core.widgets.views import ListPreviewWidget, ListWidgetWithDnD, TreeWidgetWithDnD, handle_mime_data_urls from openlp.core.ui.icons import UiIcons -CLAPPERBOARD = UiIcons().clapperboard + +@pytest.fixture +def clapperboard(mock_settings): + return UiIcons().clapperboard @pytest.yield_fixture @@ -202,7 +205,7 @@ def test_replace_recalculate_layout_text(mocked_setRowHeight, mocked_resizeRowsT @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') def test_replace_recalculate_layout_img(mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." disabled, img slides unchanged in replace_service_item & __recalc... """ @@ -218,8 +221,8 @@ def test_replace_recalculate_layout_img(mocked_setRowHeight, mocked_resizeRowsTo service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) list_preview_widget.replace_service_item(service_item, 200, 0) @@ -242,7 +245,7 @@ def test_replace_recalculate_layout_img(mocked_setRowHeight, mocked_resizeRowsTo @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') def test_replace_recalculate_layout_img_max(mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." enabled, img slides resized in replace_service_item & __recalc... """ @@ -258,8 +261,8 @@ def test_replace_recalculate_layout_img_max(mocked_setRowHeight, mocked_resizeRo service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) list_preview_widget.replace_service_item(service_item, 200, 0) @@ -280,7 +283,7 @@ def test_replace_recalculate_layout_img_max(mocked_setRowHeight, mocked_resizeRo @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') def test_replace_recalculate_layout_img_auto(mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." auto, img slides resized in replace_service_item & __recalc... """ @@ -297,8 +300,8 @@ def test_replace_recalculate_layout_img_auto(mocked_setRowHeight, mocked_resizeR service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) list_preview_widget.replace_service_item(service_item, 200, 0) @@ -359,7 +362,7 @@ def test_row_resized_text(mocked_cellWidget, mocked_setRowHeight, mocked_resizeR @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @patch(u'openlp.core.widgets.views.ListPreviewWidget.cellWidget') def test_row_resized_img(mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." disabled, image-based slides not affected in row_resized. """ @@ -375,8 +378,8 @@ def test_row_resized_img(mocked_cellWidget, mocked_setRowHeight, mocked_resizeRo service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # Mock self.cellWidget().children().setMaximumWidth() mocked_cellWidget_child = MagicMock() mocked_cellWidget_obj = MagicMock() @@ -399,7 +402,7 @@ def test_row_resized_img(mocked_cellWidget, mocked_setRowHeight, mocked_resizeRo @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @patch(u'openlp.core.widgets.views.ListPreviewWidget.cellWidget') def test_row_resized_img_max(mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." enabled, image-based slides are scaled in row_resized. """ @@ -414,8 +417,8 @@ def test_row_resized_img_max(mocked_cellWidget, mocked_setRowHeight, mocked_resi service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # Mock self.cellWidget().children().setMaximumWidth() mocked_cellWidget_child = MagicMock() mocked_cellWidget_obj = MagicMock() @@ -436,7 +439,7 @@ def test_row_resized_img_max(mocked_cellWidget, mocked_setRowHeight, mocked_resi @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @patch(u'openlp.core.widgets.views.ListPreviewWidget.cellWidget') def test_row_resized_setting_changed(mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents, - preview_widget_env, mock_settings): + preview_widget_env, mock_settings, clapperboard): """ Test if "Max height for non-text slides..." enabled while item live, program doesn't crash on row_resized. """ @@ -452,8 +455,8 @@ def test_row_resized_setting_changed(mocked_cellWidget, mocked_setRowHeight, moc service_item = MagicMock() service_item.is_text.return_value = False service_item.is_capable.return_value = False - service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': CLAPPERBOARD}, - {'title': None, 'path': None, 'image': CLAPPERBOARD}] + service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': clapperboard}, + {'title': None, 'path': None, 'image': clapperboard}] # Mock self.cellWidget().children() mocked_cellWidget_obj = MagicMock() mocked_cellWidget_obj.children.return_value = None