Changeged 'combined' bible verses and made a seperate 'saved' list

This commit is contained in:
Philip Ridout 2017-03-31 19:41:38 +01:00
parent fc505c2a13
commit 53b210d9cd
4 changed files with 176 additions and 118 deletions

5
openlp/core/ui/lib/listwidgetwithdnd.py Normal file → Executable file
View File

@ -44,7 +44,6 @@ class ListWidgetWithDnD(QtWidgets.QListWidget):
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.setAlternatingRowColors(True) self.setAlternatingRowColors(True)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.locked = False
def activateDnD(self): def activateDnD(self):
""" """
@ -54,15 +53,13 @@ class ListWidgetWithDnD(QtWidgets.QListWidget):
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file) Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file)
def clear(self, search_while_typing=False, override_lock=False): def clear(self, search_while_typing=False):
""" """
Re-implement clear, so that we can customise feedback when using 'Search as you type' Re-implement clear, so that we can customise feedback when using 'Search as you type'
:param search_while_typing: True if we want to display the customised message :param search_while_typing: True if we want to display the customised message
:return: None :return: None
""" """
if self.locked and not override_lock:
return
if search_while_typing: if search_while_typing:
self.no_results_text = UiStrings().ShortResults self.no_results_text = UiStrings().ShortResults
else: else:

158
openlp/plugins/bibles/lib/mediaitem.py Normal file → Executable file
View File

