diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 75917c55d..0ab98a0a4 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -103,6 +103,13 @@ class Book(BaseModel): """ Book model """ + @property + def songs(self): + """ + A property to return the songs associated with this book. + """ + return [sbe.song for sbe in self.entries] + def __repr__(self): return ''.format(myid=self.id, name=self.name, @@ -383,7 +390,7 @@ def init_schema(url): class_mapper(SongBookEntry) except UnmappedClassError: mapper(SongBookEntry, songs_songbooks_table, properties={ - 'songbook': relation(Book) + 'songbook': relation(Book, backref='entries') }) try: class_mapper(Book) diff --git a/tests/openlp_plugins/songs/forms/test_songmaintenanceform.py b/tests/openlp_plugins/songs/forms/test_songmaintenanceform.py index 8808605f3..7049b52c3 100644 --- a/tests/openlp_plugins/songs/forms/test_songmaintenanceform.py +++ b/tests/openlp_plugins/songs/forms/test_songmaintenanceform.py @@ -24,7 +24,7 @@ Package to test the openlp.plugins.songs.forms.songmaintenanceform package. import pytest import os -from unittest.mock import MagicMock, call, patch, ANY +from unittest.mock import MagicMock, call, create_autospec, patch, ANY from PyQt5 import QtCore, QtWidgets @@ -208,10 +208,43 @@ def test_delete_item(mocked_critical_error_message_box, form_env): mocked_get_current_item_id.assert_called_once_with(mocked_list_widget) mocked_manager.get_object.assert_called_once_with(mocked_item_class, 1) mocked_critical_error_message_box.assert_called_once_with(dialog_title, delete_text, form, True) - mocked_manager.delete_object(mocked_item_class, 1) + mocked_manager.delete_object.assert_called_once_with(mocked_item_class, 1) mocked_reset_func.assert_called_once_with() +@patch('openlp.plugins.songs.forms.songmaintenanceform.critical_error_message_box') +def test_delete_book_assigned(mocked_critical_error_message_box, form_env): + """ + Test the _delete_item() method + """ + # GIVEN: Some mocked items + form = form_env[0] + mocked_manager = form_env[1] + mocked_item = create_autospec(Book, spec_set=True) + mocked_item.id = 1 + mocked_manager.get_object.return_value = mocked_item + mocked_critical_error_message_box.return_value = QtWidgets.QMessageBox.Yes + mocked_item_class = MagicMock() + mocked_list_widget = MagicMock() + mocked_reset_func = MagicMock() + dialog_title = 'Delete Book' + delete_text = 'Are you sure you want to delete the selected book?' + error_text = 'This book cannot be deleted, it is currenty assigned to at least one song.' + + # WHEN: _delete_item() is called + with patch.object(form, '_get_current_item_id') as mocked_get_current_item_id: + mocked_get_current_item_id.return_value = 1 + form._delete_item(mocked_item_class, mocked_list_widget, mocked_reset_func, dialog_title, delete_text, + error_text) + + # THEN: The right things should have been called + mocked_get_current_item_id.assert_called_once_with(mocked_list_widget) + mocked_manager.get_object.assert_called_once_with(mocked_item_class, 1) + mocked_critical_error_message_box.assert_called_once_with(dialog_title, error_text) + mocked_manager.delete_object.assert_not_called() + mocked_reset_func.assert_not_called() + + @patch('openlp.plugins.songs.forms.songmaintenanceform.QtWidgets.QListWidgetItem') @patch('openlp.plugins.songs.forms.songmaintenanceform.Author') def test_reset_authors(MockedAuthor, MockedQListWidgetItem, form_env):