""" Package to test the openlp.core.lib package. """ from unittest import TestCase from datetime import datetime, timedelta from mock import MagicMock, patch from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon, \ image_to_byte, check_item_selected, validate_thumb, create_separated_list, clean_tags, expand_tags class TestLib(TestCase): def str_to_bool_with_bool_test(self): """ Test the str_to_bool function with boolean input """ #GIVEN: A boolean value set to true true_boolean = True # WHEN: We "convert" it to a bool true_result = str_to_bool(true_boolean) # THEN: We should get back a True bool assert isinstance(true_result, bool), u'The result should be a boolean' assert true_result is True, u'The result should be True' #GIVEN: A boolean value set to false false_boolean = False # WHEN: We "convert" it to a bool false_result = str_to_bool(false_boolean) # THEN: We should get back a True bool assert isinstance(false_result, bool), u'The result should be a boolean' assert false_result is False, u'The result should be True' def str_to_bool_with_invalid_test(self): """ Test the str_to_bool function with a set of invalid inputs """ # GIVEN: An integer value int_string = 1 # WHEN: we convert it to a bool int_result = str_to_bool(int_string) # THEN: we should get back a false assert int_result is False, u'The result should be False' # GIVEN: An string value with completely invalid input invalid_string = u'my feet are wet' # WHEN: we convert it to a bool str_result = str_to_bool(invalid_string) # THEN: we should get back a false assert str_result is False, u'The result should be False' def str_to_bool_with_false_values_test(self): """ Test the str_to_bool function with a set of false inputs """ # GIVEN: A string set to "false" false_string = u'false' # WHEN: we convert it to a bool false_result = str_to_bool(false_string) # THEN: we should get back a false assert false_result is False, u'The result should be False' # GIVEN: An string set to "NO" no_string = u'NO' # WHEN: we convert it to a bool str_result = str_to_bool(no_string) # THEN: we should get back a false assert str_result is False, u'The result should be False' def str_to_bool_with_true_values_test(self): """ Test the str_to_bool function with a set of true inputs """ # GIVEN: A string set to "True" true_string = u'True' # WHEN: we convert it to a bool true_result = str_to_bool(true_string) # THEN: we should get back a true assert true_result is True, u'The result should be True' # GIVEN: An string set to "yes" yes_string = u'yes' # WHEN: we convert it to a bool str_result = str_to_bool(yes_string) # THEN: we should get back a true assert str_result is True, u'The result should be True' def translate_test(self): """ Test the translate() function """ # GIVEN: A string to translate and a mocked Qt translate function context = u'OpenLP.Tests' text = u'Untranslated string' comment = u'A comment' encoding = 1 n = 1 mocked_translate = MagicMock(return_value=u'Translated string') # WHEN: we call the translate function result = translate(context, text, comment, encoding, n, mocked_translate) # THEN: the translated string should be returned, and the mocked function should have been called mocked_translate.assert_called_with(context, text, comment, encoding, n) assert result == u'Translated string', u'The translated string should have been returned' def check_directory_exists_test(self): """ Test the check_directory_exists() function """ with patch(u'openlp.core.lib.os.path.exists') as mocked_exists, \ patch(u'openlp.core.lib.os.makedirs') as mocked_makedirs: # GIVEN: A directory to check and a mocked out os.makedirs and os.path.exists directory_to_check = u'existing/directory' # WHEN: os.path.exists returns True and we check to see if the directory exists mocked_exists.return_value = True check_directory_exists(directory_to_check) # THEN: Only os.path.exists should have been called mocked_exists.assert_called_with(directory_to_check) assert not mocked_makedirs.called, u'os.makedirs should not have been called' # WHEN: os.path.exists returns False and we check the directory exists mocked_exists.return_value = False check_directory_exists(directory_to_check) # THEN: Both the mocked functions should have been called mocked_exists.assert_called_with(directory_to_check) mocked_makedirs.assert_called_with(directory_to_check) # WHEN: os.path.exists raises an IOError mocked_exists.side_effect = IOError() check_directory_exists(directory_to_check) # THEN: We shouldn't get an exception though the mocked exists has been called mocked_exists.assert_called_with(directory_to_check) # WHEN: Some other exception is raised mocked_exists.side_effect = ValueError() # THEN: check_directory_exists raises an exception mocked_exists.assert_called_with(directory_to_check) self.assertRaises(ValueError, check_directory_exists, directory_to_check) def get_text_file_string_no_file_test(self): """ Test the get_text_file_string() function when a file does not exist """ with patch(u'openlp.core.lib.os.path.isfile') as mocked_isfile: # GIVEN: A mocked out isfile which returns true, and a text file name filename = u'testfile.txt' mocked_isfile.return_value = False # WHEN: get_text_file_string is called result = get_text_file_string(filename) # THEN: The result should be False mocked_isfile.assert_called_with(filename) assert result is False, u'False should be returned if no file exists' def get_text_file_string_read_error_test(self): """ Test the get_text_file_string() method when a read error happens """ with patch(u'openlp.core.lib.os.path.isfile') as mocked_isfile, patch(u'__builtin__.open') as mocked_open: # GIVEN: A mocked-out open() which raises an exception and isfile returns True filename = u'testfile.txt' mocked_isfile.return_value = True mocked_open.side_effect = IOError() # WHEN: get_text_file_string is called result = get_text_file_string(filename) # THEN: None should be returned mocked_isfile.assert_called_with(filename) mocked_open.assert_called_with(filename, u'r') assert result is None, u'None should be returned if the file cannot be opened' def get_text_file_string_decode_error_test(self): """ Test the get_text_file_string() method when the contents cannot be decoded """ assert True, u'Impossible to test due to conflicts when mocking out the "open" function' def build_icon_with_qicon_test(self): """ Test the build_icon() function with a QIcon instance """ with patch(u'openlp.core.lib.QtGui') as MockedQtGui: # GIVEN: A mocked QIcon MockedQtGui.QIcon = MagicMock mocked_icon = MockedQtGui.QIcon() # WHEN: We pass a QIcon instance in result = build_icon(mocked_icon) # THEN: The result should be our mocked QIcon assert result is mocked_icon, u'The result should be the mocked QIcon' def build_icon_with_resource_test(self): """ Test the build_icon() function with a resource URI """ with patch(u'openlp.core.lib.QtGui') as MockedQtGui, \ patch(u'openlp.core.lib.QtGui.QPixmap') as MockedQPixmap: # GIVEN: A mocked QIcon and a mocked QPixmap MockedQtGui.QIcon = MagicMock MockedQtGui.QIcon.Normal = 1 MockedQtGui.QIcon.Off = 2 MockedQPixmap.return_value = u'mocked_pixmap' resource_uri = u':/resource/uri' # WHEN: We pass a QIcon instance in result = build_icon(resource_uri) # THEN: The result should be our mocked QIcon MockedQPixmap.assert_called_with(resource_uri) # There really should be more assert statements here but due to type checking and things they all break. The # best we can do is to assert that we get back a MagicMock object. assert isinstance(result, MagicMock), u'The result should be a MagicMock, because we mocked it out' def image_to_byte_test(self): """ Test the image_to_byte() function """ with patch(u'openlp.core.lib.QtCore') as MockedQtCore: # GIVEN: A set of mocked-out Qt classes mocked_byte_array = MagicMock() MockedQtCore.QByteArray.return_value = mocked_byte_array mocked_byte_array.toBase64.return_value = u'base64mock' mocked_buffer = MagicMock() MockedQtCore.QBuffer.return_value = mocked_buffer MockedQtCore.QIODevice.WriteOnly = u'writeonly' mocked_image = MagicMock() # WHEN: We convert an image to a byte array result = image_to_byte(mocked_image) # THEN: We should receive a value of u'base64mock' MockedQtCore.QByteArray.assert_called_with() MockedQtCore.QBuffer.assert_called_with(mocked_byte_array) mocked_buffer.open.assert_called_with(u'writeonly') mocked_image.save.assert_called_with(mocked_buffer, "PNG") mocked_byte_array.toBase64.assert_called_with() assert result == u'base64mock', u'The result should be the return value of the mocked out base64 method' def check_item_selected_true_test(self): """ Test that the check_item_selected() function returns True when there are selected indexes. """ # GIVEN: A mocked out QtGui module and a list widget with selected indexes MockedQtGui = patch(u'openlp.core.lib.QtGui') mocked_list_widget = MagicMock() mocked_list_widget.selectedIndexes.return_value = True message = u'message' # WHEN: We check if there are selected items result = check_item_selected(mocked_list_widget, message) # THEN: The selectedIndexes function should have been called and the result should be true mocked_list_widget.selectedIndexes.assert_called_with() assert result, u'The result should be True' def check_item_selected_false_test(self): """ Test that the check_item_selected() function returns False when there are no selected indexes. """ # GIVEN: A mocked out QtGui module and a list widget with selected indexes with patch(u'openlp.core.lib.QtGui') as MockedQtGui, \ patch(u'openlp.core.lib.translate') as mocked_translate: mocked_translate.return_value = u'mocked translate' mocked_list_widget = MagicMock() mocked_list_widget.selectedIndexes.return_value = False mocked_list_widget.parent.return_value = u'parent' message = u'message' # WHEN: We check if there are selected items result = check_item_selected(mocked_list_widget, message) # THEN: The selectedIndexes function should have been called and the result should be true mocked_list_widget.selectedIndexes.assert_called_with() MockedQtGui.QMessageBox.information.assert_called_with(u'parent', u'mocked translate', 'message') assert not result, u'The result should be False' def clean_tags_test(self): """ Test clean_tags() method. """ with patch(u'openlp.core.lib.FormattingTags.get_html_tags') as mocked_get_tags: # GIVEN: Mocked get_html_tags() method. mocked_get_tags.return_value = [{ u'desc': u'Black', u'start tag': u'{b}', u'start html': u'', u'end tag': u'{/b}', u'end html': u'', u'protected': True, u'temporary': False }] string_to_pass = u'ASDF
foo{br}bar {b}black{/b}' wanted_string = u'ASDF\nfoo\nbar black' # WHEN: Clean the string. result_string = clean_tags(string_to_pass) # THEN: The strings should be identical. assert result_string == wanted_string, u'The strings should be identical.' def expand_tags_test(self): """ Test the expand_tags() method. """ with patch(u'openlp.core.lib.FormattingTags.get_html_tags') as mocked_get_tags: # GIVEN: Mocked get_html_tags() method. mocked_get_tags.return_value = [ { u'desc': u'Black', u'start tag': u'{b}', u'start html': u'', u'end tag': u'{/b}', u'end html': u'', u'protected': True, u'temporary': False }, { u'desc': u'Yellow', u'start tag': u'{y}', u'start html': u'', u'end tag': u'{/y}', u'end html': u'', u'protected': True, u'temporary': False }, { u'desc': u'Green', u'start tag': u'{g}', u'start html': u'', u'end tag': u'{/g}', u'end html': u'', u'protected': True, u'temporary': False } ] string_to_pass = u'{b}black{/b}{y}yellow{/y}' wanted_string = u'black' + \ 'yellow' # WHEN: Replace the tags. result_string = expand_tags(string_to_pass) # THEN: The strings should be identical. assert result_string == wanted_string, u'The strings should be identical.' def validate_thumb_file_does_not_exist_test(self): """ Test the validate_thumb() function when the thumbnail does not exist """ # GIVEN: A mocked out os module, with path.exists returning False, and fake paths to a file and a thumb with patch(u'openlp.core.lib.os') as mocked_os: file_path = u'path/to/file' thumb_path = u'path/to/thumb' mocked_os.path.exists.return_value = False # WHEN: we run the validate_thumb() function result = validate_thumb(file_path, thumb_path) # THEN: we should have called a few functions, and the result should be False mocked_os.path.exists.assert_called_with(thumb_path) assert result is False, u'The result should be False' def validate_thumb_file_exists_and_newer_test(self): """ Test the validate_thumb() function when the thumbnail exists and has a newer timestamp than the file """ # GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb with patch(u'openlp.core.lib.os') as mocked_os: file_path = u'path/to/file' thumb_path = u'path/to/thumb' file_mocked_stat = MagicMock() file_mocked_stat.st_mtime = datetime.now() thumb_mocked_stat = MagicMock() thumb_mocked_stat.st_mtime = datetime.now() + timedelta(seconds=10) mocked_os.path.exists.return_value = True mocked_os.stat.side_effect = [file_mocked_stat, thumb_mocked_stat] # WHEN: we run the validate_thumb() function # THEN: we should have called a few functions, and the result should be True #mocked_os.path.exists.assert_called_with(thumb_path) def validate_thumb_file_exists_and_older_test(self): """ Test the validate_thumb() function when the thumbnail exists but is older than the file """ # GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb with patch(u'openlp.core.lib.os') as mocked_os: file_path = u'path/to/file' thumb_path = u'path/to/thumb' file_mocked_stat = MagicMock() file_mocked_stat.st_mtime = datetime.now() thumb_mocked_stat = MagicMock() thumb_mocked_stat.st_mtime = datetime.now() - timedelta(seconds=10) mocked_os.path.exists.return_value = True mocked_os.stat.side_effect = lambda fname: file_mocked_stat if fname == file_path else thumb_mocked_stat # WHEN: we run the validate_thumb() function result = validate_thumb(file_path, thumb_path) # THEN: we should have called a few functions, and the result should be False mocked_os.path.exists.assert_called_with(thumb_path) mocked_os.stat.assert_any_call(file_path) mocked_os.stat.assert_any_call(thumb_path) assert result is False, u'The result should be False' def create_separated_list_qlocate_test(self): """ Test the create_separated_list function using the Qt provided method. """ with patch(u'openlp.core.lib.Qt') as mocked_qt, \ patch(u'openlp.core.lib.QtCore.QLocale.createSeparatedList') as mocked_createSeparatedList: # GIVEN: A list of strings and the mocked Qt module. mocked_qt.PYQT_VERSION_STR = u'4.9' mocked_qt.qVersion.return_value = u'4.8' mocked_createSeparatedList.return_value = u'Author 1, Author 2, and Author 3' string_list = [u'Author 1', u'Author 2', u'Author 3'] # WHEN: We get a string build from the entries it the list and a separator. string_result = create_separated_list(string_list) # THEN: We should have "Author 1, Author 2, and Author 3" assert string_result == u'Author 1, Author 2, and Author 3', u'The string should be u\'Author 1, ' \ 'Author 2, and Author 3\'.' def create_separated_list_empty_list_test(self): """ Test the create_separated_list function with an empty list. """ with patch(u'openlp.core.lib.Qt') as mocked_qt: # GIVEN: An empty list and the mocked Qt module. mocked_qt.PYQT_VERSION_STR = u'4.8' mocked_qt.qVersion.return_value = u'4.7' string_list = [] # WHEN: We get a string build from the entries it the list and a separator. string_result = create_separated_list(string_list) # THEN: We shoud have an emptry string. assert string_result == u'', u'The string sould be empty.' def create_separated_list_with_one_item_test(self): """ Test the create_separated_list function with a list consisting of only one entry. """ with patch(u'openlp.core.lib.Qt') as mocked_qt: # GIVEN: A list with a string and the mocked Qt module. mocked_qt.PYQT_VERSION_STR = u'4.8' mocked_qt.qVersion.return_value = u'4.7' string_list = [u'Author 1'] # WHEN: We get a string build from the entries it the list and a separator. string_result = create_separated_list(string_list) # THEN: We should have "Author 1" assert string_result == u'Author 1', u'The string should be u\'Author 1\'.' def create_separated_list_with_two_items_test(self): """ Test the create_separated_list function with a list of two entries. """ with patch(u'openlp.core.lib.Qt') as mocked_qt, patch(u'openlp.core.lib.translate') as mocked_translate: # GIVEN: A list of strings and the mocked Qt module. mocked_qt.PYQT_VERSION_STR = u'4.8' mocked_qt.qVersion.return_value = u'4.7' mocked_translate.return_value = u'%s and %s' string_list = [u'Author 1', u'Author 2'] # WHEN: We get a string build from the entries it the list and a seperator. string_result = create_separated_list(string_list) # THEN: We should have "Author 1 and Author 2" assert string_result == u'Author 1 and Author 2', u'The string should be u\'Author 1 and Author 2\'.' def create_separated_list_with_three_items_test(self): """ Test the create_separated_list function with a list of three items. """ with patch(u'openlp.core.lib.Qt') as mocked_qt, patch(u'openlp.core.lib.translate') as mocked_translate: # GIVEN: A list with a string and the mocked Qt module. mocked_qt.PYQT_VERSION_STR = u'4.8' mocked_qt.qVersion.return_value = u'4.7' # Always return the untranslated string. mocked_translate.side_effect = lambda module, string_to_translate, comment: string_to_translate string_list = [u'Author 1', u'Author 2', u'Author 3'] # WHEN: We get a string build from the entries it the list and a seperator. string_result = create_separated_list(string_list) # THEN: We should have "Author 1, Author 2, and Author 3" assert string_result == u'Author 1, Author 2, and Author 3', u'The string should be u\'Author 1, ' \ 'Author 2, and Author 3\'.'