@ -57,6 +57,17 @@ class BibleSearch(object):
Combined = 3 Combined = 3
class ResultsTab(object):
Saved = 0
Search = 1
class SearchStatus(object):
SearchButton = 0
SearchAsYouType = 1
NotEnoughText = 2
class BibleMediaItem(MediaManagerItem): class BibleMediaItem(MediaManagerItem):
""" """
This is the custom media manager item for Bibles. This is the custom media manager item for Bibles.
@ -78,6 +89,9 @@ class BibleMediaItem(MediaManagerItem):
self.sort_icon = build_icon(':/bibles/bibles_book_sort.png') self.sort_icon = build_icon(':/bibles/bibles_book_sort.png')
self.bible = None self.bible = None
self.second_bible = None self.second_bible = None
self.saved_results = []
self.current_results = []
self.search_status = SearchStatus().SearchButton
# TODO: Make more central and clean up after! # TODO: Make more central and clean up after!
self.search_timer = QtCore.QTimer() self.search_timer = QtCore.QTimer()
self.search_timer.setInterval(200) self.search_timer.setInterval(200)
@ -176,15 +190,18 @@ class BibleMediaItem(MediaManagerItem):
# Note: If we use QPushButton instead of the QToolButton, the icon will be larger than the Lock icon. # Note: If we use QPushButton instead of the QToolButton, the icon will be larger than the Lock icon.
self.clear_button = QtWidgets.QToolButton(self) self.clear_button = QtWidgets.QToolButton(self)
self.clear_button.setIcon(self.clear_icon) self.clear_button.setIcon(self.clear_icon)
self.lock_button = QtWidgets.QToolButton(self) self.save_results_button = QtWidgets.QToolButton(self)
self.lock_button.setIcon(self.unlock_icon) self.save_results_button.setIcon(self.unlock_icon)
self.lock_button.setCheckable(True)
self.search_button_layout.addWidget(self.clear_button) self.search_button_layout.addWidget(self.clear_button)
self.search_button_layout.addWidget(self.lock_button) self.search_button_layout.addWidget(self.save_results_button)
self.search_button = QtWidgets.QPushButton(self) self.search_button = QtWidgets.QPushButton(self)
self.search_button_layout.addWidget(self.search_button) self.search_button_layout.addWidget(self.search_button)
self.general_bible_layout.addRow(self.search_button_layout) self.general_bible_layout.addRow(self.search_button_layout)
self.page_layout.addWidget(self.options_widget) self.page_layout.addWidget(self.options_widget)
self.results_view_tab = QtWidgets.QTabBar(self)
self.results_view_tab.addTab('')
self.results_view_tab.addTab('')
self.page_layout.addWidget(self.results_view_tab)
def setupUi(self): def setupUi(self):
super().setupUi() super().setupUi()
@ -211,12 +228,15 @@ class BibleMediaItem(MediaManagerItem):
# Buttons # Buttons
self.book_order_button.toggled.connect(self.on_book_order_button_toggled) self.book_order_button.toggled.connect(self.on_book_order_button_toggled)
self.clear_button.clicked.connect(self.on_clear_button_clicked) self.clear_button.clicked.connect(self.on_clear_button_clicked)
self.lock_button.toggled.connect(self.on_lock_button_toggled) self.save_results_button.clicked.connect(self.on_save_results_button_clicked)
self.search_button.clicked.connect(self.on_search_button_clicked) self.search_button.clicked.connect(self.on_search_button_clicked)
# Other stuff # Other stuff
self.search_edit.returnPressed.connect(self.on_search_button_clicked) self.search_edit.returnPressed.connect(self.on_search_button_clicked)
self.search_tab_bar.currentChanged.connect(self.on_search_tab_bar_current_changed) self.search_tab_bar.currentChanged.connect(self.on_search_tab_bar_current_changed)
self.results_view_tab.currentChanged.connect(self.on_results_view_tab_current_changed)
self.search_edit.textChanged.connect(self.on_search_edit_text_changed) self.search_edit.textChanged.connect(self.on_search_edit_text_changed)
self.on_results_view_tab_total_update(ResultsTab.Saved)
self.on_results_view_tab_total_update(ResultsTab.Search)
def retranslateUi(self): def retranslateUi(self):
log.debug('retranslateUi') log.debug('retranslateUi')
@ -225,9 +245,9 @@ class BibleMediaItem(MediaManagerItem):
self.style_combo_box.setItemText(LayoutStyle.VersePerSlide, UiStrings().VersePerSlide) self.style_combo_box.setItemText(LayoutStyle.VersePerSlide, UiStrings().VersePerSlide)
self.style_combo_box.setItemText(LayoutStyle.VersePerLine, UiStrings().VersePerLine) self.style_combo_box.setItemText(LayoutStyle.VersePerLine, UiStrings().VersePerLine)
self.style_combo_box.setItemText(LayoutStyle.Continuous, UiStrings().Continuous) self.style_combo_box.setItemText(LayoutStyle.Continuous, UiStrings().Continuous)
self.clear_button.setToolTip(translate('BiblesPlugin.MediaItem', 'Clear the search results.')) self.clear_button.setToolTip(translate('BiblesPlugin.MediaItem', 'Clear the results on the current tab.'))
self.lock_button.setToolTip( self.save_results_button.setToolTip(
translate('BiblesPlugin.MediaItem', 'Toggle to keep or clear the previous results.')) translate('BiblesPlugin.MediaItem', 'Add the search results to the saved list.'))
self.search_button.setText(UiStrings().Search) self.search_button.setText(UiStrings().Search)
def on_focus(self): def on_focus(self):
@ -423,6 +443,35 @@ class BibleMediaItem(MediaManagerItem):
self.select_tab.setVisible(not search_tab) self.select_tab.setVisible(not search_tab)
self.on_focus() self.on_focus()
def on_results_view_tab_current_changed(self, index):
"""
Update list_widget with the contents of the selected list
:param index: The index of the tab that has been changed to. (int)
:return: None
"""
if index == ResultsTab.Saved:
self.add_built_results_to_list_widget(self.saved_results)
elif index == ResultsTab.Search:
self.add_built_results_to_list_widget(self.current_results)
def on_results_view_tab_total_update(self, index):
"""
Update the result total count on the tab with the given index.
:param index: Index of the tab to update (int)
:return: None
"""
string = ''
count = 0
if index == ResultsTab.Saved:
string = translate('BiblesPlugin.MediaItem', 'Saved ({result_count})')
count = len(self.saved_results)
elif index == ResultsTab.Search:
string = translate('BiblesPlugin.MediaItem', 'Results ({result_count})')
count = len(self.current_results)
self.results_view_tab.setTabText(index, string.format(result_count = count))
def on_book_order_button_toggled(self, checked): def on_book_order_button_toggled(self, checked):
""" """
Change the sort order of the book names Change the sort order of the book names
@ -442,22 +491,25 @@ class BibleMediaItem(MediaManagerItem):
:return: None :return: None
""" """
current_index = self.results_view_tab.currentIndex()
if current_index == ResultsTab.Saved:
self.saved_results = []
elif current_index == ResultsTab.Search:
self.current_results = []
self.search_edit.clear()
self.on_focus()
self.on_results_view_tab_total_update(current_index)
self.list_view.clear() self.list_view.clear()
self.search_edit.clear()
self.on_focus()
def on_lock_button_toggled(self, checked): def on_save_results_button_clicked(self):
""" """
Toggle the lock button, if Search tab is used, set focus to search field. Toggle the lock button.
:param checked: The state of the toggle button. (bool)
:return: None :return: None
""" """
self.list_view.locked = checked for verse in self.list_view.selectedItems():
if checked: self.saved_results.append(verse.data(QtCore.Qt.UserRole))
self.sender().setIcon(self.lock_icon) self.on_results_view_tab_total_update(ResultsTab.Saved)
else:
self.sender().setIcon(self.unlock_icon)
def on_style_combo_box_index_changed(self, index): def on_style_combo_box_index_changed(self, index):
""" """
@ -497,9 +549,11 @@ class BibleMediaItem(MediaManagerItem):
if critical_error_message_box( if critical_error_message_box(
message=translate('BiblesPlugin.MediaItem', message=translate('BiblesPlugin.MediaItem',
'OpenLP cannot combine single and dual Bible verse search results. ' 'OpenLP cannot combine single and dual Bible verse search results. '
'Do you want to clear your search results and start a new search?'), 'Do you want to clear your results and start a new search?'),
parent=self, question=True) == QtWidgets.QMessageBox.Yes: parent=self, question=True) == QtWidgets.QMessageBox.Yes:
self.list_view.clear(override_lock=True) self.display_results()
self.saved_results = []
self.on_results_view_tab_total_update(ResultsTab.Saved)
else: else:
self.second_combo_box.setCurrentIndex(self.second_combo_box.findData(self.second_bible)) self.second_combo_box.setCurrentIndex(self.second_combo_box.findData(self.second_bible))
return return
@ -602,6 +656,8 @@ class BibleMediaItem(MediaManagerItem):
:return: None :return: None
""" """
self.search_timer.stop()
self.search_status = SearchStatus().SearchButton
if not self.bible: if not self.bible:
self.main_window.information_message(UiStrings().BibleNoBiblesTitle, UiStrings().BibleNoBibles) self.main_window.information_message(UiStrings().BibleNoBiblesTitle, UiStrings().BibleNoBibles)
return return
@ -613,6 +669,7 @@ class BibleMediaItem(MediaManagerItem):
elif self.select_tab.isVisible(): elif self.select_tab.isVisible():
self.select_search() self.select_search()
self.search_button.setEnabled(True) self.search_button.setEnabled(True)
self.results_view_tab.setCurrentIndex(ResultsTab.Search)
self.application.set_normal_cursor() self.application.set_normal_cursor()
def select_search(self): def select_search(self):
@ -636,13 +693,14 @@ class BibleMediaItem(MediaManagerItem):
:return: None :return: None
""" """
self.search_results = []
verse_refs = self.plugin.manager.parse_ref(self.bible.name, search_text) verse_refs = self.plugin.manager.parse_ref(self.bible.name, search_text)
self.search_results = self.plugin.manager.get_verses(self.bible.name, verse_refs, True) self.search_results = self.plugin.manager.get_verses(self.bible.name, verse_refs, True)
if self.second_bible and self.search_results: if self.second_bible and self.search_results:
self.search_results = self.plugin.manager.get_verses(self.second_bible.name, verse_refs, True) self.search_results = self.plugin.manager.get_verses(self.second_bible.name, verse_refs, True)
self.display_results() self.display_results()
def on_text_search(self, text, search_while_type=False): def on_text_search(self, text):
""" """
We are doing a 'Text Search'. We are doing a 'Text Search'.
This search is called on def text_search by 'Search' Text and Combined Searches. This search is called on def text_search by 'Search' Text and Combined Searches.
@ -663,7 +721,7 @@ class BibleMediaItem(MediaManagerItem):
verse=verse.verse, bible_name=self.second_bible.name)) verse=verse.verse, bible_name=self.second_bible.name))
not_found_count += 1 not_found_count += 1
self.search_results = filtered_search_results self.search_results = filtered_search_results
if not_found_count != 0 and not search_while_type: if not_found_count != 0 and self.search_status == SearchStatus.SearchButton:
self.main_window.information_message( self.main_window.information_message(
translate('BiblesPlugin.MediaItem', 'Verses not found'), translate('BiblesPlugin.MediaItem', 'Verses not found'),
translate('BiblesPlugin.MediaItem', translate('BiblesPlugin.MediaItem',
@ -673,22 +731,23 @@ class BibleMediaItem(MediaManagerItem):
).format(second_name=self.second_bible.name, name=self.bible.name, count=not_found_count)) ).format(second_name=self.second_bible.name, name=self.bible.name, count=not_found_count))
self.display_results() self.display_results()
def text_search(self, search_while_type=False): def text_search(self):
""" """
This triggers the proper 'Search' search based on which search type is used. This triggers the proper 'Search' search based on which search type is used.
"Eg. "Reference Search", "Text Search" or "Combined search". "Eg. "Reference Search", "Text Search" or "Combined search".
""" """
self.search_results = []
log.debug('text_search called') log.debug('text_search called')
text = self.search_edit.text() text = self.search_edit.text()
if text == '': if text == '':
self.list_view.clear() self.display_results()
return return
self.list_view.clear(search_while_typing=search_while_type) self.on_results_view_tab_total_update(ResultsTab.Search)
if self.search_edit.current_search_type() == BibleSearch.Reference: if self.search_edit.current_search_type() == BibleSearch.Reference:
if get_reference_match('full').match(text): if get_reference_match('full').match(text):
# Valid reference found. Do reference search. # Valid reference found. Do reference search.
self.text_reference_search(text) self.text_reference_search(text)
elif not search_while_type: elif self.search_status == SearchStatus.SearchButton:
self.main_window.information_message( self.main_window.information_message(
translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'), translate('BiblesPlugin.BibleManager', 'Scripture Reference Error'),
translate('BiblesPlugin.BibleManager', translate('BiblesPlugin.BibleManager',
@ -700,10 +759,12 @@ class BibleMediaItem(MediaManagerItem):
self.text_reference_search(text) self.text_reference_search(text)
else: else:
# It can only be a 'Combined' search without a valid reference, or a 'Text' search # It can only be a 'Combined' search without a valid reference, or a 'Text' search
if search_while_type: if self.search_status == SearchStatus().SearchAsYouType:
if len(text) > 8 and VALID_TEXT_SEARCH.search(text): if len(text) <= 8:
self.on_text_search(text, True) self.search_status = SearchStatus.NotEnoughText
elif VALID_TEXT_SEARCH.search(text): self.display_results()
return
if VALID_TEXT_SEARCH.search(text):
self.on_text_search(text) self.on_text_search(text)
def on_search_edit_text_changed(self): def on_search_edit_text_changed(self):
@ -724,7 +785,9 @@ class BibleMediaItem(MediaManagerItem):
:return: None :return: None
""" """
self.text_search(True) self.search_status = SearchStatus().SearchAsYouType
self.text_search()
self.results_view_tab.setCurrentIndex(ResultsTab.Search)
def display_results(self): def display_results(self):
""" """
@ -732,14 +795,16 @@ class BibleMediaItem(MediaManagerItem):
:return: None :return: None
""" """
self.list_view.clear() self.current_results = self.build_display_results(self.bible, self.second_bible, self.search_results)
if self.search_results:
items = self.build_display_results(self.bible, self.second_bible, self.search_results)
for item in items:
self.list_view.addItem(item)
self.list_view.selectAll()
self.search_results = [] self.search_results = []
self.second_search_results = [] self.add_built_results_to_list_widget(self.current_results)
def add_built_results_to_list_widget(self, results):
self.list_view.clear(self.search_status == SearchStatus.NotEnoughText)
for item in self.build_list_widget_items(results):
self.list_view.addItem(item)
self.list_view.selectAll()
self.on_results_view_tab_total_update(ResultsTab.Search)
def build_display_results(self, bible, second_bible, search_results): def build_display_results(self, bible, second_bible, search_results):
""" """
@ -789,11 +854,19 @@ class BibleMediaItem(MediaManagerItem):
bible_text = '{book} {chapter:d}{sep}{verse:d} ({version}, {second_version})' bible_text = '{book} {chapter:d}{sep}{verse:d} ({version}, {second_version})'
else: else:
bible_text = '{book} {chapter:d}{sep}{verse:d} ({version})' bible_text = '{book} {chapter:d}{sep}{verse:d} ({version})'
bible_verse = QtWidgets.QListWidgetItem(bible_text.format(sep=verse_separator, **data)) data['item_title'] = bible_text.format(sep=verse_separator, **data)
bible_verse.setData(QtCore.Qt.UserRole, data) items.append(data)
items.append(bible_verse)
return items return items
def build_list_widget_items(self, items):
list_widget_items = []
for data in items:
bible_verse = QtWidgets.QListWidgetItem(data['item_title'])
bible_verse.setData(QtCore.Qt.UserRole, data)
list_widget_items.append(bible_verse)
return list_widget_items
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
context=ServiceItemContext.Service): context=ServiceItemContext.Service):
""" """
@ -910,4 +983,5 @@ class BibleMediaItem(MediaManagerItem):
""" """
reference = self.plugin.manager.parse_ref(self.bible.name, item_id) reference = self.plugin.manager.parse_ref(self.bible.name, item_id)
search_results = self.plugin.manager.get_verses(self.bible.name, reference, False) search_results = self.plugin.manager.get_verses(self.bible.name, reference, False)
return self.build_display_results(self.bible, None, search_results) items = self.build_display_results(self.bible, None, search_results)
return self.build_list_widget_items(items)

View File

@ -33,37 +33,6 @@ class TestListWidgetWithDnD(TestCase):
""" """
Test the :class:`~openlp.core.lib.listwidgetwithdnd.ListWidgetWithDnD` class Test the :class:`~openlp.core.lib.listwidgetwithdnd.ListWidgetWithDnD` class
""" """
def test_clear_locked(self):
"""
Test the clear method the list is 'locked'
"""
with patch('openlp.core.ui.lib.listwidgetwithdnd.QtWidgets.QListWidget.clear') as mocked_clear_super_method:
# GIVEN: An instance of ListWidgetWithDnD
widget = ListWidgetWithDnD()
# WHEN: The list is 'locked' and clear has been called
widget.locked = True
widget.clear()
# THEN: The super method should not have been called (i.e. The list not cleared)
self.assertFalse(mocked_clear_super_method.called)
def test_clear_overide_locked(self):
"""
Test the clear method the list is 'locked', but clear is called with 'override_lock' set to True
"""
with patch('openlp.core.ui.lib.listwidgetwithdnd.QtWidgets.QListWidget.clear') as mocked_clear_super_method:
# GIVEN: An instance of ListWidgetWithDnD
widget = ListWidgetWithDnD()
# WHEN: The list is 'locked' and clear has been called with override_lock se to True
widget.locked = True
widget.clear(override_lock=True)
# THEN: The super method should have been called (i.e. The list is cleared regardless whether it is locked
# or not)
mocked_clear_super_method.assert_called_once_with()
def test_clear(self): def test_clear(self):
""" """
Test the clear method when called without any arguments. Test the clear method when called without any arguments.

100
tests/functional/openlp_plugins/bibles/test_mediaitem.py Normal file → Executable file
View File

@ -31,7 +31,8 @@ from tests.helpers.testmixin import TestMixin
from openlp.core.common import Registry from openlp.core.common import Registry
from openlp.core.lib import MediaManagerItem from openlp.core.lib import MediaManagerItem
from openlp.plugins.bibles.lib.mediaitem import BibleMediaItem, BibleSearch, get_reference_separators, VALID_TEXT_SEARCH from openlp.plugins.bibles.lib.mediaitem import BibleMediaItem, BibleSearch, ResultsTab, SearchStatus, \
get_reference_separators, VALID_TEXT_SEARCH
class TestBibleMediaItemModulefunctions(TestCase): class TestBibleMediaItemModulefunctions(TestCase):
@ -143,6 +144,7 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item = BibleMediaItem(None, self.mocked_plugin) self.media_item = BibleMediaItem(None, self.mocked_plugin)
self.media_item.settings_section = 'bibles' self.media_item.settings_section = 'bibles'
self.media_item.results_view_tab = MagicMock()
self.mocked_book_1 = MagicMock(**{'get_name.return_value': 'Book 1', 'book_reference_id': 1}) self.mocked_book_1 = MagicMock(**{'get_name.return_value': 'Book 1', 'book_reference_id': 1})
self.mocked_book_2 = MagicMock(**{'get_name.return_value': 'Book 2', 'book_reference_id': 2}) self.mocked_book_2 = MagicMock(**{'get_name.return_value': 'Book 2', 'book_reference_id': 2})
@ -156,6 +158,7 @@ class TestMediaItem(TestCase, TestMixin):
self.mocked_bible_2 = MagicMock(**{'get_books.return_value': self.book_list_2}) self.mocked_bible_2 = MagicMock(**{'get_books.return_value': self.book_list_2})
self.mocked_bible_2.name = 'Bible 2' self.mocked_bible_2.name = 'Bible 2'
def test_media_item_instance(self): def test_media_item_instance(self):
""" """
When creating an instance of C test that it is also an instance of When creating an instance of C test that it is also an instance of
@ -658,56 +661,66 @@ class TestMediaItem(TestCase, TestMixin):
# THEN: The select_book_combo_box model sort should have been reset # THEN: The select_book_combo_box model sort should have been reset
self.media_item.select_book_combo_box.model().sort.assert_called_once_with(-1) self.media_item.select_book_combo_box.model().sort.assert_called_once_with(-1)
def test_on_clear_button_clicked(self): def test_on_clear_button_clicked_saved_tab(self):
""" """
Test on_clear_button_clicked Test on_clear_button_clicked when the saved tab is selected
"""
# GIVEN: An instance of :class:`MediaManagerItem` and mocked out saved_tab and select_tab and a mocked out
# list_view and search_edit
self.media_item.list_view = MagicMock()
self.media_item.search_edit = MagicMock()
self.media_item.results_view_tab = MagicMock(**{'currentIndex.return_value': ResultsTab.Saved})
self.media_item.saved_results = ['Some', 'Results']
with patch.object(self.media_item, 'on_focus'):
# WHEN: Calling on_clear_button_clicked
self.media_item.on_clear_button_clicked()
# THEN: The list_view should be cleared
self.assertEqual(self.media_item.saved_results, [])
self.media_item.list_view.clear.assert_called_once_with()
def test_on_clear_button_clicked_search_tab(self):
"""
Test on_clear_button_clicked when the search tab is selected
""" """
# GIVEN: An instance of :class:`MediaManagerItem` and mocked out search_tab and select_tab and a mocked out # GIVEN: An instance of :class:`MediaManagerItem` and mocked out search_tab and select_tab and a mocked out
# list_view and search_edit # list_view and search_edit
self.media_item.list_view = MagicMock() self.media_item.list_view = MagicMock()
self.media_item.search_edit = MagicMock() self.media_item.search_edit = MagicMock()
self.media_item.results_view_tab = MagicMock(**{'currentIndex.return_value': ResultsTab.Search})
self.media_item.current_results = ['Some', 'Results']
with patch.object(self.media_item, 'on_focus'): with patch.object(self.media_item, 'on_focus'):
# WHEN: Calling on_clear_button_clicked # WHEN: Calling on_clear_button_clicked
self.media_item.on_clear_button_clicked() self.media_item.on_clear_button_clicked()
# THEN: The list_view and the search_edit should be cleared # THEN: The list_view and the search_edit should be cleared
self.assertEqual(self.media_item.current_results, [])
self.media_item.list_view.clear.assert_called_once_with() self.media_item.list_view.clear.assert_called_once_with()
self.media_item.search_edit.clear.assert_called_once_with() self.media_item.search_edit.clear.assert_called_once_with()
def test_on_lock_button_toggled_search_tab_lock_icon(self):
def test_on_save_results_button_clicked(self):
""" """
Test that "on_lock_button_toggled" toggles the lock properly. Test that "on_save_results_button_clicked" saves the results.
""" """
# GIVEN: An instance of :class:`MediaManagerItem` a mocked sender and list_view # GIVEN: An instance of :class:`MediaManagerItem` and a mocked list_view
self.media_item.list_view = MagicMock() result_1 = MagicMock(**{'data.return_value': 'R1'})
self.media_item.lock_icon = 'lock icon' result_2 = MagicMock(**{'data.return_value': 'R2'})
mocked_sender_instance = MagicMock() result_3 = MagicMock(**{'data.return_value': 'R3'})
with patch.object(self.media_item, 'sender', return_value=mocked_sender_instance): self.media_item.list_view = MagicMock(**{'selectedItems.return_value': [result_1, result_2, result_3]})
# WHEN: When the lock_button is checked with patch.object(self.media_item, 'on_results_view_tab_total_update') as \
self.media_item.on_lock_button_toggled(True) mocked_on_results_view_tab_total_update :
# THEN: list_view should be 'locked' and the lock icon set # WHEN: When the save_results_button is clicked
self.assertTrue(self.media_item.list_view.locked) self.media_item.on_save_results_button_clicked()
mocked_sender_instance.setIcon.assert_called_once_with('lock icon')
def test_on_lock_button_toggled_unlock_icon(self): # THEN: The selected results in the list_view should be added to the 'saved_results' list. And the saved_tab
""" # total should be updated.
Test that "on_lock_button_toggled" toggles the lock properly. self.assertEqual(self.media_item.saved_results, ['R1', 'R2', 'R3'])
""" mocked_on_results_view_tab_total_update.assert_called_once_with(ResultsTab.Saved)
# GIVEN: An instance of :class:`MediaManagerItem` a mocked sender and list_view
self.media_item.list_view = MagicMock()
self.media_item.unlock_icon = 'unlock icon'
mocked_sender_instance = MagicMock()
with patch.object(self.media_item, 'sender', return_value=mocked_sender_instance):
# WHEN: When the lock_button is unchecked
self.media_item.on_lock_button_toggled(False)
# THEN: list_view should be 'unlocked' and the unlock icon set
self.assertFalse(self.media_item.list_view.locked)
mocked_sender_instance.setIcon.assert_called_once_with('unlock icon')
def test_on_style_combo_box_changed(self): def test_on_style_combo_box_changed(self):
""" """
@ -815,7 +828,9 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.list_view = MagicMock(**{'count.return_value': 5}) self.media_item.list_view = MagicMock(**{'count.return_value': 5})
self.media_item.style_combo_box = MagicMock() self.media_item.style_combo_box = MagicMock()
self.media_item.select_book_combo_box = MagicMock() self.media_item.select_book_combo_box = MagicMock()
self.media_item.search_results = ['list', 'of', 'results']
with patch.object(self.media_item, 'initialise_advanced_bible') as mocked_initialise_advanced_bible, \ with patch.object(self.media_item, 'initialise_advanced_bible') as mocked_initialise_advanced_bible, \
patch.object(self.media_item, 'display_results'), \
patch('openlp.plugins.bibles.lib.mediaitem.critical_error_message_box', patch('openlp.plugins.bibles.lib.mediaitem.critical_error_message_box',
return_value=QtWidgets.QMessageBox.Yes) as mocked_critical_error_message_box: return_value=QtWidgets.QMessageBox.Yes) as mocked_critical_error_message_box:
@ -825,9 +840,8 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.second_combo_box = MagicMock(**{'currentData.return_value': self.mocked_bible_1}) self.media_item.second_combo_box = MagicMock(**{'currentData.return_value': self.mocked_bible_1})
self.media_item.on_second_combo_box_index_changed(5) self.media_item.on_second_combo_box_index_changed(5)
# THEN: The list_view should be cleared and the selected bible should be set as the current bible # THEN: The selected bible should be set as the current bible
self.assertTrue(mocked_critical_error_message_box.called) self.assertTrue(mocked_critical_error_message_box.called)
self.media_item.list_view.clear.assert_called_once_with(override_lock=True)
self.media_item.style_combo_box.setEnabled.assert_called_once_with(False) self.media_item.style_combo_box.setEnabled.assert_called_once_with(False)
self.assertTrue(mocked_initialise_advanced_bible.called) self.assertTrue(mocked_initialise_advanced_bible.called)
self.assertEqual(self.media_item.second_bible, self.mocked_bible_1) self.assertEqual(self.media_item.second_bible, self.mocked_bible_1)
@ -841,7 +855,9 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.list_view = MagicMock(**{'count.return_value': 5}) self.media_item.list_view = MagicMock(**{'count.return_value': 5})
self.media_item.style_combo_box = MagicMock() self.media_item.style_combo_box = MagicMock()
self.media_item.select_book_combo_box = MagicMock() self.media_item.select_book_combo_box = MagicMock()
self.media_item.search_results = ['list', 'of', 'results']
with patch.object(self.media_item, 'initialise_advanced_bible') as mocked_initialise_advanced_bible, \ with patch.object(self.media_item, 'initialise_advanced_bible') as mocked_initialise_advanced_bible, \
patch.object(self.media_item, 'display_results'), \
patch('openlp.plugins.bibles.lib.mediaitem.critical_error_message_box', patch('openlp.plugins.bibles.lib.mediaitem.critical_error_message_box',
return_value=QtWidgets.QMessageBox.Yes) as mocked_critical_error_message_box: return_value=QtWidgets.QMessageBox.Yes) as mocked_critical_error_message_box:
# WHEN: The previously is a bible new selection is None and the user selects yes # WHEN: The previously is a bible new selection is None and the user selects yes
@ -850,9 +866,8 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.second_combo_box = MagicMock(**{'currentData.return_value': None}) self.media_item.second_combo_box = MagicMock(**{'currentData.return_value': None})
self.media_item.on_second_combo_box_index_changed(0) self.media_item.on_second_combo_box_index_changed(0)
# THEN: The list_view should be cleared and the selected bible should be set as the current bible # THEN: The selected bible should be set as the current bible
self.assertTrue(mocked_critical_error_message_box.called) self.assertTrue(mocked_critical_error_message_box.called)
self.media_item.list_view.clear.assert_called_once_with(override_lock=True)
self.media_item.style_combo_box.setEnabled.assert_called_once_with(True) self.media_item.style_combo_box.setEnabled.assert_called_once_with(True)
self.assertFalse(mocked_initialise_advanced_bible.called) self.assertFalse(mocked_initialise_advanced_bible.called)
self.assertEqual(self.media_item.second_bible, None) self.assertEqual(self.media_item.second_bible, None)
@ -1388,8 +1403,9 @@ class TestMediaItem(TestCase, TestMixin):
# WHEN: Calling on_search_timer_timeout # WHEN: Calling on_search_timer_timeout
self.media_item.on_search_timer_timeout() self.media_item.on_search_timer_timeout()
# THEN: The text_search method should have been called with True # THEN: The search_status should be set to SearchAsYouType and text_search should have been called
mocked_text_search.assert_called_once_with(True) self.assertEqual(self.media_item.search_status, SearchStatus().SearchAsYouType)
mocked_text_search.assert_called_once_with()
def test_display_results_no_results(self): def test_display_results_no_results(self):
""" """
@ -1407,7 +1423,6 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.display_results() self.media_item.display_results()
# THEN: No items should be added to the list # THEN: No items should be added to the list
self.media_item.list_view.clear.assert_called_once_with()
self.assertFalse(self.media_item.list_view.addItem.called) self.assertFalse(self.media_item.list_view.addItem.called)
def test_display_results_results(self): def test_display_results_results(self):
@ -1415,7 +1430,10 @@ class TestMediaItem(TestCase, TestMixin):
Test the display_results method when there are items to display Test the display_results method when there are items to display
""" """
# GIVEN: An instance of BibleMediaItem and a mocked build_display_results which returns a list of results # GIVEN: An instance of BibleMediaItem and a mocked build_display_results which returns a list of results
with patch.object(self.media_item, 'build_display_results', return_value=['list', 'items']): with patch.object(self.media_item, 'build_display_results', return_value=[
{'item_title': 'Title 1'}, {'item_title': 'Title 2'}]), \
patch.object(self.media_item, 'add_built_results_to_list_widget') as \
mocked_add_built_results_to_list_widget:
self.media_item.search_results = ['results'] self.media_item.search_results = ['results']
self.media_item.list_view = MagicMock() self.media_item.list_view = MagicMock()
@ -1423,5 +1441,5 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item.display_results() self.media_item.display_results()
# THEN: addItem should have been with the display items # THEN: addItem should have been with the display items
self.media_item.list_view.clear.assert_called_once_with() mocked_add_built_results_to_list_widget.assert_called_once_with(
self.assertEqual(self.media_item.list_view.addItem.call_args_list, [call('list'), call('items')]) [{'item_title': 'Title 1'}, {'item_title': 'Title 2'}])