# -*- coding: utf-8 -*- # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # # Copyright (c) 2008-2017 OpenLP Developers # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # # Software Foundation; version 2 of the License. # # # # This program is distributed in the hope that it will be useful, but WITHOUT # # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # # more details. # # # # You should have received a copy of the GNU General Public License along # # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ Package to test the openlp.core.ui.firsttimeform package. """ import os import socket import tempfile import urllib from unittest import TestCase from openlp.core.common import Registry from openlp.core.ui.firsttimeform import FirstTimeForm from tests.functional import MagicMock, patch from tests.helpers.testmixin import TestMixin FAKE_CONFIG = b""" [general] base url = http://example.com/frw/ [songs] directory = songs [bibles] directory = bibles [themes] directory = themes """ FAKE_BROKEN_CONFIG = b""" [general] base url = http://example.com/frw/ [songs] directory = songs [bibles] directory = bibles """ FAKE_INVALID_CONFIG = b""" This is not a config file Some text """ class TestFirstTimeForm(TestCase, TestMixin): 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) self.tempfile = os.path.join(tempfile.gettempdir(), 'testfile') def tearDown(self): if os.path.isfile(self.tempfile): os.remove(self.tempfile) @patch('openlp.core.ui.firsttimewizard.is_macosx') def constructor_macosx_test(self, mocked_is_macosx): """ Test that the form is resized correctly on OS X """ # GIVEN: The platform is OS X mocked_is_macosx.return_value = True # WHEN: The wizard is created frw = FirstTimeForm(None) # THEN: The form should have been resized size = frw.size() self.assertEqual(634, size.width()) self.assertEqual(386, size.height()) def initialise_test(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) # THEN: The screens should be set up, and the default values initialised self.assertEqual(expected_screens, frw.screens, 'The screens should be correct') self.assertTrue(frw.web_access, 'The default value of self.web_access should be True') self.assertFalse(frw.was_cancelled, 'The default value of self.was_cancelled should be False') self.assertListEqual([], frw.theme_screenshot_threads, 'The list of threads should be empty') self.assertListEqual([], frw.theme_screenshot_workers, 'The list of workers should be empty') self.assertFalse(frw.has_run_wizard, 'has_run_wizard should be False') def set_defaults_test(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()) with patch.object(frw, 'restart') as mocked_restart, \ patch.object(frw, 'cancel_button') as mocked_cancel_button, \ patch.object(frw, 'no_internet_finish_button') as mocked_no_internet_finish_btn, \ patch.object(frw, 'currentIdChanged') as mocked_currentIdChanged, \ patch.object(Registry, 'register_function') as mocked_register_function, \ patch('openlp.core.ui.firsttimeform.Settings') as MockedSettings, \ patch('openlp.core.ui.firsttimeform.gettempdir') as mocked_gettempdir, \ patch('openlp.core.ui.firsttimeform.check_directory_exists') as mocked_check_directory_exists, \ patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: mocked_settings = MagicMock() mocked_settings.value.return_value = True MockedSettings.return_value = mocked_settings mocked_gettempdir.return_value = 'temp' expected_temp_path = os.path.join('temp', 'openlp') # WHEN: The set_defaults() method is run frw.set_defaults() # THEN: The default values should have been set mocked_restart.assert_called_with() self.assertEqual('http://openlp.org/files/frw/', frw.web, 'The default URL should be set') mocked_cancel_button.clicked.connect.assert_called_with(frw.on_cancel_button_clicked) mocked_no_internet_finish_btn.clicked.connect.assert_called_with(frw.on_no_internet_finish_button_clicked) mocked_currentIdChanged.connect.assert_called_with(frw.on_current_id_changed) mocked_register_function.assert_called_with('config_screen_changed', frw.update_screen_list_combo) mocked_no_internet_finish_btn.setVisible.assert_called_with(False) mocked_settings.value.assert_called_with('core/has run wizard') mocked_gettempdir.assert_called_with() mocked_check_directory_exists.assert_called_with(expected_temp_path) def update_screen_list_combo_test(self): """ Test that the update_screen_list_combo() method works correctly """ # GIVEN: A mocked Screen() object and an initialised First Run Wizard and a mocked display_combo_box expected_screen_list = ['Screen 1', 'Screen 2'] mocked_screens = MagicMock() mocked_screens.get_screen_list.return_value = expected_screen_list frw = FirstTimeForm(None) frw.initialize(mocked_screens) with patch.object(frw, 'display_combo_box') as mocked_display_combo_box: mocked_display_combo_box.count.return_value = 2 # WHEN: update_screen_list_combo() is called frw.update_screen_list_combo() # THEN: The combobox should have been updated mocked_display_combo_box.clear.assert_called_with() mocked_screens.get_screen_list.assert_called_with() mocked_display_combo_box.addItems.assert_called_with(expected_screen_list) mocked_display_combo_box.count.assert_called_with() mocked_display_combo_box.setCurrentIndex.assert_called_with(1) def on_cancel_button_clicked_test(self): """ Test that the cancel button click slot shuts down the threads correctly """ # GIVEN: A FRW, some mocked threads and workers (that isn't quite done) and other mocked stuff frw = FirstTimeForm(None) frw.initialize(MagicMock()) mocked_worker = MagicMock() mocked_thread = MagicMock() mocked_thread.isRunning.side_effect = [True, False] frw.theme_screenshot_workers.append(mocked_worker) frw.theme_screenshot_threads.append(mocked_thread) with patch('openlp.core.ui.firsttimeform.time') as mocked_time, \ patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: # WHEN: on_cancel_button_clicked() is called frw.on_cancel_button_clicked() # THEN: The right things should be called in the right order self.assertTrue(frw.was_cancelled, 'The was_cancelled property should have been set to True') mocked_worker.set_download_canceled.assert_called_with(True) mocked_thread.isRunning.assert_called_with() self.assertEqual(2, mocked_thread.isRunning.call_count, 'isRunning() should have been called twice') mocked_time.sleep.assert_called_with(0.1) self.assertEqual(1, mocked_time.sleep.call_count, 'sleep() should have only been called once') mocked_set_normal_cursor.assert_called_with() def broken_config_test(self): """ Test if we can handle an config file with missing data """ # GIVEN: A mocked get_web_page, a First Time Wizard, an expected screen object, and a mocked broken config file with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page: first_time_form = FirstTimeForm(None) first_time_form.initialize(MagicMock()) mocked_get_web_page.return_value.read.return_value = FAKE_BROKEN_CONFIG # WHEN: The First Time Wizard is downloads the config file first_time_form._download_index() # THEN: The First Time Form should not have web access self.assertFalse(first_time_form.web_access, 'There should not be web access with a broken config file') def invalid_config_test(self): """ Test if we can handle an config file in invalid format """ # GIVEN: A mocked get_web_page, a First Time Wizard, an expected screen object, and a mocked invalid config file with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page: first_time_form = FirstTimeForm(None) first_time_form.initialize(MagicMock()) mocked_get_web_page.return_value.read.return_value = FAKE_INVALID_CONFIG # WHEN: The First Time Wizard is downloads the config file first_time_form._download_index() # THEN: The First Time Form should not have web access self.assertFalse(first_time_form.web_access, 'There should not be web access with an invalid config file') @patch('openlp.core.ui.firsttimeform.get_web_page') @patch('openlp.core.ui.firsttimeform.QtWidgets.QMessageBox') def network_error_test(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 = urllib.error.HTTPError(url='http//localhost', code=407, msg='Network proxy error', hdrs=None, fp=None) # 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 self.assertEquals(mocked_message_box.mock_calls[1][1][0], 'Network Error 407', 'first_time_form should have caught Network Error') @patch('openlp.core.ui.firsttimeform.urllib.request.urlopen') def socket_timeout_test(self, mocked_urlopen): """ Test socket timeout gets caught """ # GIVEN: Mocked urlopen to fake a network disconnect in the middle of a download first_time_form = FirstTimeForm(None) first_time_form.initialize(MagicMock()) mocked_urlopen.side_effect = socket.timeout() # WHEN: Attempt to retrieve a file first_time_form.url_get_file(url='http://localhost/test', f_path=self.tempfile) # THEN: socket.timeout should have been caught # NOTE: Test is if $tmpdir/tempfile is still there, then test fails since ftw deletes bad downloaded files self.assertFalse(os.path.exists(self.tempfile), 'FTW url_get_file should have caught socket.timeout')