forked from openlp/openlp
Found and fixed some tests that were not getting picked up
bzr-revno: 2782
This commit is contained in:
commit
f7e1dcbea1
@ -96,6 +96,8 @@ class BibleImport(BibleDB, LogMixin, RegistryProperties):
|
||||
if language_form.exec(bible_name):
|
||||
combo_box = language_form.language_combo_box
|
||||
language_id = combo_box.itemData(combo_box.currentIndex())
|
||||
else:
|
||||
return False
|
||||
if not language_id:
|
||||
return None
|
||||
self.save_meta('language_id', language_id)
|
||||
|
@ -347,7 +347,7 @@ class TestInit(TestCase, TestMixin):
|
||||
self.assertTrue(mocked_log.exception.called)
|
||||
self.assertFalse(result, 'delete_file should return False when an OSError is raised')
|
||||
|
||||
def test_get_file_encoding_done_test(self):
|
||||
def test_get_file_encoding_done(self):
|
||||
"""
|
||||
Test get_file_encoding when the detector sets done to True
|
||||
"""
|
||||
@ -368,7 +368,7 @@ class TestInit(TestCase, TestMixin):
|
||||
mocked_universal_detector_inst.close.assert_called_once_with()
|
||||
self.assertEqual(result, encoding_result)
|
||||
|
||||
def test_get_file_encoding_eof_test(self):
|
||||
def test_get_file_encoding_eof(self):
|
||||
"""
|
||||
Test get_file_encoding when the end of the file is reached
|
||||
"""
|
||||
@ -390,7 +390,7 @@ class TestInit(TestCase, TestMixin):
|
||||
mocked_universal_detector_inst.close.assert_called_once_with()
|
||||
self.assertEqual(result, encoding_result)
|
||||
|
||||
def test_get_file_encoding_oserror_test(self):
|
||||
def test_get_file_encoding_oserror(self):
|
||||
"""
|
||||
Test get_file_encoding when the end of the file is reached
|
||||
"""
|
||||
|
@ -62,7 +62,7 @@ class TestFirstTimeForm(TestCase, TestMixin):
|
||||
self.assertTrue('OpenLP 3.1.5 build 3000' in about_form.about_text_edit.toPlainText(),
|
||||
"The build number should be set correctly")
|
||||
|
||||
def test_about_form_date_test(self):
|
||||
def test_about_form_date(self):
|
||||
"""
|
||||
Test that the copyright date is included correctly
|
||||
"""
|
||||
|
@ -691,7 +691,7 @@ class TestSlideController(TestCase):
|
||||
])
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def on_preview_double_click_unblank_display_test(self, MockedSettings):
|
||||
def test_on_preview_double_click_unblank_display(self, MockedSettings):
|
||||
# GIVEN: A slide controller, actions needed, settins set to True.
|
||||
slide_controller = SlideController(None)
|
||||
mocked_settings = MagicMock()
|
||||
@ -714,7 +714,7 @@ class TestSlideController(TestCase):
|
||||
self.assertEqual(0, slide_controller.on_preview_add_to_service.call_count, 'Should have not been called.')
|
||||
|
||||
@patch('openlp.core.ui.slidecontroller.Settings')
|
||||
def on_preview_double_click_add_to_service_test(self, MockedSettings):
|
||||
def test_on_preview_double_click_add_to_service(self, MockedSettings):
|
||||
# GIVEN: A slide controller, actions needed, settins set to False.
|
||||
slide_controller = SlideController(None)
|
||||
mocked_settings = MagicMock()
|
||||
|
@ -66,7 +66,7 @@ class TestBibleImport(TestCase):
|
||||
self.addCleanup(self.registry_patcher.stop)
|
||||
self.registry_patcher.start()
|
||||
|
||||
def init_kwargs_none_test(self):
|
||||
def test_init_kwargs_none(self):
|
||||
"""
|
||||
Test the initialisation of the BibleImport Class when no key word arguments are supplied
|
||||
"""
|
||||
@ -75,10 +75,10 @@ class TestBibleImport(TestCase):
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# THEN: The filename attribute should be None
|
||||
self.assertIsNone(instance.filename)
|
||||
self.assertIsInstance(instance, BibleDB)
|
||||
assert instance.filename is None
|
||||
assert isinstance(instance, BibleDB)
|
||||
|
||||
def init_kwargs_set_test(self):
|
||||
def test_init_kwargs_set(self):
|
||||
"""
|
||||
Test the initialisation of the BibleImport Class when supplied with select keyword arguments
|
||||
"""
|
||||
@ -88,268 +88,270 @@ class TestBibleImport(TestCase):
|
||||
instance = BibleImport(MagicMock(), **kwargs)
|
||||
|
||||
# THEN: The filename keyword should be set to bible.xml
|
||||
self.assertEqual(instance.filename, 'bible.xml')
|
||||
self.assertIsInstance(instance, BibleDB)
|
||||
assert instance.filename == 'bible.xml'
|
||||
assert isinstance(instance, BibleDB)
|
||||
|
||||
def get_language_canceled_test(self):
|
||||
@patch.object(BibleDB, '_setup')
|
||||
@patch('openlp.plugins.bibles.forms.LanguageForm')
|
||||
def test_get_language_canceled(self, MockedLanguageForm, mocked_setup):
|
||||
"""
|
||||
Test the BibleImport.get_language method when the user rejects the dialog box
|
||||
"""
|
||||
# GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Rejected and an instance of BibleDB
|
||||
with patch.object(BibleDB, '_setup'), patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
|
||||
# TODO: The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason
|
||||
MockedLanguageForm.return_value.exec.return_value = 0
|
||||
instance = BibleImport(MagicMock())
|
||||
mocked_wizard = MagicMock()
|
||||
instance.wizard = mocked_wizard
|
||||
|
||||
# The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason
|
||||
mocked_language_form_instance = MagicMock(**{'exec.return_value': 0})
|
||||
mocked_language_form.return_value = mocked_language_form_instance
|
||||
instance = BibleImport(MagicMock())
|
||||
mocked_wizard = MagicMock()
|
||||
instance.wizard = mocked_wizard
|
||||
# WHEN: Calling get_language()
|
||||
result = instance.get_language('ESV')
|
||||
|
||||
# WHEN: Calling get_language()
|
||||
result = instance.get_language()
|
||||
# THEN: get_language() should return False
|
||||
MockedLanguageForm.assert_called_once_with(mocked_wizard)
|
||||
MockedLanguageForm.return_value.exec.assert_called_once_with('ESV')
|
||||
assert result is False, 'get_language() should return False if the user rejects the dialog box'
|
||||
|
||||
# THEN: get_language() should return False
|
||||
mocked_language_form.assert_called_once_with(mocked_wizard)
|
||||
mocked_language_form_instance.exec.assert_called_once_with(None)
|
||||
self.assertFalse(result, 'get_language() should return False if the user rejects the dialog box')
|
||||
|
||||
def get_language_accepted_test(self):
|
||||
@patch.object(BibleDB, 'save_meta')
|
||||
@patch.object(BibleDB, '_setup')
|
||||
@patch('openlp.plugins.bibles.forms.LanguageForm')
|
||||
def test_get_language_accepted(self, MockedLanguageForm, mocked_setup, mocked_save_meta):
|
||||
"""
|
||||
Test the BibleImport.get_language method when the user accepts the dialog box
|
||||
"""
|
||||
# GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Accepted an instance of BibleDB and
|
||||
# a combobox with the selected item data as 10
|
||||
with patch.object(BibleDB, 'save_meta'), patch.object(BibleDB, '_setup'), \
|
||||
patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
|
||||
# The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason
|
||||
MockedLanguageForm.return_value.exec.return_value = 1
|
||||
MockedLanguageForm.return_value.language_combo_box.itemData.return_value = 10
|
||||
instance = BibleImport(MagicMock())
|
||||
mocked_wizard = MagicMock()
|
||||
instance.wizard = mocked_wizard
|
||||
|
||||
# The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason
|
||||
mocked_language_form_instance = MagicMock(**{'exec.return_value': 1,
|
||||
'language_combo_box.itemData.return_value': 10})
|
||||
mocked_language_form.return_value = mocked_language_form_instance
|
||||
instance = BibleImport(MagicMock())
|
||||
mocked_wizard = MagicMock()
|
||||
instance.wizard = mocked_wizard
|
||||
# WHEN: Calling get_language()
|
||||
result = instance.get_language('Bible Name')
|
||||
|
||||
# WHEN: Calling get_language()
|
||||
result = instance.get_language('Bible Name')
|
||||
# THEN: get_language() should return the id of the selected language in the combo box
|
||||
MockedLanguageForm.assert_called_once_with(mocked_wizard)
|
||||
MockedLanguageForm.return_value.exec.assert_called_once_with('Bible Name')
|
||||
assert result == 10, 'get_language() should return the id of the language the user has chosen when ' \
|
||||
'they accept the dialog box'
|
||||
|
||||
# THEN: get_language() should return the id of the selected language in the combo box
|
||||
mocked_language_form.assert_called_once_with(mocked_wizard)
|
||||
mocked_language_form_instance.exec.assert_called_once_with('Bible Name')
|
||||
self.assertEqual(result, 10, 'get_language() should return the id of the language the user has chosen when '
|
||||
'they accept the dialog box')
|
||||
|
||||
def get_language_id_language_found_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.get_language')
|
||||
@patch.object(BibleImport, 'get_language')
|
||||
def test_get_language_id_language_found(self, mocked_db_get_language, mocked_get_language):
|
||||
"""
|
||||
Test get_language_id() when called with a name found in the languages list
|
||||
"""
|
||||
# GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport
|
||||
with patch('openlp.core.common.languages.get_language', return_value=Language(30, 'English', 'en')) \
|
||||
as mocked_languages_get_language, \
|
||||
patch.object(BibleImport, 'get_language') as mocked_db_get_language:
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
mocked_get_language.return_value = Language(30, 'English', 'en')
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('English', 'KJV')
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('English', 'KJV')
|
||||
|
||||
# THEN: The id of the language returned from languages.get_language should be returned
|
||||
mocked_languages_get_language.assert_called_once_with('English')
|
||||
self.assertFalse(mocked_db_get_language.called)
|
||||
instance.save_meta.assert_called_once_with('language_id', 30)
|
||||
self.assertEqual(result, 30)
|
||||
# THEN: The id of the language returned from languages.get_language should be returned
|
||||
mocked_get_language.assert_called_once_with('English')
|
||||
assert mocked_db_get_language.called is False
|
||||
instance.save_meta.assert_called_once_with('language_id', 30)
|
||||
assert result == 30, 'Result should be 30, was {}'.format(result)
|
||||
|
||||
def get_language_id_language_not_found_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.get_language', return_value=None)
|
||||
@patch.object(BibleImport, 'get_language', return_value=20)
|
||||
def test_get_language_id_language_not_found(self, mocked_db_get_language, mocked_languages_get_language):
|
||||
"""
|
||||
Test get_language_id() when called with a name not found in the languages list
|
||||
"""
|
||||
# GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport
|
||||
with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
|
||||
patch.object(BibleImport, 'get_language', return_value=20) as mocked_db_get_language:
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('RUS', 'KJV')
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('RUS', 'KJV')
|
||||
|
||||
# THEN: The id of the language returned from languages.get_language should be returned
|
||||
mocked_languages_get_language.assert_called_once_with('RUS')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
instance.save_meta.assert_called_once_with('language_id', 20)
|
||||
self.assertEqual(result, 20)
|
||||
# THEN: The id of the language returned from languages.get_language should be returned
|
||||
mocked_languages_get_language.assert_called_once_with('RUS')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
instance.save_meta.assert_called_once_with('language_id', 20)
|
||||
assert result == 20
|
||||
|
||||
def get_language_id_user_choice_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.get_language', return_value=None)
|
||||
@patch.object(BibleImport, 'get_language', return_value=40)
|
||||
@patch.object(BibleImport, 'log_error')
|
||||
def test_get_language_id_user_choice(self, mocked_log_error, mocked_db_get_language, mocked_languages_get_language):
|
||||
"""
|
||||
Test get_language_id() when the language is not found and the user is asked for the language
|
||||
"""
|
||||
# GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a
|
||||
# language id.
|
||||
with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
|
||||
patch.object(BibleImport, 'get_language', return_value=40) as mocked_db_get_language, \
|
||||
patch.object(BibleImport, 'log_error') as mocked_log_error:
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('English', 'KJV')
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('English', 'KJV')
|
||||
|
||||
# THEN: The id of the language returned from BibleDB.get_language should be returned
|
||||
mocked_languages_get_language.assert_called_once_with('English')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
self.assertFalse(mocked_log_error.error.called)
|
||||
instance.save_meta.assert_called_once_with('language_id', 40)
|
||||
self.assertEqual(result, 40)
|
||||
# THEN: The id of the language returned from BibleDB.get_language should be returned
|
||||
mocked_languages_get_language.assert_called_once_with('English')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
assert mocked_log_error.error.called is False
|
||||
instance.save_meta.assert_called_once_with('language_id', 40)
|
||||
assert result == 40
|
||||
|
||||
def get_language_id_user_choice_rejected_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.get_language', return_value=None)
|
||||
@patch.object(BibleImport, 'get_language', return_value=None)
|
||||
@patch.object(BibleImport, 'log_error')
|
||||
def test_get_language_id_user_choice_rejected(self, mocked_log_error, mocked_db_get_language,
|
||||
mocked_languages_get_language):
|
||||
"""
|
||||
Test get_language_id() when the language is not found and the user rejects the dilaog box
|
||||
"""
|
||||
# GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a
|
||||
# language id.
|
||||
with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
|
||||
patch.object(BibleImport, 'get_language', return_value=None) as mocked_db_get_language, \
|
||||
patch.object(BibleImport, 'log_error') as mocked_log_error:
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
instance = BibleImport(MagicMock())
|
||||
instance.save_meta = MagicMock()
|
||||
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('Qwerty', 'KJV')
|
||||
# WHEN: Calling get_language_id() with a language name and bible name
|
||||
result = instance.get_language_id('Qwerty', 'KJV')
|
||||
|
||||
# THEN: None should be returned and an error should be logged
|
||||
mocked_languages_get_language.assert_called_once_with('Qwerty')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
mocked_log_error.assert_called_once_with(
|
||||
'Language detection failed when importing from "KJV". User aborted language selection.')
|
||||
self.assertFalse(instance.save_meta.called)
|
||||
self.assertIsNone(result)
|
||||
# THEN: None should be returned and an error should be logged
|
||||
mocked_languages_get_language.assert_called_once_with('Qwerty')
|
||||
mocked_db_get_language.assert_called_once_with('KJV')
|
||||
mocked_log_error.assert_called_once_with(
|
||||
'Language detection failed when importing from "KJV". User aborted language selection.')
|
||||
assert instance.save_meta.called is False
|
||||
assert result is None
|
||||
|
||||
def get_book_ref_id_by_name_get_book_test(self):
|
||||
@patch.object(BibleImport, 'log_debug')
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', **{'get_book.return_value': {'id': 20}})
|
||||
def test_get_book_ref_id_by_name_get_book(self, MockBibleResourcesDB, mocked_log_debug):
|
||||
"""
|
||||
Test get_book_ref_id_by_name when the book is found as a book in BiblesResourcesDB
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when get_book is
|
||||
# called
|
||||
with patch.object(BibleImport, 'log_debug'), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': {'id': 20}}):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
|
||||
# THEN: The bible id should be returned
|
||||
self.assertEqual(result, 20)
|
||||
# THEN: The bible id should be returned
|
||||
assert result == 20
|
||||
|
||||
def get_book_ref_id_by_name_get_alternative_book_name_test(self):
|
||||
@patch.object(BibleImport, 'log_debug')
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': 30})
|
||||
def test_get_book_ref_id_by_name_get_alternative_book_name(self, MockBibleResourcesDB, mocked_log_debug):
|
||||
"""
|
||||
Test get_book_ref_id_by_name when the book is found as an alternative book in BiblesResourcesDB
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when
|
||||
# get_alternative_book_name is called
|
||||
with patch.object(BibleImport, 'log_debug'), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': 30}):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
|
||||
# THEN: The bible id should be returned
|
||||
self.assertEqual(result, 30)
|
||||
# THEN: The bible id should be returned
|
||||
assert result == 30
|
||||
|
||||
def get_book_ref_id_by_name_get_book_reference_id_test(self):
|
||||
@patch.object(BibleImport, 'log_debug')
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None})
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB', **{'get_book_reference_id.return_value': 40})
|
||||
def test_get_book_ref_id_by_name_get_book_reference_id(self, MockAlterativeBookNamesDB, MockBibleResourcesDB,
|
||||
mocked_log_debug):
|
||||
"""
|
||||
Test get_book_ref_id_by_name when the book is found as a book in AlternativeBookNamesDB
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked AlternativeBookNamesDB which returns a book id when
|
||||
# get_book_reference_id is called
|
||||
with patch.object(BibleImport, 'log_debug'), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
|
||||
**{'get_book_reference_id.return_value': 40}):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
|
||||
# THEN: The bible id should be returned
|
||||
self.assertEqual(result, 40)
|
||||
# THEN: The bible id should be returned
|
||||
assert result == 40
|
||||
|
||||
def get_book_ref_id_by_name_book_name_form_rejected_test(self):
|
||||
@patch.object(BibleImport, 'log_debug')
|
||||
@patch.object(BibleImport, 'get_books')
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None})
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
|
||||
**{'get_book_reference_id.return_value': None})
|
||||
@patch('openlp.plugins.bibles.forms.BookNameForm',
|
||||
return_value=MagicMock(**{'exec.return_value': QDialog.Rejected}))
|
||||
def test_get_book_ref_id_by_name_book_name_form_rejected(self, MockBookNameForm, MockAlterativeBookNamesDB,
|
||||
MockBibleResourcesDB, mocked_get_books, mocked_log_debug):
|
||||
"""
|
||||
Test get_book_ref_id_by_name when the user rejects the BookNameForm
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user rejecting the dialog
|
||||
with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
|
||||
**{'get_book_reference_id.return_value': None}), \
|
||||
patch('openlp.plugins.bibles.forms.BookNameForm',
|
||||
return_value=MagicMock(**{'exec.return_value': QDialog.Rejected})):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
|
||||
# THEN: None should be returned
|
||||
self.assertIsNone(result)
|
||||
# THEN: None should be returned
|
||||
assert result is None
|
||||
|
||||
def get_book_ref_id_by_name_book_name_form_accepted_test(self):
|
||||
@patch.object(BibleImport, 'log_debug')
|
||||
@patch.object(BibleImport, 'get_books')
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None})
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
|
||||
**{'get_book_reference_id.return_value': None})
|
||||
@patch('openlp.plugins.bibles.forms.BookNameForm',
|
||||
return_value=MagicMock(**{'exec.return_value': QDialog.Accepted, 'book_id': 50}))
|
||||
def test_get_book_ref_id_by_name_book_name_form_accepted(self, MockBookNameForm, MockAlterativeBookNamesDB,
|
||||
MockBibleResourcesDB, mocked_get_books, mocked_log_debug):
|
||||
"""
|
||||
Test get_book_ref_id_by_name when the user accepts the BookNameForm
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user accepting the dialog
|
||||
with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
|
||||
**{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
|
||||
patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
|
||||
**{'get_book_reference_id.return_value': None}) as mocked_alternative_book_names_db, \
|
||||
patch('openlp.plugins.bibles.forms.BookNameForm',
|
||||
return_value=MagicMock(**{'exec.return_value': QDialog.Accepted, 'book_id': 50})):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
# WHEN: Calling get_book_ref_id_by_name
|
||||
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
||||
|
||||
# THEN: An alternative book name should be created and a bible id should be returned
|
||||
mocked_alternative_book_names_db.create_alternative_book_name.assert_called_once_with('Gen', 50, 4)
|
||||
self.assertEqual(result, 50)
|
||||
# THEN: An alternative book name should be created and a bible id should be returned
|
||||
MockAlterativeBookNamesDB.create_alternative_book_name.assert_called_once_with('Gen', 50, 4)
|
||||
assert result == 50
|
||||
|
||||
def is_compressed_compressed_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=True)
|
||||
def test_is_compressed_compressed(self, mocked_is_zipfile):
|
||||
"""
|
||||
Test is_compressed when the 'file' being tested is compressed
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked is_zipfile which returns True
|
||||
with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=True):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling is_compressed
|
||||
result = instance.is_compressed('file.ext')
|
||||
# WHEN: Calling is_compressed
|
||||
result = instance.is_compressed('file.ext')
|
||||
|
||||
# THEN: Then critical_error_message_box should be called informing the user that the file is compressed and
|
||||
# True should be returned
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='The file "file.ext" you supplied is compressed. You must decompress it before import.')
|
||||
self.assertTrue(result)
|
||||
# THEN: Then critical_error_message_box should be called informing the user that the file is compressed and
|
||||
# True should be returned
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='The file "file.ext" you supplied is compressed. You must decompress it before import.')
|
||||
assert result is True
|
||||
|
||||
def is_compressed_not_compressed_test(self):
|
||||
@patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=False)
|
||||
def test_is_compressed_not_compressed(self, mocked_is_zipfile):
|
||||
"""
|
||||
Test is_compressed when the 'file' being tested is not compressed
|
||||
"""
|
||||
# GIVEN: An instance of BibleImport and a mocked is_zipfile which returns False
|
||||
with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=False):
|
||||
instance = BibleImport(MagicMock())
|
||||
instance = BibleImport(MagicMock())
|
||||
|
||||
# WHEN: Calling is_compressed
|
||||
result = instance.is_compressed('file.ext')
|
||||
# WHEN: Calling is_compressed
|
||||
result = instance.is_compressed('file.ext')
|
||||
|
||||
# THEN: False should be returned and critical_error_message_box should not have been called
|
||||
self.assertFalse(result)
|
||||
self.assertFalse(self.mocked_critical_error_message_box.called)
|
||||
# THEN: False should be returned and critical_error_message_box should not have been called
|
||||
assert result is False
|
||||
assert self.mocked_critical_error_message_box.called is False
|
||||
|
||||
def parse_xml_etree_test(self):
|
||||
def test_parse_xml_etree(self):
|
||||
"""
|
||||
Test BibleImport.parse_xml() when called with the use_objectify default value
|
||||
"""
|
||||
@ -362,12 +364,11 @@ class TestBibleImport(TestCase):
|
||||
result = instance.parse_xml('file.tst')
|
||||
|
||||
# THEN: The result returned should contain the correct data, and should be an instance of eetree_Element
|
||||
self.assertEqual(etree.tostring(result),
|
||||
b'<root>\n <data><div>Test<p>data</p><a>to</a>keep</div></data>\n'
|
||||
b' <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n</root>')
|
||||
self.assertIsInstance(result, etree._Element)
|
||||
assert etree.tostring(result) == b'<root>\n <data><div>Test<p>data</p><a>to</a>keep</div></data>\n' \
|
||||
b' <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n</root>'
|
||||
assert isinstance(result, etree._Element)
|
||||
|
||||
def parse_xml_etree_use_objectify_test(self):
|
||||
def test_parse_xml_etree_use_objectify(self):
|
||||
"""
|
||||
Test BibleImport.parse_xml() when called with use_objectify set to True
|
||||
"""
|
||||
@ -380,12 +381,11 @@ class TestBibleImport(TestCase):
|
||||
result = instance.parse_xml('file.tst', use_objectify=True)
|
||||
|
||||
# THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement
|
||||
self.assertEqual(etree.tostring(result),
|
||||
b'<root><data><div>Test<p>data</p><a>to</a>keep</div></data>'
|
||||
b'<data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data></root>')
|
||||
self.assertIsInstance(result, objectify.ObjectifiedElement)
|
||||
assert etree.tostring(result) == b'<root><data><div>Test<p>data</p><a>to</a>keep</div></data>' \
|
||||
b'<data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data></root>'
|
||||
assert isinstance(result, objectify.ObjectifiedElement)
|
||||
|
||||
def parse_xml_elements_test(self):
|
||||
def test_parse_xml_elements(self):
|
||||
"""
|
||||
Test BibleImport.parse_xml() when given a tuple of elements to remove
|
||||
"""
|
||||
@ -399,10 +399,10 @@ class TestBibleImport(TestCase):
|
||||
result = instance.parse_xml('file.tst', elements=elements)
|
||||
|
||||
# THEN: The result returned should contain the correct data
|
||||
self.assertEqual(etree.tostring(result),
|
||||
b'<root>\n <data><div>Test<p>data</p><a>to</a>keep</div></data>\n <data/>\n</root>')
|
||||
assert etree.tostring(result) == \
|
||||
b'<root>\n <data><div>Test<p>data</p><a>to</a>keep</div></data>\n <data/>\n</root>'
|
||||
|
||||
def parse_xml_tags_test(self):
|
||||
def test_parse_xml_tags(self):
|
||||
"""
|
||||
Test BibleImport.parse_xml() when given a tuple of tags to remove
|
||||
"""
|
||||
@ -416,10 +416,10 @@ class TestBibleImport(TestCase):
|
||||
result = instance.parse_xml('file.tst', tags=tags)
|
||||
|
||||
# THEN: The result returned should contain the correct data
|
||||
self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data><unsupported>Test'
|
||||
b'<x>data</x><y>to</y>discard</unsupported></data>\n</root>')
|
||||
assert etree.tostring(result) == b'<root>\n <data>Testdatatokeep</data>\n <data><unsupported>Test' \
|
||||
b'<x>data</x><y>to</y>discard</unsupported></data>\n</root>'
|
||||
|
||||
def parse_xml_elements_tags_test(self):
|
||||
def test_parse_xml_elements_tags(self):
|
||||
"""
|
||||
Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove
|
||||
"""
|
||||
@ -434,53 +434,53 @@ class TestBibleImport(TestCase):
|
||||
result = instance.parse_xml('file.tst', elements=elements, tags=tags)
|
||||
|
||||
# THEN: The result returned should contain the correct data
|
||||
self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data/>\n</root>')
|
||||
assert etree.tostring(result) == b'<root>\n <data>Testdatatokeep</data>\n <data/>\n</root>'
|
||||
|
||||
def parse_xml_file_file_not_found_exception_test(self):
|
||||
@patch.object(BibleImport, 'log_exception')
|
||||
def test_parse_xml_file_file_not_found_exception(self, mocked_log_exception):
|
||||
"""
|
||||
Test that parse_xml handles a FileNotFoundError exception correctly
|
||||
"""
|
||||
with patch.object(BibleImport, 'log_exception') as mocked_log_exception:
|
||||
# GIVEN: A mocked open which raises a FileNotFoundError and an instance of BibleImporter
|
||||
exception = FileNotFoundError()
|
||||
exception.filename = 'file.tst'
|
||||
exception.strerror = 'No such file or directory'
|
||||
self.mocked_open.side_effect = exception
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
# GIVEN: A mocked open which raises a FileNotFoundError and an instance of BibleImporter
|
||||
exception = FileNotFoundError()
|
||||
exception.filename = 'file.tst'
|
||||
exception.strerror = 'No such file or directory'
|
||||
self.mocked_open.side_effect = exception
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling parse_xml
|
||||
result = importer.parse_xml('file.tst')
|
||||
# WHEN: Calling parse_xml
|
||||
result = importer.parse_xml('file.tst')
|
||||
|
||||
# THEN: parse_xml should have caught the error, informed the user and returned None
|
||||
mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
title='An Error Occured When Opening A File',
|
||||
message='The following error occurred when trying to open\nfile.tst:\n\nNo such file or directory')
|
||||
self.assertIsNone(result)
|
||||
# THEN: parse_xml should have caught the error, informed the user and returned None
|
||||
mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
title='An Error Occured When Opening A File',
|
||||
message='The following error occurred when trying to open\nfile.tst:\n\nNo such file or directory')
|
||||
assert result is None
|
||||
|
||||
def parse_xml_file_permission_error_exception_test(self):
|
||||
@patch.object(BibleImport, 'log_exception')
|
||||
def test_parse_xml_file_permission_error_exception(self, mocked_log_exception):
|
||||
"""
|
||||
Test that parse_xml handles a PermissionError exception correctly
|
||||
"""
|
||||
with patch.object(BibleImport, 'log_exception') as mocked_log_exception:
|
||||
# GIVEN: A mocked open which raises a PermissionError and an instance of BibleImporter
|
||||
exception = PermissionError()
|
||||
exception.filename = 'file.tst'
|
||||
exception.strerror = 'Permission denied'
|
||||
self.mocked_open.side_effect = exception
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
# GIVEN: A mocked open which raises a PermissionError and an instance of BibleImporter
|
||||
exception = PermissionError()
|
||||
exception.filename = 'file.tst'
|
||||
exception.strerror = 'Permission denied'
|
||||
self.mocked_open.side_effect = exception
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling parse_xml
|
||||
result = importer.parse_xml('file.tst')
|
||||
# WHEN: Calling parse_xml
|
||||
result = importer.parse_xml('file.tst')
|
||||
|
||||
# THEN: parse_xml should have caught the error, informed the user and returned None
|
||||
mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
title='An Error Occured When Opening A File',
|
||||
message='The following error occurred when trying to open\nfile.tst:\n\nPermission denied')
|
||||
self.assertIsNone(result)
|
||||
# THEN: parse_xml should have caught the error, informed the user and returned None
|
||||
mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
title='An Error Occured When Opening A File',
|
||||
message='The following error occurred when trying to open\nfile.tst:\n\nPermission denied')
|
||||
assert result is None
|
||||
|
||||
def set_current_chapter_test(self):
|
||||
def test_set_current_chapter(self):
|
||||
"""
|
||||
Test set_current_chapter
|
||||
"""
|
||||
@ -494,121 +494,121 @@ class TestBibleImport(TestCase):
|
||||
# THEN: Increment_progress_bar should have been called with a text string
|
||||
importer.wizard.increment_progress_bar.assert_called_once_with('Importing Book_Name Chapter...')
|
||||
|
||||
def validate_xml_file_compressed_file_test(self):
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=True)
|
||||
def test_validate_xml_file_compressed_file(self, mocked_is_compressed):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError when is_compressed returns True
|
||||
"""
|
||||
# GIVEN: A mocked parse_xml which returns None
|
||||
with patch.object(BibleImport, 'is_compressed', return_value=True):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling is_compressed
|
||||
# THEN: ValidationError should be raised, with the message 'Compressed file'
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Compressed file')
|
||||
# WHEN: Calling is_compressed
|
||||
# THEN: ValidationError should be raised, with the message 'Compressed file'
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Compressed file'
|
||||
|
||||
def validate_xml_file_parse_xml_fails_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml', return_value=None)
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_parse_xml_fails(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError when parse_xml returns None
|
||||
"""
|
||||
# GIVEN: A mocked parse_xml which returns None
|
||||
with patch.object(BibleImport, 'parse_xml', return_value=None), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, with the message 'Error when opening file'
|
||||
# the user that an OpenSong bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Error when opening file')
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, with the message 'Error when opening file'
|
||||
# the user that an OpenSong bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Error when opening file'
|
||||
|
||||
def validate_xml_file_success_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>'))
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_success(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file returns True with valid XML
|
||||
"""
|
||||
# GIVEN: Some test data with an OpenSong Bible "bible" root tag
|
||||
with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
result = importer.validate_xml_file('file.name', 'bible')
|
||||
# WHEN: Calling validate_xml_file
|
||||
result = importer.validate_xml_file('file.name', 'bible')
|
||||
|
||||
# THEN: True should be returned
|
||||
self.assertTrue(result)
|
||||
# THEN: True should be returned
|
||||
assert result is True
|
||||
|
||||
def validate_xml_file_opensong_root_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>'))
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_opensong_root(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError with an OpenSong root tag
|
||||
"""
|
||||
# GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
|
||||
with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an OpenSong bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Invalid xml.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an OpenSong XML bible.')
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an OpenSong bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Invalid xml.'
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an OpenSong XML bible.')
|
||||
|
||||
def validate_xml_file_osis_root_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml')
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_osis_root(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError with an OSIS root tag
|
||||
"""
|
||||
# GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
|
||||
with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring(
|
||||
'<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
mocked_parse_xml.return_value = objectify.fromstring(
|
||||
'<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an OSIS bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Invalid xml.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an OSIS XML bible.')
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an OSIS bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Invalid xml.'
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an OSIS XML bible.')
|
||||
|
||||
def validate_xml_file_zefania_root_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<xmlbible></xmlbible>'))
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_zefania_root(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError with an Zefania root tag
|
||||
"""
|
||||
# GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
|
||||
with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<xmlbible></xmlbible>')), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an Zefania bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Invalid xml.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an Zefania XML bible.')
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that an Zefania bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Invalid xml.'
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an Zefania XML bible.')
|
||||
|
||||
def validate_xml_file_unknown_root_test(self):
|
||||
@patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<unknownbible></unknownbible>'))
|
||||
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
||||
def test_validate_xml_file_unknown_root(self, mocked_is_compressed, mocked_parse_xml):
|
||||
"""
|
||||
Test that validate_xml_file raises a ValidationError with an unknown root tag
|
||||
"""
|
||||
# GIVEN: Some test data with an unknown root tag and an instance of BibleImport
|
||||
with patch.object(
|
||||
BibleImport, 'parse_xml', return_value=objectify.fromstring('<unknownbible></unknownbible>')), \
|
||||
patch.object(BibleImport, 'is_compressed', return_value=False):
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
importer = BibleImport(MagicMock(), path='.', name='.', filename='')
|
||||
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that a unknown xml bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
self.assertEqual(context.exception.msg, 'Invalid xml.')
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an unknown type of XML bible.')
|
||||
# WHEN: Calling validate_xml_file
|
||||
# THEN: ValidationError should be raised, and the critical error message box should was called informing
|
||||
# the user that a unknown xml bible was found
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
importer.validate_xml_file('file.name', 'xbible')
|
||||
assert context.exception.msg == 'Invalid xml.'
|
||||
self.mocked_critical_error_message_box.assert_called_once_with(
|
||||
message='Incorrect Bible file type supplied. This looks like an unknown type of XML bible.')
|
||||
|
@ -66,7 +66,7 @@ class TestCSVImport(TestCase):
|
||||
self.assertEqual(importer.books_file, 'books.csv')
|
||||
self.assertEqual(importer.verses_file, 'verse.csv')
|
||||
|
||||
def book_namedtuple_test(self):
|
||||
def test_book_namedtuple(self):
|
||||
"""
|
||||
Test that the Book namedtuple is created as expected
|
||||
"""
|
||||
@ -80,7 +80,7 @@ class TestCSVImport(TestCase):
|
||||
self.assertEqual(result.name, 'name')
|
||||
self.assertEqual(result.abbreviation, 'abbreviation')
|
||||
|
||||
def verse_namedtuple_test(self):
|
||||
def test_verse_namedtuple(self):
|
||||
"""
|
||||
Test that the Verse namedtuple is created as expected
|
||||
"""
|
||||
@ -94,7 +94,7 @@ class TestCSVImport(TestCase):
|
||||
self.assertEqual(result.number, 'number')
|
||||
self.assertEqual(result.text, 'text')
|
||||
|
||||
def get_book_name_id_test(self):
|
||||
def test_get_book_name_id(self):
|
||||
"""
|
||||
Test that get_book_name() returns the correct book when called with an id
|
||||
"""
|
||||
@ -109,7 +109,7 @@ class TestCSVImport(TestCase):
|
||||
# THEN: get_book_name() should return the book name associated with that id from the books dictionary
|
||||
self.assertEqual(actual_result, expected_result)
|
||||
|
||||
def get_book_name_test(self):
|
||||
def test_get_book_name(self):
|
||||
"""
|
||||
Test that get_book_name() returns the name when called with a non integer value
|
||||
"""
|
||||
@ -124,7 +124,7 @@ class TestCSVImport(TestCase):
|
||||
# THEN: get_book_name() should return the input
|
||||
self.assertEqual(actual_result, expected_result)
|
||||
|
||||
def parse_csv_file_test(self):
|
||||
def test_parse_csv_file(self):
|
||||
"""
|
||||
Test the parse_csv_file() with sample data
|
||||
"""
|
||||
@ -147,7 +147,7 @@ class TestCSVImport(TestCase):
|
||||
mocked_open.assert_called_once_with('file.csv', 'r', encoding='utf-8', newline='')
|
||||
mocked_reader.assert_called_once_with(ANY, delimiter=',', quotechar='"')
|
||||
|
||||
def parse_csv_file_oserror_test(self):
|
||||
def test_parse_csv_file_oserror(self):
|
||||
"""
|
||||
Test the parse_csv_file() handles an OSError correctly
|
||||
"""
|
||||
@ -162,7 +162,7 @@ class TestCSVImport(TestCase):
|
||||
CSVBible.parse_csv_file('file.csv', None)
|
||||
self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed')
|
||||
|
||||
def parse_csv_file_csverror_test(self):
|
||||
def test_parse_csv_file_csverror(self):
|
||||
"""
|
||||
Test the parse_csv_file() handles an csv.Error correctly
|
||||
"""
|
||||
@ -178,7 +178,7 @@ class TestCSVImport(TestCase):
|
||||
CSVBible.parse_csv_file('file.csv', None)
|
||||
self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed')
|
||||
|
||||
def process_books_stopped_import_test(self):
|
||||
def test_process_books_stopped_import(self):
|
||||
"""
|
||||
Test process books when the import is stopped
|
||||
"""
|
||||
@ -197,7 +197,7 @@ class TestCSVImport(TestCase):
|
||||
self.assertFalse(importer.wizard.increment_progress_bar.called)
|
||||
self.assertEqual(result, {})
|
||||
|
||||
def process_books_test(self):
|
||||
def test_process_books(self):
|
||||
"""
|
||||
Test process books when it completes successfully
|
||||
"""
|
||||
@ -222,7 +222,7 @@ class TestCSVImport(TestCase):
|
||||
[call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)])
|
||||
self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'})
|
||||
|
||||
def process_verses_stopped_import_test(self):
|
||||
def test_process_verses_stopped_import(self):
|
||||
"""
|
||||
Test process_verses when the import is stopped
|
||||
"""
|
||||
@ -242,7 +242,7 @@ class TestCSVImport(TestCase):
|
||||
self.assertFalse(importer.get_book_name.called)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def process_verses_successful_test(self):
|
||||
def test_process_verses_successful(self):
|
||||
"""
|
||||
Test process_verses when the import is successful
|
||||
"""
|
||||
@ -274,7 +274,7 @@ class TestCSVImport(TestCase):
|
||||
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 do_import_invalid_language_id_test(self):
|
||||
def test_do_import_invalid_language_id(self):
|
||||
"""
|
||||
Test do_import when the user cancels the language selection dialog box
|
||||
"""
|
||||
@ -291,7 +291,7 @@ class TestCSVImport(TestCase):
|
||||
importer.get_language.assert_called_once_with('Bible Name')
|
||||
self.assertFalse(result)
|
||||
|
||||
def do_import_success_test(self):
|
||||
def test_do_import_success(self):
|
||||
"""
|
||||
Test do_import when the import succeeds
|
||||
"""
|
||||
@ -317,7 +317,7 @@ class TestCSVImport(TestCase):
|
||||
importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1'])
|
||||
self.assertTrue(result)
|
||||
|
||||
def file_import_test(self):
|
||||
def test_file_import(self):
|
||||
"""
|
||||
Test the actual import of CSV Bible file
|
||||
"""
|
||||
|
@ -69,7 +69,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: The importer should be an instance of BibleDB
|
||||
self.assertIsInstance(importer, BibleImport)
|
||||
|
||||
def get_text_no_text_test(self):
|
||||
def test_get_text_no_text(self):
|
||||
"""
|
||||
Test that get_text handles elements containing text in a combination of text and tail attributes
|
||||
"""
|
||||
@ -82,7 +82,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: A blank string should be returned
|
||||
self.assertEqual(result, '')
|
||||
|
||||
def get_text_text_test(self):
|
||||
def test_get_text_text(self):
|
||||
"""
|
||||
Test that get_text handles elements containing text in a combination of text and tail attributes
|
||||
"""
|
||||
@ -99,7 +99,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: The text returned should be as expected
|
||||
self.assertEqual(result, 'Element text sub_text_tail text sub_text_tail tail sub_text text sub_tail tail')
|
||||
|
||||
def parse_chapter_number_test(self):
|
||||
def test_parse_chapter_number(self):
|
||||
"""
|
||||
Test parse_chapter_number when supplied with chapter number and an instance of OpenSongBible
|
||||
"""
|
||||
@ -110,7 +110,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: The 10 should be returned as an Int
|
||||
self.assertEqual(result, 10)
|
||||
|
||||
def parse_chapter_number_empty_attribute_test(self):
|
||||
def test_parse_chapter_number_empty_attribute(self):
|
||||
"""
|
||||
Testparse_chapter_number when the chapter number is an empty string. (Bug #1074727)
|
||||
"""
|
||||
@ -121,7 +121,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: parse_chapter_number should increment the previous verse number
|
||||
self.assertEqual(result, 13)
|
||||
|
||||
def parse_verse_number_valid_verse_no_test(self):
|
||||
def test_parse_verse_number_valid_verse_no(self):
|
||||
"""
|
||||
Test parse_verse_number when supplied with a valid verse number
|
||||
"""
|
||||
@ -134,7 +134,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: parse_verse_number should return the verse number
|
||||
self.assertEqual(result, 15)
|
||||
|
||||
def parse_verse_number_verse_range_test(self):
|
||||
def test_parse_verse_number_verse_range(self):
|
||||
"""
|
||||
Test parse_verse_number when supplied with a verse range
|
||||
"""
|
||||
@ -147,7 +147,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: parse_verse_number should return the first verse number in the range
|
||||
self.assertEqual(result, 24)
|
||||
|
||||
def parse_verse_number_invalid_verse_no_test(self):
|
||||
def test_parse_verse_number_invalid_verse_no(self):
|
||||
"""
|
||||
Test parse_verse_number when supplied with a invalid verse number
|
||||
"""
|
||||
@ -160,7 +160,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: parse_verse_number should increment the previous verse number
|
||||
self.assertEqual(result, 42)
|
||||
|
||||
def parse_verse_number_empty_attribute_test(self):
|
||||
def test_parse_verse_number_empty_attribute(self):
|
||||
"""
|
||||
Test parse_verse_number when the verse number is an empty string. (Bug #1074727)
|
||||
"""
|
||||
@ -172,7 +172,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: parse_verse_number should increment the previous verse number
|
||||
self.assertEqual(result, 15)
|
||||
|
||||
def parse_verse_number_invalid_type_test(self):
|
||||
def test_parse_verse_number_invalid_type(self):
|
||||
"""
|
||||
Test parse_verse_number when the verse number is an invalid type)
|
||||
"""
|
||||
@ -188,7 +188,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
mocked_log_warning.assert_called_once_with('Illegal verse number: (1, 2, 3)')
|
||||
self.assertEqual(result, 13)
|
||||
|
||||
def process_books_stop_import_test(self):
|
||||
def test_process_books_stop_import(self):
|
||||
"""
|
||||
Test process_books when stop_import is set to True
|
||||
"""
|
||||
@ -202,7 +202,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: find_and_create_book should not have been called
|
||||
self.assertFalse(self.mocked_find_and_create_book.called)
|
||||
|
||||
def process_books_completes_test(self):
|
||||
def test_process_books_completes(self):
|
||||
"""
|
||||
Test process_books when it processes all books
|
||||
"""
|
||||
@ -231,7 +231,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
[call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')])
|
||||
self.assertEqual(importer.session.commit.call_count, 2)
|
||||
|
||||
def process_chapters_stop_import_test(self):
|
||||
def test_process_chapters_stop_import(self):
|
||||
"""
|
||||
Test process_chapters when stop_import is set to True
|
||||
"""
|
||||
@ -247,7 +247,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
self.assertFalse(importer.parse_chapter_number.called)
|
||||
|
||||
@patch('openlp.plugins.bibles.lib.importers.opensong.parse_chapter_number', **{'side_effect': [1, 2]})
|
||||
def process_chapters_completes_test(self, mocked_parse_chapter_number):
|
||||
def test_process_chapters_completes(self, mocked_parse_chapter_number):
|
||||
"""
|
||||
Test process_chapters when it completes
|
||||
"""
|
||||
@ -279,7 +279,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
self.assertEqual(importer.wizard.increment_progress_bar.call_args_list,
|
||||
[call('Importing Book 1...'), call('Importing Book 2...')])
|
||||
|
||||
def process_verses_stop_import_test(self):
|
||||
def test_process_verses_stop_import(self):
|
||||
"""
|
||||
Test process_verses when stop_import is set to True
|
||||
"""
|
||||
@ -294,7 +294,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
# THEN: importer.parse_verse_number not have been called
|
||||
self.assertFalse(importer.parse_verse_number.called)
|
||||
|
||||
def process_verses_completes_test(self):
|
||||
def test_process_verses_completes(self):
|
||||
"""
|
||||
Test process_verses when it completes
|
||||
"""
|
||||
@ -329,7 +329,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
importer.create_verse.call_args_list,
|
||||
[call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')])
|
||||
|
||||
def do_import_parse_xml_fails_test(self):
|
||||
def test_do_import_parse_xml_fails(self):
|
||||
"""
|
||||
Test do_import when parse_xml fails (returns None)
|
||||
"""
|
||||
@ -347,7 +347,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
self.assertFalse(result)
|
||||
self.assertFalse(mocked_language_id.called)
|
||||
|
||||
def do_import_no_language_test(self):
|
||||
def test_do_import_no_language(self):
|
||||
"""
|
||||
Test do_import when the user cancels the language selection dialog
|
||||
"""
|
||||
@ -366,7 +366,7 @@ class TestOpenSongImport(TestCase, TestMixin):
|
||||
self.assertFalse(result)
|
||||
self.assertFalse(mocked_process_books.called)
|
||||
|
||||
def do_import_completes_test(self):
|
||||
def test_do_import_completes(self):
|
||||
"""
|
||||
Test do_import when it completes successfully
|
||||
"""
|
||||
|
@ -68,7 +68,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: The importer should be an instance of BibleDB
|
||||
self.assertIsInstance(importer, BibleDB)
|
||||
|
||||
def process_books_stop_import_test(self):
|
||||
def test_process_books_stop_import(self):
|
||||
"""
|
||||
Test process_books when stop_import is set to True
|
||||
"""
|
||||
@ -83,7 +83,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: find_and_create_book should not have been called
|
||||
self.assertFalse(self.mocked_find_and_create_book.called)
|
||||
|
||||
def process_books_completes_test(self):
|
||||
def test_process_books_completes(self):
|
||||
"""
|
||||
Test process_books when it processes all books
|
||||
"""
|
||||
@ -111,7 +111,7 @@ class TestOsisImport(TestCase):
|
||||
[call('db_book1', book1), call('db_book2', book2)])
|
||||
self.assertEqual(importer.session.commit.call_count, 2)
|
||||
|
||||
def process_chapters_verse_in_chapter_verse_text_test(self):
|
||||
def test_process_chapters_verse_in_chapter_verse_text(self):
|
||||
"""
|
||||
Test process_chapters when supplied with an etree element with a verse element nested in it
|
||||
"""
|
||||
@ -137,7 +137,7 @@ class TestOsisImport(TestCase):
|
||||
mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
|
||||
mocked_process_verse.assert_called_once_with(test_book, 2, test_verse)
|
||||
|
||||
def process_chapters_verse_in_chapter_verse_milestone_test(self):
|
||||
def test_process_chapters_verse_in_chapter_verse_milestone(self):
|
||||
"""
|
||||
Test process_chapters when supplied with an etree element with a verse element nested, when the verse system is
|
||||
based on milestones
|
||||
@ -164,7 +164,7 @@ class TestOsisImport(TestCase):
|
||||
mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
|
||||
mocked_process_verse.assert_called_once_with(test_book, 2, test_verse, use_milestones=True)
|
||||
|
||||
def process_chapters_milestones_chapter_no_sid_test(self):
|
||||
def test_process_chapters_milestones_chapter_no_sid(self):
|
||||
"""
|
||||
Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
|
||||
configuration, where the chapter is the "closing" milestone. (Missing the sID attribute)
|
||||
@ -187,7 +187,7 @@ class TestOsisImport(TestCase):
|
||||
self.assertFalse(mocked_set_current_chapter.called)
|
||||
self.assertFalse(mocked_process_verse.called)
|
||||
|
||||
def process_chapters_milestones_chapter_sid_test(self):
|
||||
def test_process_chapters_milestones_chapter_sid(self):
|
||||
"""
|
||||
Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
|
||||
configuration, where the chapter is the "opening" milestone. (Has the sID attribute)
|
||||
@ -210,7 +210,7 @@ class TestOsisImport(TestCase):
|
||||
mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
|
||||
self.assertFalse(mocked_process_verse.called)
|
||||
|
||||
def process_chapters_milestones_verse_tag_test(self):
|
||||
def test_process_chapters_milestones_verse_tag(self):
|
||||
"""
|
||||
Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
|
||||
configuration, where the verse is the "opening" milestone. (Has the sID attribute)
|
||||
@ -235,7 +235,7 @@ class TestOsisImport(TestCase):
|
||||
self.assertFalse(mocked_set_current_chapter.called)
|
||||
mocked_process_verse.assert_called_once_with(test_book, 0, test_verse, use_milestones=True)
|
||||
|
||||
def process_verse_no_osis_id_test(self):
|
||||
def test_process_verse_no_osis_id(self):
|
||||
"""
|
||||
Test process_verse when the element supplied does not have and osisID attribute
|
||||
"""
|
||||
@ -253,7 +253,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should not have been called
|
||||
self.assertFalse(self.mocked_create_verse.called)
|
||||
|
||||
def process_verse_use_milestones_no_s_id_test(self):
|
||||
def test_process_verse_use_milestones_no_s_id(self):
|
||||
"""
|
||||
Test process_verse when called with use_milestones set to True, but the element supplied does not have and sID
|
||||
attribute
|
||||
@ -272,7 +272,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should not have been called
|
||||
self.assertFalse(self.mocked_create_verse.called)
|
||||
|
||||
def process_verse_use_milestones_no_tail_test(self):
|
||||
def test_process_verse_use_milestones_no_tail(self):
|
||||
"""
|
||||
Test process_verse when called with use_milestones set to True, but the element supplied does not have a 'tail'
|
||||
"""
|
||||
@ -290,7 +290,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should not have been called
|
||||
self.assertFalse(self.mocked_create_verse.called)
|
||||
|
||||
def process_verse_use_milestones_success_test(self):
|
||||
def test_process_verse_use_milestones_success(self):
|
||||
"""
|
||||
Test process_verse when called with use_milestones set to True, and the verse element successfully imports
|
||||
"""
|
||||
@ -309,7 +309,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should have been called with the test data
|
||||
self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text')
|
||||
|
||||
def process_verse_no_text_test(self):
|
||||
def test_process_verse_no_text(self):
|
||||
"""
|
||||
Test process_verse when called with an empty verse element
|
||||
"""
|
||||
@ -328,7 +328,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should not have been called
|
||||
self.assertFalse(self.mocked_create_verse.called)
|
||||
|
||||
def process_verse_success_test(self):
|
||||
def test_process_verse_success(self):
|
||||
"""
|
||||
Test process_verse when called with an element with text set
|
||||
"""
|
||||
@ -347,7 +347,7 @@ class TestOsisImport(TestCase):
|
||||
# THEN: create_verse should have been called with the test data
|
||||
self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text')
|
||||
|
||||
def do_import_parse_xml_fails_test(self):
|
||||
def test_do_import_parse_xml_fails(self):
|
||||
"""
|
||||
Test do_import when parse_xml fails (returns None)
|
||||
"""
|
||||
@ -365,7 +365,7 @@ class TestOsisImport(TestCase):
|
||||
self.assertFalse(result)
|
||||
self.assertFalse(mocked_language_id.called)
|
||||
|
||||
def do_import_no_language_test(self):
|
||||
def test_do_import_no_language(self):
|
||||
"""
|
||||
Test do_import when the user cancels the language selection dialog
|
||||
"""
|
||||
@ -384,7 +384,7 @@ class TestOsisImport(TestCase):
|
||||
self.assertFalse(result)
|
||||
self.assertFalse(mocked_process_books.called)
|
||||
|
||||
def do_import_completes_test(self):
|
||||
def test_do_import_completes(self):
|
||||
"""
|
||||
Test do_import when it completes successfully
|
||||
"""
|
||||
|
@ -239,160 +239,160 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
self.assertIsNone(return_value, 'db_set_record_struct should return None')
|
||||
mocked_struct.Struct.assert_called_with('>50sHIB250s250s10sQ')
|
||||
|
||||
def test_get_field(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
def test_get_field(self, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`db_get_field` module
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager", an encoding and some test data and known results
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.encoding = TEST_DATA_ENCODING
|
||||
importer.fields = TEST_FIELDS
|
||||
importer.field_descriptions = TEST_FIELD_DESCS
|
||||
field_results = [(0, b'A Heart Like Thine'), (1, 100), (2, 102), (3, True), (6, None), (7, None)]
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.encoding = TEST_DATA_ENCODING
|
||||
importer.fields = TEST_FIELDS
|
||||
importer.field_descriptions = TEST_FIELD_DESCS
|
||||
field_results = [(0, b'A Heart Like Thine'), (1, 100), (2, 102), (3, True), (6, None), (7, None)]
|
||||
|
||||
# WHEN: Called with test data
|
||||
for field_index, result in field_results:
|
||||
return_value = importer.db_get_field(field_index)
|
||||
# WHEN: Called with test data
|
||||
for field_index, result in field_results:
|
||||
return_value = importer.db_get_field(field_index)
|
||||
|
||||
# THEN: db_get_field should return the known results
|
||||
self.assertEqual(return_value, result,
|
||||
'db_get_field should return "%s" when called with "%s"' %
|
||||
(result, TEST_FIELDS[field_index]))
|
||||
# THEN: db_get_field should return the known results
|
||||
self.assertEqual(return_value, result,
|
||||
'db_get_field should return "%s" when called with "%s"' %
|
||||
(result, TEST_FIELDS[field_index]))
|
||||
|
||||
def test_get_memo_field(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
def test_get_memo_field(self, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`db_get_field` module
|
||||
"""
|
||||
for test_results in GET_MEMO_FIELD_TEST_RESULTS:
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager", a mocked out memo_file and an encoding
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
|
||||
mocked_manager = MagicMock()
|
||||
mocked_memo_file = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.memo_file = mocked_memo_file
|
||||
importer.encoding = TEST_DATA_ENCODING
|
||||
mocked_manager = MagicMock()
|
||||
mocked_memo_file = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.memo_file = mocked_memo_file
|
||||
importer.encoding = TEST_DATA_ENCODING
|
||||
|
||||
# WHEN: Supplied with test fields and test field descriptions
|
||||
importer.fields = TEST_FIELDS
|
||||
importer.field_descriptions = TEST_FIELD_DESCS
|
||||
field_index = test_results[0]
|
||||
mocked_memo_file.read.return_value = test_results[1]
|
||||
get_field_result = test_results[2]['return']
|
||||
get_field_read_calls = test_results[2]['read']
|
||||
get_field_seek_calls = test_results[2]['seek']
|
||||
# WHEN: Supplied with test fields and test field descriptions
|
||||
importer.fields = TEST_FIELDS
|
||||
importer.field_descriptions = TEST_FIELD_DESCS
|
||||
field_index = test_results[0]
|
||||
mocked_memo_file.read.return_value = test_results[1]
|
||||
get_field_result = test_results[2]['return']
|
||||
get_field_read_calls = test_results[2]['read']
|
||||
get_field_seek_calls = test_results[2]['seek']
|
||||
|
||||
# THEN: db_get_field should return the appropriate value with the appropriate mocked objects being
|
||||
# called
|
||||
self.assertEqual(importer.db_get_field(field_index), get_field_result)
|
||||
for call in get_field_read_calls:
|
||||
mocked_memo_file.read.assert_any_call(call)
|
||||
for call in get_field_seek_calls:
|
||||
if isinstance(call, int):
|
||||
mocked_memo_file.seek.assert_any_call(call)
|
||||
else:
|
||||
mocked_memo_file.seek.assert_any_call(call[0], call[1])
|
||||
# THEN: db_get_field should return the appropriate value with the appropriate mocked objects being
|
||||
# called
|
||||
self.assertEqual(importer.db_get_field(field_index), get_field_result)
|
||||
for call in get_field_read_calls:
|
||||
mocked_memo_file.read.assert_any_call(call)
|
||||
for call in get_field_seek_calls:
|
||||
if isinstance(call, int):
|
||||
mocked_memo_file.seek.assert_any_call(call)
|
||||
else:
|
||||
mocked_memo_file.seek.assert_any_call(call[0], call[1])
|
||||
|
||||
def test_do_import_source_invalid(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', side_effect=[True, False])
|
||||
def test_do_import_source_invalid(self, mocked_is_file, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`do_import` module produces an error when Songs.MB not found.
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', side_effect=[True, False]):
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
with patch.object(importer, 'log_error') as mocked_log_error:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
with patch.object(importer, 'log_error') as mocked_log_error:
|
||||
|
||||
# WHEN: do_import is supplied with an import source (Songs.MB missing)
|
||||
importer.import_source = 'Songs.DB'
|
||||
importer.do_import()
|
||||
# WHEN: do_import is supplied with an import source (Songs.MB missing)
|
||||
importer.import_source = 'Songs.DB'
|
||||
importer.do_import()
|
||||
|
||||
# THEN: do_import should have logged an error that the Songs.MB file could not be found.
|
||||
mocked_log_error.assert_any_call(importer.import_source,
|
||||
'Could not find the "Songs.MB" file. It must be in the same folder as '
|
||||
'the "Songs.DB" file.')
|
||||
# THEN: do_import should have logged an error that the Songs.MB file could not be found.
|
||||
mocked_log_error.assert_any_call(importer.import_source,
|
||||
'Could not find the "Songs.MB" file. It must be in the same folder as '
|
||||
'the "Songs.DB" file.')
|
||||
|
||||
def test_do_import_database_validity(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True)
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat')
|
||||
def test_do_import_database_validity(self, mocked_stat, mocked_is_file, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`do_import` module handles invalid database files correctly
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, os.path and a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat') as mocked_stat:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
# WHEN: DB file size is less than 0x800
|
||||
mocked_stat.return_value.st_size = 0x7FF
|
||||
|
||||
# WHEN: DB file size is less than 0x800
|
||||
mocked_stat.return_value.st_size = 0x7FF
|
||||
# THEN: do_import should return None having called Path.stat()
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
mocked_stat.assert_called_once_with()
|
||||
|
||||
# THEN: do_import should return None having called Path.stat()
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
mocked_stat.assert_called_once_with()
|
||||
|
||||
def test_do_import_memo_validty(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True)
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800})
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.open')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.struct')
|
||||
def test_do_import_memo_validty(self, mocked_struct, mocked_open, mocked_stat, mocked_is_file, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`do_import` module handles invalid memo files correctly
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800}), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.open') as mocked_open, \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
|
||||
# WHEN: Unpacking first 35 bytes of Memo file
|
||||
struct_unpack_return_values = [(0, 0x700, 2, 0, 0), (0, 0x800, 0, 0, 0), (0, 0x800, 5, 0, 0)]
|
||||
mocked_struct.unpack.side_effect = struct_unpack_return_values
|
||||
# WHEN: Unpacking first 35 bytes of Memo file
|
||||
struct_unpack_return_values = [(0, 0x700, 2, 0, 0), (0, 0x800, 0, 0, 0), (0, 0x800, 5, 0, 0)]
|
||||
mocked_struct.unpack.side_effect = struct_unpack_return_values
|
||||
|
||||
# THEN: do_import should return None having called closed the open files db and memo files.
|
||||
for effect in struct_unpack_return_values:
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
self.assertEqual(mocked_open().close.call_count, 2,
|
||||
'The open db and memo files should have been closed')
|
||||
mocked_open().close.reset_mock()
|
||||
self.assertIs(mocked_open().seek.called, False, 'db_file.seek should not have been called.')
|
||||
# THEN: do_import should return None having called closed the open files db and memo files.
|
||||
for effect in struct_unpack_return_values:
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
self.assertEqual(mocked_open().close.call_count, 2,
|
||||
'The open db and memo files should have been closed')
|
||||
mocked_open().close.reset_mock()
|
||||
self.assertIs(mocked_open().seek.called, False, 'db_file.seek should not have been called.')
|
||||
|
||||
def test_code_page_to_encoding(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True)
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800})
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.Path.open')
|
||||
@patch('builtins.open')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.struct')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding')
|
||||
def test_code_page_to_encoding(self, mocked_retrieve_windows_encoding, mocked_struct, mocked_open, mocked_path_open,
|
||||
mocked_path_stat, mocked_path_is_file, MockSongImport):
|
||||
"""
|
||||
Test the :mod:`do_import` converts the code page to the encoding correctly
|
||||
"""
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager"
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800}), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.Path.open'), \
|
||||
patch('builtins.open'), patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct, \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding') as \
|
||||
mocked_retrieve_windows_encoding:
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
mocked_manager = MagicMock()
|
||||
importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
|
||||
importer.import_source = 'Songs.DB'
|
||||
|
||||
# WHEN: Unpacking the code page
|
||||
for code_page, encoding in CODE_PAGE_MAPPINGS:
|
||||
struct_unpack_return_values = [(0, 0x800, 2, 0, 0), (code_page, )]
|
||||
mocked_struct.unpack.side_effect = struct_unpack_return_values
|
||||
mocked_retrieve_windows_encoding.return_value = False
|
||||
# WHEN: Unpacking the code page
|
||||
for code_page, encoding in CODE_PAGE_MAPPINGS:
|
||||
struct_unpack_return_values = [(0, 0x800, 2, 0, 0), (code_page, )]
|
||||
mocked_struct.unpack.side_effect = struct_unpack_return_values
|
||||
mocked_retrieve_windows_encoding.return_value = False
|
||||
|
||||
# THEN: do_import should return None having called retrieve_windows_encoding with the correct encoding.
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
mocked_retrieve_windows_encoding.assert_any_call(encoding)
|
||||
# THEN: do_import should return None having called retrieve_windows_encoding with the correct encoding.
|
||||
self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
|
||||
mocked_retrieve_windows_encoding.assert_any_call(encoding)
|
||||
|
||||
def test_db_file_import(self):
|
||||
return self._test_db_file_import(os.path.join(TEST_PATH, 'Songs.DB'))
|
||||
return self._run_db_file_import(os.path.join(TEST_PATH, 'Songs.DB'))
|
||||
|
||||
def test_sqlite_db_file_import(self):
|
||||
return self._test_db_file_import(os.path.join(TEST_PATH, 'ew6'))
|
||||
return self._run_db_file_import(os.path.join(TEST_PATH, 'ew6'))
|
||||
|
||||
def _test_db_file_import(self, source_path):
|
||||
def _run_db_file_import(self, source_path):
|
||||
"""
|
||||
Test the actual import of real song database files and check that the imported data is correct.
|
||||
"""
|
||||
@ -448,62 +448,61 @@ class TestEasyWorshipSongImport(TestCase):
|
||||
'verse_order_list for %s should be %s' % (title, verse_order_list))
|
||||
mocked_finish.assert_called_with()
|
||||
|
||||
def test_ews_file_import(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding')
|
||||
def test_ews_file_import(self, mocked_retrieve_windows_encoding, MockSongImport):
|
||||
"""
|
||||
Test the actual import of song from ews file and check that the imported data is correct.
|
||||
"""
|
||||
|
||||
# GIVEN: Test files with a mocked out SongImport class, a mocked out "manager", a mocked out "import_wizard",
|
||||
# and mocked out "author", "add_copyright", "add_verse", "finish" methods.
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
|
||||
patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding') \
|
||||
as mocked_retrieve_windows_encoding:
|
||||
mocked_retrieve_windows_encoding.return_value = 'cp1252'
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
mocked_add_author = MagicMock()
|
||||
mocked_add_verse = MagicMock()
|
||||
mocked_finish = MagicMock()
|
||||
mocked_title = MagicMock()
|
||||
mocked_finish.return_value = True
|
||||
importer = EasyWorshipSongImportLogger(mocked_manager)
|
||||
importer.import_wizard = mocked_import_wizard
|
||||
importer.stop_import_flag = False
|
||||
importer.add_author = mocked_add_author
|
||||
importer.add_verse = mocked_add_verse
|
||||
importer.title = mocked_title
|
||||
importer.finish = mocked_finish
|
||||
importer.topics = []
|
||||
mocked_retrieve_windows_encoding.return_value = 'cp1252'
|
||||
mocked_manager = MagicMock()
|
||||
mocked_import_wizard = MagicMock()
|
||||
mocked_add_author = MagicMock()
|
||||
mocked_add_verse = MagicMock()
|
||||
mocked_finish = MagicMock()
|
||||
mocked_title = MagicMock()
|
||||
mocked_finish.return_value = True
|
||||
importer = EasyWorshipSongImportLogger(mocked_manager)
|
||||
importer.import_wizard = mocked_import_wizard
|
||||
importer.stop_import_flag = False
|
||||
importer.add_author = mocked_add_author
|
||||
importer.add_verse = mocked_add_verse
|
||||
importer.title = mocked_title
|
||||
importer.finish = mocked_finish
|
||||
importer.topics = []
|
||||
|
||||
# WHEN: Importing ews file
|
||||
importer.import_source = os.path.join(TEST_PATH, 'test1.ews')
|
||||
import_result = importer.do_import()
|
||||
# WHEN: Importing ews file
|
||||
importer.import_source = os.path.join(TEST_PATH, 'test1.ews')
|
||||
import_result = importer.do_import()
|
||||
|
||||
# THEN: do_import should return none, the song data should be as expected, and finish should have been
|
||||
# called.
|
||||
title = EWS_SONG_TEST_DATA['title']
|
||||
self.assertIsNone(import_result, 'do_import should return None when it has completed')
|
||||
self.assertIn(title, importer._title_assignment_list, 'title for should be "%s"' % title)
|
||||
mocked_add_author.assert_any_call(EWS_SONG_TEST_DATA['authors'][0])
|
||||
for verse_text, verse_tag in EWS_SONG_TEST_DATA['verses']:
|
||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||
mocked_finish.assert_called_with()
|
||||
# THEN: do_import should return none, the song data should be as expected, and finish should have been
|
||||
# called.
|
||||
title = EWS_SONG_TEST_DATA['title']
|
||||
self.assertIsNone(import_result, 'do_import should return None when it has completed')
|
||||
self.assertIn(title, importer._title_assignment_list, 'title for should be "%s"' % title)
|
||||
mocked_add_author.assert_any_call(EWS_SONG_TEST_DATA['authors'][0])
|
||||
for verse_text, verse_tag in EWS_SONG_TEST_DATA['verses']:
|
||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||
mocked_finish.assert_called_with()
|
||||
|
||||
def test_import_rtf_unescaped_unicode(self):
|
||||
@patch('openlp.plugins.songs.lib.importers.easyworship.SongImport')
|
||||
def test_import_rtf_unescaped_unicode(self, MockSongImport):
|
||||
"""
|
||||
Test import of rtf without the expected escaping of unicode
|
||||
"""
|
||||
|
||||
# GIVEN: A mocked out SongImport class, a mocked out "manager" and mocked out "author" method.
|
||||
with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
|
||||
mocked_manager = MagicMock()
|
||||
mocked_add_author = MagicMock()
|
||||
importer = EasyWorshipSongImportLogger(mocked_manager)
|
||||
importer.add_author = mocked_add_author
|
||||
importer.encoding = 'cp1252'
|
||||
mocked_manager = MagicMock()
|
||||
mocked_add_author = MagicMock()
|
||||
importer = EasyWorshipSongImportLogger(mocked_manager)
|
||||
importer.add_author = mocked_add_author
|
||||
importer.encoding = 'cp1252'
|
||||
|
||||
# WHEN: running set_song_import_object on a verse string without the needed escaping
|
||||
importer.set_song_import_object('Test Author', b'Det som var fr\x86n begynnelsen')
|
||||
# WHEN: running set_song_import_object on a verse string without the needed escaping
|
||||
importer.set_song_import_object('Test Author', b'Det som var fr\x86n begynnelsen')
|
||||
|
||||
# THEN: The import should fail
|
||||
self.assertEquals(importer.entry_error_log, 'Unexpected data formatting.', 'Import should fail')
|
||||
# THEN: The import should fail
|
||||
self.assertEquals(importer.entry_error_log, 'Unexpected data formatting.', 'Import should fail')
|
||||
|
@ -135,7 +135,7 @@ class TestSongSelectImport(TestCase, TestMixin):
|
||||
|
||||
@patch('openlp.plugins.songs.lib.songselect.build_opener')
|
||||
@patch('openlp.plugins.songs.lib.songselect.BeautifulSoup')
|
||||
def login_url_from_form_test(self, MockedBeautifulSoup, mocked_build_opener):
|
||||
def test_login_url_from_form(self, MockedBeautifulSoup, mocked_build_opener):
|
||||
"""
|
||||
Test that the login URL is from the form
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user