def process_books_completes_test(self): """ Test process_books when it processes all books """ # GIVEN: An instance of OpenSongBible Importer and two mocked books self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2'] with patch.object(OpenSongBible, 'process_chapters') as mocked_process_chapters: importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') book1 = MagicMock() book1.attrib = {'n': 'Name1'} book1.c = 'Chapter1' book2 = MagicMock() book2.attrib = {'n': 'Name2'} book2.c = 'Chapter2' importer.language_id = 10 importer.session = MagicMock() importer.stop_import_flag = False # WHEN: Calling process_books with the two books importer.process_books([book1, book2]) # THEN: find_and_create_book and process_books should be called with the details from the mocked books self.assertEqual(self.mocked_find_and_create_book.call_args_list, [call('Name1', 2, 10), call('Name2', 2, 10)]) self.assertEqual( mocked_process_chapters.call_args_list, [call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')]) self.assertEqual(importer.session.commit.call_count, 2)
def parse_options_from_sys_argv_test(self, MockedOptionParser): """ Test that parse_options sets up OptionParser correctly and parses sys.argv """ # GIVEN: A list of valid options and a mocked out OptionParser object mocked_parser = MagicMock() MockedOptionParser.return_value = mocked_parser expected_calls = [ call('-e', '--no-error-form', dest='no_error_form', action='store_true', help='Disable the error notification form.'), call('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL', help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".'), call('-p', '--portable', dest='portable', action='store_true', help='Specify if this should be run as a portable app, off a USB flash drive (not implemented).'), call('-d', '--dev-version', dest='dev_version', action='store_true', help='Ignore the version file and pull the version directly from Bazaar'), call('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).') ] # WHEN: Calling parse_options parse_options([]) # THEN: A tuple should be returned with the parsed options and left over options MockedOptionParser.assert_called_with(usage='Usage: %prog [options] [qt-options]') self.assertEquals(expected_calls, mocked_parser.add_option.call_args_list) mocked_parser.parse_args.assert_called_with()
def test_on_new_clicked(self): """ 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 # 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) ] self.assertEqual(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)
def test_process_chapters(self, mocked_open, mocked_os): """ Test the process_chapters() method """ # GIVEN: A WordProject importer and a bunch of mocked things importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip') importer.base_dir = '' importer.stop_import_flag = False importer.language_id = 'en' mocked_open.return_value.__enter__.return_value.read.return_value = CHAPTER_PAGE mocked_os.path.join.side_effect = lambda *x: ''.join(x) mocked_os.path.normpath.side_effect = lambda x: x mocked_db_book = MagicMock() mocked_db_book.name = 'Genesis' book_id = 1 book_link = '01/1.htm' # WHEN: process_chapters() is called with patch.object(importer, 'set_current_chapter') as mocked_set_current_chapter, \ patch.object(importer, 'process_verses') as mocked_process_verses: importer.process_chapters(mocked_db_book, book_id, book_link) # THEN: The right methods should have been called expected_set_current_chapter_calls = [call('Genesis', ch) for ch in range(1, 51)] expected_process_verses_calls = [call(mocked_db_book, 1, ch) for ch in range(1, 51)] mocked_os.path.join.assert_called_once_with('', '01/1.htm') mocked_open.assert_called_once_with('01/1.htm', encoding='utf-8', errors='ignore') assert mocked_set_current_chapter.call_args_list == expected_set_current_chapter_calls assert mocked_process_verses.call_args_list == expected_process_verses_calls
def test_replace_recalculate_layout_img_auto(self, mocked_setRowHeight, mocked_resizeRowsToContents): """ Test if "Max height for non-text slides..." auto, img slides resized in replace_service_item & __recalc... """ # GIVEN: A setting to adjust "Max height for non-text slides in slide controller", # an image ServiceItem and a ListPreviewWidget. # Mock Settings().value('advanced/slide max height') self.mocked_Settings_obj.value.return_value = -4 # Mock self.viewport().width() self.mocked_viewport_obj.width.return_value = 200 self.mocked_viewport_obj.height.return_value = 600 # Mock image service item 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': None}, {'title': None, 'path': None, 'image': None}] # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) list_preview_widget.replace_service_item(service_item, 200, 0) # Change viewport width before forcing a resize self.mocked_viewport_obj.width.return_value = 400 # WHEN: __recalculate_layout() is called (via screen_size_changed) list_preview_widget.screen_size_changed(1) self.mocked_viewport_obj.height.return_value = 200 list_preview_widget.screen_size_changed(1) # THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called # twice for each slide. self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called') self.assertEquals(mocked_setRowHeight.call_count, 6, 'Should be called 3 times for each slide') calls = [call(0, 100), call(1, 100), call(0, 150), call(1, 150), call(0, 100), call(1, 100)] mocked_setRowHeight.assert_has_calls(calls)
def do_import_success_test(self): """ Test do_import when the import succeeds """ # GIVEN: An instance of CSVBible mocked_manager = MagicMock() with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'): importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv') importer.get_language = MagicMock(return_value=10) importer.parse_csv_file = MagicMock( side_effect=[['Book 1'], ['Verse 1']]) importer.process_books = MagicMock(return_value=['Book 1']) importer.process_verses = MagicMock(return_value=['Verse 1']) importer.session = MagicMock() importer.stop_import_flag = False importer.wizard = MagicMock() # WHEN: Calling do_import result = importer.do_import('Bible Name') # THEN: parse_csv_file should be called twice, # and True should be returned. self.assertEqual( importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)]) importer.process_books.assert_called_once_with(['Book 1']) importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1']) self.assertTrue(result)
def test_autoscroll_normal(self, mocked_slide_count, mocked_item, mocked_scrollToItem, mocked_selectRow): """ Test if 'advanced/autoscrolling' setting valid, autoscrolling called as expected. """ # GIVEN: A setting for autoscrolling and a ListPreviewWidget. # Mock Settings().value('advanced/autoscrolling') self.mocked_Settings_obj.value.return_value = {'dist': -1, 'pos': 1} # Mocked returns mocked_slide_count.return_value = 3 mocked_item.return_value = None # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) # WHEN: change_slide() is called list_preview_widget.change_slide(1) self.mocked_Settings_obj.value.return_value = {'dist': 0, 'pos': 1} list_preview_widget.change_slide(1) self.mocked_Settings_obj.value.return_value = {'dist': 1, 'pos': 1} list_preview_widget.change_slide(1) # THEN: no further functions should be called self.assertEquals(mocked_slide_count.call_count, 3, 'Should be called') self.assertEquals(mocked_scrollToItem.call_count, 3, 'Should be called') self.assertEquals(mocked_selectRow.call_count, 3, 'Should be called') self.assertEquals(mocked_item.call_count, 3, 'Should be called') calls = [call(0, 0), call(1, 0), call(2, 0)] mocked_item.assert_has_calls(calls)
def process_books_test(self): """ Test process books when it completes successfully """ # GIVEN: An instance of CSVBible with the stop_import_flag set to False, and some sample data mocked_manager = MagicMock() with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv') importer.find_and_create_book = MagicMock() importer.language_id = 10 importer.stop_import_flag = False importer.wizard = MagicMock() books = [ Book('1', '1', '1. Mosebog', '1Mos'), Book('2', '1', '2. Mosebog', '2Mos') ] # WHEN: Calling process_books result = importer.process_books(books) # THEN: translate and find_and_create_book should have been called with both book names. # The returned data should be a dictionary with both song's id and names. self.assertEqual( importer.find_and_create_book.mock_calls, [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)]) self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'})
def test_returned_file_list(self): """ Test that FileDialog.getOpenFileNames handles a list of files properly when QFileList.getOpenFileNames returns a good file name, a url encoded file name and a non-existing file """ self.mocked_os.rest_mock() self.mocked_qt_gui.reset_mock() # GIVEN: A List of known values as a return value from QFileDialog.getOpenFileNames and a list of valid file # names. self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = ([ '/Valid File', '/url%20encoded%20file%20%231', '/non-existing'], []) self.mocked_os.path.exists.side_effect = lambda file_name: file_name in [ '/Valid File', '/url encoded file #1'] self.mocked_ui_strings().FileNotFound = 'File Not Found' self.mocked_ui_strings().FileNotFoundMessage = 'File {name} not found.\nPlease try selecting it individually.' # WHEN: FileDialog.getOpenFileNames is called result = FileDialog.getOpenFileNames(self.mocked_parent) # THEN: os.path.exists should have been called with known args. QmessageBox.information should have been # called. The returned result should correlate with the input. call_list = [call('/Valid File'), call('/url%20encoded%20file%20%231'), call('/url encoded file #1'), call('/non-existing'), call('/non-existing')] self.mocked_os.path.exists.assert_has_calls(call_list) self.mocked_qt_gui.QMessageBox.information.assert_called_with( self.mocked_parent, 'File Not Found', 'File /non-existing not found.\nPlease try selecting it individually.') self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')
def test_update_ui_dvd(self, mocked_get_vlc): """ Test updating the UI for a CD or DVD """ # GIVEN: A whole bunch of mocks mocked_vlc = MagicMock() mocked_vlc.State.Ended = 1 mocked_get_vlc.return_value = mocked_vlc mocked_controller = MagicMock() mocked_controller.media_info.start_time = 100 mocked_controller.media_info.end_time = 300 mocked_controller.seek_slider.isSliderDown.return_value = False mocked_display = MagicMock() mocked_display.controller = mocked_controller mocked_display.vlc_media.get_state.return_value = 1 mocked_display.vlc_media_player.get_time.return_value = 400000 mocked_display.controller.media_info.media_type = MediaType.DVD vlc_player = VlcPlayer(None) # WHEN: update_ui() is called with patch.object(vlc_player, 'stop') as mocked_stop, \ patch.object(vlc_player, 'set_visible') as mocked_set_visible: vlc_player.update_ui(mocked_display) # THEN: Certain methods should be called mocked_stop.assert_called_with(mocked_display) self.assertEqual(2, mocked_stop.call_count) mocked_display.vlc_media_player.get_time.assert_called_with() mocked_set_visible.assert_called_with(mocked_display, False) mocked_controller.seek_slider.setSliderPosition.assert_called_with( 300000) expected_calls = [call(True), call(False)] self.assertEqual( expected_calls, mocked_controller.seek_slider.blockSignals.call_args_list)
def process_books_completes_test(self): """ Test process_books when it processes all books """ # GIVEN: An instance of OSISBible Importer and two mocked books self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2'] with patch.object(OSISBible, 'process_chapters') as mocked_process_chapters: importer = OSISBible(MagicMock(), path='.', name='.', filename='') book1 = MagicMock() book1.get.return_value = 'Name1' book2 = MagicMock() book2.get.return_value = 'Name2' mocked_data = MagicMock(**{'xpath.return_value': [book1, book2]}) importer.language_id = 10 importer.session = MagicMock() importer.stop_import_flag = False # WHEN: Calling process_books with the two books importer.process_books(mocked_data) # THEN: find_and_create_book and process_books should be called with the details from the mocked books self.assertEqual(self.mocked_find_and_create_book.call_args_list, [call('Name1', 2, 10), call('Name2', 2, 10)]) self.assertEqual( mocked_process_chapters.call_args_list, [call('db_book1', book1), call('db_book2', book2)]) self.assertEqual(importer.session.commit.call_count, 2)
def update_ui_dvd_test(self, mocked_get_vlc): """ Test updating the UI for a CD or DVD """ # GIVEN: A whole bunch of mocks mocked_vlc = MagicMock() mocked_vlc.State.Ended = 1 mocked_get_vlc.return_value = mocked_vlc mocked_controller = MagicMock() mocked_controller.media_info.start_time = 100 mocked_controller.media_info.end_time = 300 mocked_controller.seek_slider.isSliderDown.return_value = False mocked_display = MagicMock() mocked_display.controller = mocked_controller mocked_display.vlc_media.get_state.return_value = 1 mocked_display.vlc_media_player.get_time.return_value = 400000 mocked_display.controller.media_info.media_type = MediaType.DVD vlc_player = VlcPlayer(None) # WHEN: update_ui() is called with patch.object(vlc_player, 'stop') as mocked_stop, \ patch.object(vlc_player, 'set_visible') as mocked_set_visible: vlc_player.update_ui(mocked_display) # THEN: Certain methods should be called mocked_stop.assert_called_with(mocked_display) self.assertEqual(2, mocked_stop.call_count) mocked_display.vlc_media_player.get_time.assert_called_with() mocked_set_visible.assert_called_with(mocked_display, False) mocked_controller.seek_slider.setSliderPosition.assert_called_with(300000) expected_calls = [call(True), call(False)] self.assertEqual(expected_calls, mocked_controller.seek_slider.blockSignals.call_args_list)
def test_do_import(self, mocked_pyodbc): """ Test the MediaShoutImport do_import method """ SongRecord = namedtuple( 'SongRecord', 'Record, Title, Author, Copyright, SongID, CCLI, Notes') VerseRecord = namedtuple('VerseRecord', 'Type, Number, Text') PlayOrderRecord = namedtuple('PlayOrderRecord', 'Type, Number, POrder') ThemeRecord = namedtuple('ThemeRecord', 'Name') GroupRecord = namedtuple('GroupRecord', 'Name') song = SongRecord(1, 'Amazing Grace', 'William Wilberforce', 'Public Domain', 1, '654321', '') verse = VerseRecord( 'Verse', 1, 'Amazing grace, how sweet the sound\nThat saved a wretch like me') play_order = PlayOrderRecord('Verse', 1, 1) theme = ThemeRecord('Grace') group = GroupRecord('Hymns') # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out importer = MediaShoutImport(MagicMock(), filename='mediashout.db') mocked_cursor = MagicMock() mocked_cursor.fetchall.side_effect = [[song], [verse], [play_order], [theme], [group]] mocked_cursor.tables.fetchone.return_value = True mocked_connection = MagicMock() mocked_connection.cursor.return_value = mocked_cursor mocked_pyodbc.connect.return_value = mocked_connection # WHEN: do_import is called with patch.object(importer, 'import_wizard') as mocked_import_wizard, \ patch.object(importer, 'process_song') as mocked_process_song: importer.do_import() # THEN: The songs should have been imported expected_execute_calls = [ call( 'SELECT Record, Title, Author, Copyright, SongID, CCLI, Notes FROM Songs ORDER BY Title' ), call( 'SELECT Type, Number, Text FROM Verses WHERE Record = ? ORDER BY Type, Number', 1.0), call( 'SELECT Type, Number, POrder FROM PlayOrder WHERE Record = ? ORDER BY POrder', 1.0), call( 'SELECT Name FROM Themes INNER JOIN SongThemes ON SongThemes.ThemeId = Themes.ThemeId ' 'WHERE SongThemes.Record = ?', 1.0), call( 'SELECT Name FROM Groups INNER JOIN SongGroups ON SongGroups.GroupId = Groups.GroupId ' 'WHERE SongGroups.Record = ?', 1.0) ] self.assertEqual(expected_execute_calls, mocked_cursor.execute.call_args_list) mocked_process_song.assert_called_once_with(song, [verse], [play_order], [theme, group])
def test_get_song(self, MockedBeautifulSoup, mocked_build_opener): """ Test that the get_song() method returns the correct song details """ # GIVEN: A bunch of mocked out stuff and an importer object mocked_song_page = MagicMock() mocked_copyright = MagicMock() mocked_copyright.find_all.return_value = [MagicMock(string='Copyright 1'), MagicMock(string='Copyright 2')] mocked_song_page.find.side_effect = [ mocked_copyright, MagicMock(find=MagicMock(string='CCLI: 123456')) ] mocked_lyrics_page = MagicMock() mocked_find_all = MagicMock() mocked_find_all.side_effect = [ [ MagicMock(contents='The Lord told Noah: there\'s gonna be a floody, floody'), MagicMock(contents='So, rise and shine, and give God the glory, glory'), MagicMock(contents='The Lord told Noah to build him an arky, arky') ], [MagicMock(string='Verse 1'), MagicMock(string='Chorus'), MagicMock(string='Verse 2')] ] mocked_lyrics_page.find.return_value = MagicMock(find_all=mocked_find_all) MockedBeautifulSoup.side_effect = [mocked_song_page, mocked_lyrics_page] mocked_callback = MagicMock() importer = SongSelectImport(None) fake_song = {'title': 'Title', 'authors': ['Author 1', 'Author 2'], 'link': 'url'} # WHEN: get_song is called result = importer.get_song(fake_song, callback=mocked_callback) # THEN: The callback should have been called three times and the song should be returned self.assertEqual(3, mocked_callback.call_count, 'The callback should have been called twice') self.assertIsNotNone(result, 'The get_song() method should have returned a song dictionary') self.assertEqual(2, mocked_lyrics_page.find.call_count, 'The find() method should have been called twice') self.assertEqual(2, mocked_find_all.call_count, 'The find_all() method should have been called twice') self.assertEqual([call('div', 'song-viewer lyrics'), call('div', 'song-viewer lyrics')], mocked_lyrics_page.find.call_args_list, 'The find() method should have been called with the right arguments') self.assertEqual([call('p'), call('h3')], mocked_find_all.call_args_list, 'The find_all() method should have been called with the right arguments') self.assertIn('copyright', result, 'The returned song should have a copyright') self.assertIn('ccli_number', result, 'The returned song should have a CCLI number') self.assertIn('verses', result, 'The returned song should have verses') self.assertEqual(3, len(result['verses']), 'Three verses should have been returned')
def process_verses_successful_test(self): """ Test process_verses when the import is successful """ # GIVEN: An instance of CSVBible with the application and wizard attributes mocked out, and some test data. mocked_manager = MagicMock() with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv') importer.create_verse = MagicMock() importer.get_book = MagicMock( return_value=Book('1', '1', '1. Mosebog', '1Mos')) importer.get_book_name = MagicMock(return_value='1. Mosebog') importer.session = MagicMock() importer.stop_import_flag = False importer.wizard = MagicMock() verses = [ Verse(1, 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), Verse( 1, 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. ' 'Men Guds Ånd svævede over Vandene.') ] books = {1: '1. Mosebog'} # WHEN: Calling process_verses importer.process_verses(verses, books) # THEN: create_verse is called with the test data self.assertEqual(importer.get_book_name.mock_calls, [call(1, books), call(1, books)]) importer.get_book.assert_called_once_with('1. Mosebog') self.assertEqual(importer.session.commit.call_count, 2) self.assertEqual(importer.create_verse.mock_calls, [ call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), call( '1', 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. ' 'Men Guds Ånd svævede over Vandene.') ])
def test_replace_service_item_thumbs(self, mocked_setRowHeight, mocked_resizeRowsToContents, mocked_image_manager): """ Test that thubmails for different slides are loaded properly in replace_service_item. """ # GIVEN: A setting to adjust "Max height for non-text slides in slide controller", # different ServiceItem(s), an ImageManager, and a ListPreviewWidget. # Mock Settings().value('advanced/slide max height') self.mocked_Settings_obj.value.return_value = 0 # Mock self.viewport().width() self.mocked_viewport_obj.width.return_value = 200 # Mock Image service item mocked_img_service_item = MagicMock() mocked_img_service_item.is_text.return_value = False mocked_img_service_item.is_media.return_value = False mocked_img_service_item.is_command.return_value = False mocked_img_service_item.is_capable.return_value = False mocked_img_service_item.get_frames.return_value = [{'title': None, 'path': 'TEST1', 'image': 'FAIL'}, {'title': None, 'path': 'TEST2', 'image': 'FAIL'}] # Mock Command service item mocked_cmd_service_item = MagicMock() mocked_cmd_service_item.is_text.return_value = False mocked_cmd_service_item.is_media.return_value = False mocked_cmd_service_item.is_command.return_value = True mocked_cmd_service_item.is_capable.return_value = True mocked_cmd_service_item.get_frames.return_value = [{'title': None, 'path': 'FAIL', 'image': 'TEST3'}, {'title': None, 'path': 'FAIL', 'image': 'TEST4'}] # Mock image_manager mocked_image_manager.get_image.return_value = QtGui.QImage() # init ListPreviewWidget and load service item list_preview_widget = ListPreviewWidget(None, 1) # WHEN: replace_service_item is called list_preview_widget.replace_service_item(mocked_img_service_item, 200, 0) list_preview_widget.replace_service_item(mocked_cmd_service_item, 200, 0) # THEN: The ImageManager should be called in the appriopriate manner for each service item. self.assertEquals(mocked_image_manager.get_image.call_count, 4, 'Should be called once for each slide') calls = [call('TEST1', ImageSource.ImagePlugin), call('TEST2', ImageSource.ImagePlugin), call('TEST3', ImageSource.CommandPlugins), call('TEST4', ImageSource.CommandPlugins)] mocked_image_manager.get_image.assert_has_calls(calls)
def test_change_color(self): """ Test that change_color sets the new color and the stylesheet """ self.change_color_patcher.stop() # GIVEN: An instance of the ColorButton object, and a mocked out setStyleSheet with patch('openlp.core.ui.lib.colorbutton.ColorButton.setStyleSheet') as mocked_set_style_sheet: widget = ColorButton() # WHEN: Changing the color widget.change_color('#000000') # THEN: The _color attribute should be set to #000000 and setStyleSheet should have been called twice self.assertEqual(widget._color, '#000000', '_color should have been set to #000000') mocked_set_style_sheet.assert_has_calls( [call('background-color: #ffffff'), call('background-color: #000000')]) self.mocked_change_color = self.change_color_patcher.start()
def test_do_import(self, mocked_pyodbc): """ Test the MediaShoutImport do_import method """ SongRecord = namedtuple('SongRecord', 'Record, Title, Author, Copyright, SongID, CCLI, Notes') VerseRecord = namedtuple('VerseRecord', 'Type, Number, Text') PlayOrderRecord = namedtuple('PlayOrderRecord', 'Type, Number, POrder') ThemeRecord = namedtuple('ThemeRecord', 'Name') GroupRecord = namedtuple('GroupRecord', 'Name') song = SongRecord(1, 'Amazing Grace', 'William Wilberforce', 'Public Domain', 1, '654321', '') verse = VerseRecord('Verse', 1, 'Amazing grace, how sweet the sound\nThat saved a wretch like me') play_order = PlayOrderRecord('Verse', 1, 1) theme = ThemeRecord('Grace') group = GroupRecord('Hymns') # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out importer = MediaShoutImport(MagicMock(), filename='mediashout.db') mocked_cursor = MagicMock() mocked_cursor.fetchall.side_effect = [[song], [verse], [play_order], [theme], [group]] mocked_cursor.tables.fetchone.return_value = True mocked_connection = MagicMock() mocked_connection.cursor.return_value = mocked_cursor mocked_pyodbc.connect.return_value = mocked_connection # WHEN: do_import is called with patch.object(importer, 'import_wizard') as mocked_import_wizard, \ patch.object(importer, 'process_song') as mocked_process_song: importer.do_import() # THEN: The songs should have been imported expected_execute_calls = [ call('SELECT Record, Title, Author, Copyright, SongID, CCLI, Notes FROM Songs ORDER BY Title'), call('SELECT Type, Number, Text FROM Verses WHERE Record = ? ORDER BY Type, Number', 1.0), call('SELECT Type, Number, POrder FROM PlayOrder WHERE Record = ? ORDER BY POrder', 1.0), call('SELECT Name FROM Themes INNER JOIN SongThemes ON SongThemes.ThemeId = Themes.ThemeId ' 'WHERE SongThemes.Record = ?', 1.0), call('SELECT Name FROM Groups INNER JOIN SongGroups ON SongGroups.GroupId = Groups.GroupId ' 'WHERE SongGroups.Record = ?', 1.0) ] self.assertEqual(expected_execute_calls, mocked_cursor.execute.call_args_list) mocked_process_song.assert_called_once_with(song, [verse], [play_order], [theme, group])
def test_update_ui(self): """ Test the update_ui() method on the SystemPlayer """ # GIVEN: A SystemPlayer instance player = SystemPlayer(self) player.state = MediaState.Playing mocked_display = MagicMock() mocked_display.media_player.state.return_value = QtMultimedia.QMediaPlayer.PausedState mocked_display.controller.media_info.end_time = 1 mocked_display.media_player.position.return_value = 2 mocked_display.controller.seek_slider.isSliderDown.return_value = False # WHEN: update_ui() is called with patch.object(player, 'stop') as mocked_stop, \ patch.object(player, 'set_visible') as mocked_set_visible: player.update_ui(mocked_display) # THEN: The UI is updated expected_stop_calls = [call(mocked_display), call(mocked_display)] expected_position_calls = [call(), call()] expected_block_signals_calls = [call(True), call(False)] mocked_display.media_player.state.assert_called_once_with() self.assertEqual(2, mocked_stop.call_count) self.assertEqual(expected_stop_calls, mocked_stop.call_args_list) self.assertEqual(2, mocked_display.media_player.position.call_count) self.assertEqual(expected_position_calls, mocked_display.media_player.position.call_args_list) mocked_set_visible.assert_called_once_with(mocked_display, False) mocked_display.controller.seek_slider.isSliderDown.assert_called_once_with() self.assertEqual(expected_block_signals_calls, mocked_display.controller.seek_slider.blockSignals.call_args_list) mocked_display.controller.seek_slider.setSliderPosition.assert_called_once_with(2)
def process_chapters_completes_test(self, mocked_parse_chapter_number): """ Test process_chapters when it completes """ # GIVEN: An instance of OpenSongBible importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') importer.wizard = MagicMock() # WHEN: called with some valid data book = MagicMock() book.name = "Book" chapter1 = MagicMock() chapter1.attrib = {'n': '1'} chapter1.c = 'Chapter1' chapter1.v = ['Chapter1 Verses'] chapter2 = MagicMock() chapter2.attrib = {'n': '2'} chapter2.c = 'Chapter2' chapter2.v = ['Chapter2 Verses'] importer.process_verses = MagicMock() importer.stop_import_flag = False importer.process_chapters(book, [chapter1, chapter2]) # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called self.assertEqual(mocked_parse_chapter_number.call_args_list, [call('1', 0), call('2', 1)]) self.assertEqual(importer.process_verses.call_args_list, [ call(book, 1, ['Chapter1 Verses']), call(book, 2, ['Chapter2 Verses']) ]) self.assertEqual( importer.wizard.increment_progress_bar.call_args_list, [call('Importing Book 1...'), call('Importing Book 2...')])
def test_returned_file_list(self): """ Test that FileDialog.getOpenFileNames handles a list of files properly when QFileList.getOpenFileNames returns a good file name, a url encoded file name and a non-existing file """ self.mocked_os.rest_mock() self.mocked_qt_gui.reset_mock() # GIVEN: A List of known values as a return value from QFileDialog.getOpenFileNames and a list of valid file # names. self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = ([ '/Valid File', '/url%20encoded%20file%20%231', '/non-existing' ], []) self.mocked_os.path.exists.side_effect = lambda file_name: file_name in [ '/Valid File', '/url encoded file #1' ] self.mocked_ui_strings().FileNotFound = 'File Not Found' self.mocked_ui_strings( ).FileNotFoundMessage = 'File {name} not found.\nPlease try selecting it individually.' # WHEN: FileDialog.getOpenFileNames is called result = FileDialog.getOpenFileNames(self.mocked_parent) # THEN: os.path.exists should have been called with known args. QmessageBox.information should have been # called. The returned result should correlate with the input. call_list = [ call('/Valid File'), call('/url%20encoded%20file%20%231'), call('/url encoded file #1'), call('/non-existing'), call('/non-existing') ] self.mocked_os.path.exists.assert_has_calls(call_list) self.mocked_qt_gui.QMessageBox.information.assert_called_with( self.mocked_parent, 'File Not Found', 'File /non-existing not found.\nPlease try selecting it individually.' ) self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')
def change_color_test(self): """ Test that change_color sets the new color and the stylesheet """ self.change_color_patcher.stop() # GIVEN: An instance of the ColorButton object, and a mocked out setStyleSheet with patch('openlp.core.lib.colorbutton.ColorButton.setStyleSheet' ) as mocked_set_style_sheet: widget = ColorButton() # WHEN: Changing the color widget.change_color('#000000') # THEN: The _color attribute should be set to #000000 and setStyleSheet should have been called twice self.assertEqual(widget._color, '#000000', '_color should have been set to #000000') mocked_set_style_sheet.assert_has_calls([ call('background-color: #ffffff'), call('background-color: #000000') ]) self.mocked_change_color = self.change_color_patcher.start()
def test_get_file_name_encoding_done_test(self): """ Test get_file_encoding when the detector sets done to True """ # GIVEN: A mocked UniversalDetector instance with done attribute set to True after first iteration with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ patch('builtins.open', return_value=BytesIO(b"data" * 260)) as mocked_open: encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} mocked_universal_detector_inst = MagicMock(result=encoding_result) type(mocked_universal_detector_inst).done = PropertyMock(side_effect=[False, True]) mocked_universal_detector.return_value = mocked_universal_detector_inst # WHEN: Calling get_file_encoding result = get_file_encoding('file name') # THEN: The feed method of UniversalDetector should only br called once before returning a result mocked_open.assert_called_once_with('file name', 'rb') self.assertEqual(mocked_universal_detector_inst.feed.mock_calls, [call(b"data" * 256)]) mocked_universal_detector_inst.close.assert_called_once_with() self.assertEqual(result, encoding_result)
def test_get_file_name_encoding_eof_test(self): """ Test get_file_encoding when the end of the file is reached """ # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test # data (enough to run the iterator twice) with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \ patch('builtins.open', return_value=BytesIO(b"data" * 260)) as mocked_open: encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99} mocked_universal_detector_inst = MagicMock(mock=mocked_universal_detector, **{'done': False, 'result': encoding_result}) mocked_universal_detector.return_value = mocked_universal_detector_inst # WHEN: Calling get_file_encoding result = get_file_encoding('file name') # THEN: The feed method of UniversalDetector should have been called twice before returning a result mocked_open.assert_called_once_with('file name', 'rb') self.assertEqual(mocked_universal_detector_inst.feed.mock_calls, [call(b"data" * 256), call(b"data" * 4)]) mocked_universal_detector_inst.close.assert_called_once_with() self.assertEqual(result, encoding_result)
def process_verses_completes_test(self): """ Test process_verses when it completes """ with patch('openlp.plugins.bibles.lib.importers.opensong.get_text', **{'side_effect': ['Verse1 Text', 'Verse2 Text']}) as mocked_get_text, \ patch.object(OpenSongBible, 'parse_verse_number', **{'side_effect': [1, 2]}) as mocked_parse_verse_number: # GIVEN: An instance of OpenSongBible importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') importer.wizard = MagicMock() # WHEN: called with some valid data book = MagicMock() book.id = 1 verse1 = MagicMock() verse1.attrib = {'n': '1'} verse1.c = 'Chapter1' verse1.v = ['Chapter1 Verses'] verse2 = MagicMock() verse2.attrib = {'n': '2'} verse2.c = 'Chapter2' verse2.v = ['Chapter2 Verses'] importer.create_verse = MagicMock() importer.stop_import_flag = False importer.process_verses(book, 1, [verse1, verse2]) # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called self.assertEqual(mocked_parse_verse_number.call_args_list, [call('1', 0), call('2', 1)]) self.assertEqual(mocked_get_text.call_args_list, [call(verse1), call(verse2)]) self.assertEqual( importer.create_verse.call_args_list, [call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')])
def test_update_ui(self): """ Test the update_ui() method on the SystemPlayer """ # GIVEN: A SystemPlayer instance player = SystemPlayer(self) player.state = MediaState.Playing mocked_display = MagicMock() mocked_display.media_player.state.return_value = QtMultimedia.QMediaPlayer.PausedState mocked_display.controller.media_info.end_time = 1 mocked_display.media_player.position.return_value = 2 mocked_display.controller.seek_slider.isSliderDown.return_value = False # WHEN: update_ui() is called with patch.object(player, 'stop') as mocked_stop, \ patch.object(player, 'set_visible') as mocked_set_visible: player.update_ui(mocked_display) # THEN: The UI is updated expected_stop_calls = [call(mocked_display), call(mocked_display)] expected_position_calls = [call(), call()] expected_block_signals_calls = [call(True), call(False)] mocked_display.media_player.state.assert_called_once_with() self.assertEqual(2, mocked_stop.call_count) self.assertEqual(expected_stop_calls, mocked_stop.call_args_list) self.assertEqual(2, mocked_display.media_player.position.call_count) self.assertEqual(expected_position_calls, mocked_display.media_player.position.call_args_list) mocked_set_visible.assert_called_once_with(mocked_display, False) mocked_display.controller.seek_slider.isSliderDown.assert_called_once_with( ) self.assertEqual( expected_block_signals_calls, mocked_display.controller.seek_slider.blockSignals.call_args_list) mocked_display.controller.seek_slider.setSliderPosition.assert_called_once_with( 2)
def test_login_fails(self, mocked_translate, mocked_critical, MockedSongSelectImport): """ Test that when the login fails, the form returns to the correct state """ # GIVEN: A valid SongSelectForm with a mocked out SongSelectImport, and a bunch of mocked out controls mocked_song_select_import = MagicMock() mocked_song_select_import.login.return_value = False MockedSongSelectImport.return_value = mocked_song_select_import mocked_translate.side_effect = lambda *args: args[1] ssform = SongSelectForm(None, MagicMock(), MagicMock()) ssform.initialise() with patch.object(ssform, 'username_edit') as mocked_username_edit, \ patch.object(ssform, 'password_edit') as mocked_password_edit, \ patch.object(ssform, 'save_password_checkbox') as mocked_save_password_checkbox, \ patch.object(ssform, 'login_button') as mocked_login_button, \ patch.object(ssform, 'login_spacer') as mocked_login_spacer, \ patch.object(ssform, 'login_progress_bar') as mocked_login_progress_bar, \ patch.object(ssform.application, 'process_events') as mocked_process_events: # WHEN: The login button is clicked, and the login is rigged to fail ssform.on_login_button_clicked() # THEN: The right things should have happened in the right order expected_username_calls = [call(False), call(True)] expected_password_calls = [call(False), call(True)] expected_save_password_calls = [call(False), call(True)] expected_login_btn_calls = [call(False), call(True)] expected_login_spacer_calls = [call(False), call(True)] expected_login_progress_visible_calls = [call(True), call(False)] expected_login_progress_value_calls = [call(0), call(0)] self.assertEqual( expected_username_calls, mocked_username_edit.setEnabled.call_args_list, 'The username edit should be disabled then enabled') self.assertEqual( expected_password_calls, mocked_password_edit.setEnabled.call_args_list, 'The password edit should be disabled then enabled') self.assertEqual( expected_save_password_calls, mocked_save_password_checkbox.setEnabled.call_args_list, 'The save password checkbox should be disabled then enabled') self.assertEqual( expected_login_btn_calls, mocked_login_button.setEnabled.call_args_list, 'The login button should be disabled then enabled') self.assertEqual( expected_login_spacer_calls, mocked_login_spacer.setVisible.call_args_list, 'Thee login spacer should be make invisible, then visible') self.assertEqual( expected_login_progress_visible_calls, mocked_login_progress_bar.setVisible.call_args_list, 'Thee login progress bar should be make visible, then invisible' ) self.assertEqual( expected_login_progress_value_calls, mocked_login_progress_bar.setValue.call_args_list, 'Thee login progress bar should have the right values set') self.assertEqual( 2, mocked_process_events.call_count, 'The process_events() method should be called twice') mocked_critical.assert_called_with( ssform, 'Error Logging In', 'There was a problem logging in, ' 'perhaps your username or password is ' 'incorrect?')
def test_get_song(self, MockedBeautifulSoup, mocked_build_opener): """ Test that the get_song() method returns the correct song details """ # GIVEN: A bunch of mocked out stuff and an importer object mocked_song_page = MagicMock() mocked_copyright = MagicMock() mocked_copyright.find_all.return_value = [ MagicMock(string='Copyright 1'), MagicMock(string='Copyright 2') ] mocked_song_page.find.side_effect = [ mocked_copyright, MagicMock(find=MagicMock(string='CCLI: 123456')) ] mocked_lyrics_page = MagicMock() mocked_find_all = MagicMock() mocked_find_all.side_effect = [[ MagicMock( contents= 'The Lord told Noah: there\'s gonna be a floody, floody'), MagicMock( contents='So, rise and shine, and give God the glory, glory'), MagicMock(contents='The Lord told Noah to build him an arky, arky') ], [ MagicMock(string='Verse 1'), MagicMock(string='Chorus'), MagicMock(string='Verse 2') ]] mocked_lyrics_page.find.return_value = MagicMock( find_all=mocked_find_all) MockedBeautifulSoup.side_effect = [ mocked_song_page, mocked_lyrics_page ] mocked_callback = MagicMock() importer = SongSelectImport(None) fake_song = { 'title': 'Title', 'authors': ['Author 1', 'Author 2'], 'link': 'url' } # WHEN: get_song is called result = importer.get_song(fake_song, callback=mocked_callback) # THEN: The callback should have been called three times and the song should be returned self.assertEqual(3, mocked_callback.call_count, 'The callback should have been called twice') self.assertIsNotNone( result, 'The get_song() method should have returned a song dictionary') self.assertEqual(2, mocked_lyrics_page.find.call_count, 'The find() method should have been called twice') self.assertEqual( 2, mocked_find_all.call_count, 'The find_all() method should have been called twice') self.assertEqual( [ call('div', 'song-viewer lyrics'), call('div', 'song-viewer lyrics') ], mocked_lyrics_page.find.call_args_list, 'The find() method should have been called with the right arguments' ) self.assertEqual( [call('p'), call('h3')], mocked_find_all.call_args_list, 'The find_all() method should have been called with the right arguments' ) self.assertIn('copyright', result, 'The returned song should have a copyright') self.assertIn('ccli_number', result, 'The returned song should have a CCLI number') self.assertIn('verses', result, 'The returned song should have verses') self.assertEqual(3, len(result['verses']), 'Three verses should have been returned')
def test_login_fails(self, mocked_translate, mocked_critical, MockedSongSelectImport): """ Test that when the login fails, the form returns to the correct state """ # GIVEN: A valid SongSelectForm with a mocked out SongSelectImport, and a bunch of mocked out controls mocked_song_select_import = MagicMock() mocked_song_select_import.login.return_value = False MockedSongSelectImport.return_value = mocked_song_select_import mocked_translate.side_effect = lambda *args: args[1] ssform = SongSelectForm(None, MagicMock(), MagicMock()) ssform.initialise() with patch.object(ssform, 'username_edit') as mocked_username_edit, \ patch.object(ssform, 'password_edit') as mocked_password_edit, \ patch.object(ssform, 'save_password_checkbox') as mocked_save_password_checkbox, \ patch.object(ssform, 'login_button') as mocked_login_button, \ patch.object(ssform, 'login_spacer') as mocked_login_spacer, \ patch.object(ssform, 'login_progress_bar') as mocked_login_progress_bar, \ patch.object(ssform.application, 'process_events') as mocked_process_events: # WHEN: The login button is clicked, and the login is rigged to fail ssform.on_login_button_clicked() # THEN: The right things should have happened in the right order expected_username_calls = [call(False), call(True)] expected_password_calls = [call(False), call(True)] expected_save_password_calls = [call(False), call(True)] expected_login_btn_calls = [call(False), call(True)] expected_login_spacer_calls = [call(False), call(True)] expected_login_progress_visible_calls = [call(True), call(False)] expected_login_progress_value_calls = [call(0), call(0)] self.assertEqual(expected_username_calls, mocked_username_edit.setEnabled.call_args_list, 'The username edit should be disabled then enabled') self.assertEqual(expected_password_calls, mocked_password_edit.setEnabled.call_args_list, 'The password edit should be disabled then enabled') self.assertEqual(expected_save_password_calls, mocked_save_password_checkbox.setEnabled.call_args_list, 'The save password checkbox should be disabled then enabled') self.assertEqual(expected_login_btn_calls, mocked_login_button.setEnabled.call_args_list, 'The login button should be disabled then enabled') self.assertEqual(expected_login_spacer_calls, mocked_login_spacer.setVisible.call_args_list, 'Thee login spacer should be make invisible, then visible') self.assertEqual(expected_login_progress_visible_calls, mocked_login_progress_bar.setVisible.call_args_list, 'Thee login progress bar should be make visible, then invisible') self.assertEqual(expected_login_progress_value_calls, mocked_login_progress_bar.setValue.call_args_list, 'Thee login progress bar should have the right values set') self.assertEqual(2, mocked_process_events.call_count, 'The process_events() method should be called twice') mocked_critical.assert_called_with(ssform, 'Error Logging In', 'There was a problem logging in, ' 'perhaps your username or password is ' 'incorrect?')
def file_import(self, source_file_name, result_data): """ Import the given file and check that it has imported correctly """ importer = self.importer_class(self.mocked_manager, filenames=[source_file_name]) importer.import_wizard = self.mocked_import_wizard importer.stop_import_flag = False importer.topics = [] # WHEN: Importing the source file importer.import_source = source_file_name add_verse_calls = self._get_data(result_data, 'verses') author_calls = self._get_data(result_data, 'authors') ccli_number = self._get_data(result_data, 'ccli_number') comments = self._get_data(result_data, 'comments') song_book_name = self._get_data(result_data, 'song_book_name') song_copyright = self._get_data(result_data, 'copyright') song_number = self._get_data(result_data, 'song_number') title = self._get_data(result_data, 'title') topics = self._get_data(result_data, 'topics') verse_order_list = self._get_data(result_data, 'verse_order_list') # THEN: do_import should return none, the song data should be as expected, and finish should have been called. self.assertIsNone( importer.do_import(), 'do_import should return None when it has completed') # Debug information - will be displayed when the test fails log.debug("Title imported: %s" % importer.title) log.debug("Verses imported: %s" % self.mocked_add_verse.mock_calls) log.debug("Verse order imported: %s" % importer.verse_order_list) log.debug("Authors imported: %s" % self.mocked_add_author.mock_calls) log.debug("CCLI No. imported: %s" % importer.ccli_number) log.debug("Comments imported: %s" % importer.comments) log.debug("Songbook imported: %s" % importer.song_book_name) log.debug("Song number imported: %s" % importer.song_number) log.debug("Song copyright imported: %s" % importer.song_number) log.debug("Topics imported: %s" % importer.topics) self.assertEqual( importer.title, title, 'title for %s should be "%s"' % (source_file_name, title)) for author in author_calls: if isinstance(author, str): self.mocked_add_author.assert_any_call(author) else: self.mocked_add_author.assert_any_call(*author) if song_copyright: self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: self.assertEqual( importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' % (source_file_name, ccli_number)) expected_calls = [] for verse_text, verse_tag in add_verse_calls: self.mocked_add_verse.assert_any_call(verse_text, verse_tag) expected_calls.append(call(verse_text, verse_tag)) self.mocked_add_verse.assert_has_calls(expected_calls, any_order=False) if topics: self.assertEqual( importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics)) if comments: self.assertEqual( importer.comments, comments, 'comments for %s should be "%s"' % (source_file_name, comments)) if song_book_name: self.assertEqual( importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % (source_file_name, song_book_name)) if song_number: self.assertEqual( importer.song_number, song_number, 'song_number for %s should be %s' % (source_file_name, song_number)) if verse_order_list: self.assertEqual( importer.verse_order_list, verse_order_list, 'verse_order_list for %s should be %s' % (source_file_name, verse_order_list)) self.mocked_finish.assert_called_with()
def file_import(self, source_file_name, result_data): """ Import the given file and check that it has imported correctly """ importer = self.importer_class(self.mocked_manager, filenames=[source_file_name]) importer.import_wizard = self.mocked_import_wizard importer.stop_import_flag = False importer.topics = [] # WHEN: Importing the source file importer.import_source = source_file_name add_verse_calls = self._get_data(result_data, 'verses') author_calls = self._get_data(result_data, 'authors') ccli_number = self._get_data(result_data, 'ccli_number') comments = self._get_data(result_data, 'comments') song_book_name = self._get_data(result_data, 'song_book_name') song_copyright = self._get_data(result_data, 'copyright') song_number = self._get_data(result_data, 'song_number') title = self._get_data(result_data, 'title') topics = self._get_data(result_data, 'topics') verse_order_list = self._get_data(result_data, 'verse_order_list') # THEN: do_import should return none, the song data should be as expected, and finish should have been called. self.assertIsNone(importer.do_import(), 'do_import should return None when it has completed') # Debug information - will be displayed when the test fails log.debug("Title imported: %s" % importer.title) log.debug("Verses imported: %s" % self.mocked_add_verse.mock_calls) log.debug("Verse order imported: %s" % importer.verse_order_list) log.debug("Authors imported: %s" % self.mocked_add_author.mock_calls) log.debug("CCLI No. imported: %s" % importer.ccli_number) log.debug("Comments imported: %s" % importer.comments) log.debug("Songbook imported: %s" % importer.song_book_name) log.debug("Song number imported: %s" % importer.song_number) log.debug("Song copyright imported: %s" % importer.song_number) log.debug("Topics imported: %s" % importer.topics) self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (source_file_name, title)) for author in author_calls: if isinstance(author, str): self.mocked_add_author.assert_any_call(author) else: self.mocked_add_author.assert_any_call(*author) if song_copyright: self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: self.assertEqual(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s' % (source_file_name, ccli_number)) expected_calls = [] for verse_text, verse_tag in add_verse_calls: self.mocked_add_verse.assert_any_call(verse_text, verse_tag) expected_calls.append(call(verse_text, verse_tag)) self.mocked_add_verse.assert_has_calls(expected_calls, any_order=False) if topics: self.assertEqual(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics)) if comments: self.assertEqual(importer.comments, comments, 'comments for %s should be "%s"' % (source_file_name, comments)) if song_book_name: self.assertEqual(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"' % (source_file_name, song_book_name)) if song_number: self.assertEqual(importer.song_number, song_number, 'song_number for %s should be %s' % (source_file_name, song_number)) if verse_order_list: self.assertEqual(importer.verse_order_list, verse_order_list, 'verse_order_list for %s should be %s' % (source_file_name, verse_order_list)) self.mocked_finish.assert_called_with()