2016-08-07 10:15:43 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2019-04-13 13:00:22 +00:00
|
|
|
##########################################################################
|
|
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
|
|
# ---------------------------------------------------------------------- #
|
2020-01-01 02:53:08 +00:00
|
|
|
# Copyright (c) 2008-2020 OpenLP Developers #
|
2019-04-13 13:00:22 +00:00
|
|
|
# ---------------------------------------------------------------------- #
|
|
|
|
# This program is free software: you can redistribute it and/or modify #
|
|
|
|
# it under the terms of the GNU General Public License as published by #
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or #
|
|
|
|
# (at your option) any later version. #
|
|
|
|
# #
|
|
|
|
# This program is distributed in the hope that it will be useful, #
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
|
|
# GNU General Public License for more details. #
|
|
|
|
# #
|
|
|
|
# You should have received a copy of the GNU General Public License #
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
|
|
##########################################################################
|
2016-08-07 10:15:43 +00:00
|
|
|
"""
|
|
|
|
This module contains tests for the bibleimport module.
|
|
|
|
"""
|
2020-03-04 06:06:47 +00:00
|
|
|
import pytest
|
2016-08-07 10:15:43 +00:00
|
|
|
from io import BytesIO
|
2019-05-22 06:47:00 +00:00
|
|
|
from pathlib import Path
|
2017-04-24 05:17:55 +00:00
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
|
2017-12-28 08:22:55 +00:00
|
|
|
from lxml import etree, objectify
|
2018-10-02 04:39:42 +00:00
|
|
|
from PyQt5.QtWidgets import QDialog
|
2016-08-07 10:15:43 +00:00
|
|
|
|
2017-10-07 07:05:07 +00:00
|
|
|
from openlp.core.common.i18n import Language
|
2020-03-04 06:06:47 +00:00
|
|
|
from openlp.core.common.registry import Registry
|
2016-08-14 10:00:27 +00:00
|
|
|
from openlp.core.lib.exceptions import ValidationError
|
2016-08-07 10:15:43 +00:00
|
|
|
from openlp.plugins.bibles.lib.bibleimport import BibleImport
|
2016-08-14 10:00:27 +00:00
|
|
|
from openlp.plugins.bibles.lib.db import BibleDB
|
2016-08-07 10:15:43 +00:00
|
|
|
|
|
|
|
|
2020-03-04 06:06:47 +00:00
|
|
|
@pytest.fixture()
|
|
|
|
def test_file():
|
|
|
|
return BytesIO(
|
|
|
|
b'<?xml version="1.0" encoding="UTF-8" ?>\n'
|
|
|
|
b'<root>\n'
|
|
|
|
b' <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'
|
|
|
|
b'</root>'
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def error_message_box(settings):
|
|
|
|
Registry().register('main_window', MagicMock())
|
|
|
|
m_box = patch('openlp.plugins.bibles.lib.bibleimport.critical_error_message_box')
|
|
|
|
yield m_box.start()
|
|
|
|
m_box.stop()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.yield_fixture()
|
|
|
|
def mocked_open():
|
|
|
|
m_open = patch.object(Path, 'open')
|
|
|
|
yield m_open.start()
|
|
|
|
m_open.stop()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.yield_fixture()
|
|
|
|
def mocked_setup():
|
|
|
|
s_up = patch('openlp.plugins.bibles.lib.db.BibleDB._setup')
|
|
|
|
yield s_up.start()
|
|
|
|
s_up.stop()
|
|
|
|
|
|
|
|
|
|
|
|
def test_init_kwargs_none(mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
Test the initialisation of the BibleImport Class when no key word arguments are supplied
|
|
|
|
"""
|
|
|
|
# GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent
|
|
|
|
# WHEN: Creating an instance of BibleImport with no key word arguments
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# THEN: The file_path attribute should be None
|
|
|
|
assert instance.file_path is None
|
|
|
|
assert isinstance(instance, BibleDB)
|
|
|
|
|
|
|
|
|
|
|
|
def test_init_kwargs_set(mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
Test the initialisation of the BibleImport Class when supplied with select keyword arguments
|
|
|
|
"""
|
|
|
|
# GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent
|
|
|
|
# WHEN: Creating an instance of BibleImport with selected key word arguments
|
|
|
|
kwargs = {'file_path': 'bible.xml'}
|
|
|
|
instance = BibleImport(MagicMock(), **kwargs)
|
|
|
|
|
|
|
|
# THEN: The file_path keyword should be set to bible.xml
|
|
|
|
assert instance.file_path == 'bible.xml'
|
|
|
|
assert isinstance(instance, BibleDB)
|
|
|
|
|
|
|
|
|
|
|
|
@patch('openlp.plugins.bibles.forms.LanguageForm')
|
|
|
|
def test_get_language_canceled(MockedLanguageForm, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
# 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
|
|
|
|
|
|
|
|
# WHEN: Calling get_language()
|
|
|
|
result = instance.get_language('ESV')
|
|
|
|
|
|
|
|
# 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'
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleDB, 'save_meta')
|
|
|
|
@patch('openlp.plugins.bibles.forms.LanguageForm')
|
|
|
|
def test_get_language_accepted(MockedLanguageForm, mocked_save_meta, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
# 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
|
|
|
|
|
|
|
|
# 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'
|
|
|
|
|
|
|
|
|
|
|
|
@patch('openlp.plugins.bibles.lib.bibleimport.get_language')
|
|
|
|
@patch.object(BibleImport, 'get_language')
|
|
|
|
def test_get_language_id_language_found(mocked_db_get_language, mocked_get_language, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
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')
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_db_get_language, mocked_languages_get_language,
|
|
|
|
mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
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')
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_log_error, mocked_db_get_language, mocked_languages_get_language,
|
|
|
|
mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
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')
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_log_error, mocked_db_get_language,
|
|
|
|
mocked_languages_get_language, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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.
|
|
|
|
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')
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
|
|
|
@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(MockBibleResourcesDB, mocked_log_debug, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
assert result == 20
|
|
|
|
|
|
|
|
|
|
|
|
@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(MockBibleResourcesDB, mocked_log_debug,
|
|
|
|
mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
assert result == 30
|
|
|
|
|
|
|
|
|
|
|
|
@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(MockAlterativeBookNamesDB, MockBibleResourcesDB,
|
|
|
|
mocked_log_debug, mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
assert result == 40
|
|
|
|
|
|
|
|
|
|
|
|
@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(MockBookNameForm, MockAlterativeBookNamesDB,
|
|
|
|
MockBibleResourcesDB, mocked_get_books, mocked_log_debug,
|
|
|
|
mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# WHEN: Calling get_book_ref_id_by_name
|
|
|
|
result = instance.get_book_ref_id_by_name('Gen', 66, 4)
|
|
|
|
|
|
|
|
# THEN: None should be returned
|
|
|
|
assert result is None
|
|
|
|
|
|
|
|
|
|
|
|
@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(MockBookNameForm, MockAlterativeBookNamesDB,
|
|
|
|
MockBibleResourcesDB, mocked_get_books, mocked_log_debug,
|
|
|
|
mocked_setup, registry):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
MockAlterativeBookNamesDB.create_alternative_book_name.assert_called_once_with('Gen', 50, 4)
|
|
|
|
assert result == 50
|
|
|
|
|
|
|
|
|
|
|
|
@patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=True)
|
|
|
|
def test_is_compressed_compressed(mocked_is_zipfile, mocked_open, mocked_setup, error_message_box):
|
|
|
|
"""
|
|
|
|
Test is_compressed when the 'file' being tested is compressed
|
|
|
|
"""
|
|
|
|
# GIVEN: An instance of BibleImport and a mocked is_zipfile which returns True
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
@patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=False)
|
|
|
|
def test_is_compressed_not_compressed(mocked_is_zipfile, mocked_open, mocked_setup, error_message_box):
|
|
|
|
"""
|
|
|
|
Test is_compressed when the 'file' being tested is not compressed
|
|
|
|
"""
|
|
|
|
# GIVEN: An instance of BibleImport and a mocked is_zipfile which returns False
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
|
|
|
|
# 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
|
|
|
|
assert result is False
|
|
|
|
assert error_message_box.called is False
|
|
|
|
|
|
|
|
|
|
|
|
def test_parse_xml_etree(registry, mocked_open, mocked_setup, test_file):
|
|
|
|
"""
|
|
|
|
Test BibleImport.parse_xml() when called with the use_objectify default value
|
|
|
|
"""
|
|
|
|
# GIVEN: A sample "file" to parse and an instance of BibleImport
|
|
|
|
mocked_open.return_value = test_file
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
instance.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml
|
|
|
|
result = instance.parse_xml(Path('file.tst'))
|
|
|
|
|
|
|
|
# THEN: The result returned should contain the correct data, and should be an instance of eetree_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 test_parse_xml_etree_use_objectify(registry, mocked_open, mocked_setup, test_file):
|
|
|
|
"""
|
|
|
|
Test BibleImport.parse_xml() when called with use_objectify set to True
|
|
|
|
"""
|
|
|
|
# GIVEN: A sample "file" to parse and an instance of BibleImport
|
|
|
|
mocked_open.return_value = test_file
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
instance.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml
|
|
|
|
result = instance.parse_xml(Path('file.tst'), use_objectify=True)
|
|
|
|
|
|
|
|
# THEN: The result returned should contain the correct data, and should be an instance of 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 test_parse_xml_elements(registry, mocked_open, mocked_setup, test_file):
|
|
|
|
"""
|
|
|
|
Test BibleImport.parse_xml() when given a tuple of elements to remove
|
|
|
|
"""
|
|
|
|
# GIVEN: A tuple of elements to remove and an instance of BibleImport
|
|
|
|
mocked_open.return_value = test_file
|
|
|
|
elements = ('unsupported', 'x', 'y')
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
instance.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml, with a test file
|
|
|
|
result = instance.parse_xml(Path('file.tst'), elements=elements)
|
|
|
|
|
|
|
|
# THEN: The result returned should contain the correct data
|
|
|
|
assert etree.tostring(result) == \
|
|
|
|
b'<root>\n <data><div>Test<p>data</p><a>to</a>keep</div></data>\n <data/>\n</root>'
|
|
|
|
|
|
|
|
|
|
|
|
def test_parse_xml_tags(registry, mocked_open, mocked_setup, test_file):
|
|
|
|
"""
|
|
|
|
Test BibleImport.parse_xml() when given a tuple of tags to remove
|
|
|
|
"""
|
|
|
|
# GIVEN: A tuple of tags to remove and an instance of BibleImport
|
|
|
|
mocked_open.return_value = test_file
|
|
|
|
tags = ('div', 'p', 'a')
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
instance.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml, with a test file
|
|
|
|
result = instance.parse_xml(Path('file.tst'), tags=tags)
|
|
|
|
|
|
|
|
# THEN: The result returned should contain the correct data
|
|
|
|
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 test_parse_xml_elements_tags(registry, mocked_open, mocked_setup, test_file):
|
|
|
|
"""
|
|
|
|
Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove
|
|
|
|
"""
|
|
|
|
# GIVEN: A tuple of elements and of tags to remove and an instance of BibleImport
|
|
|
|
mocked_open.return_value = test_file
|
|
|
|
elements = ('unsupported', 'x', 'y')
|
|
|
|
tags = ('div', 'p', 'a')
|
|
|
|
instance = BibleImport(MagicMock())
|
|
|
|
instance.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml, with a test file
|
|
|
|
result = instance.parse_xml(Path('file.tst'), elements=elements, tags=tags)
|
|
|
|
|
|
|
|
# THEN: The result returned should contain the correct data
|
|
|
|
assert etree.tostring(result) == b'<root>\n <data>Testdatatokeep</data>\n <data/>\n</root>'
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleImport, 'log_exception')
|
|
|
|
def test_parse_xml_file_file_not_found_exception(mocked_log_exception, mocked_open, error_message_box):
|
|
|
|
"""
|
|
|
|
Test that parse_xml handles a FileNotFoundError exception correctly
|
|
|
|
"""
|
|
|
|
# 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'
|
|
|
|
mocked_open.side_effect = exception
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml
|
|
|
|
result = importer.parse_xml(Path('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.')
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleImport, 'log_exception')
|
|
|
|
def test_parse_xml_file_permission_error_exception(mocked_log_exception, mocked_open, error_message_box):
|
|
|
|
"""
|
|
|
|
Test that parse_xml handles a PermissionError exception correctly
|
|
|
|
"""
|
|
|
|
# GIVEN: A mocked open which raises a PermissionError and an instance of BibleImporter
|
|
|
|
exception = PermissionError()
|
|
|
|
exception.filename = 'file.tst'
|
|
|
|
exception.strerror = 'Permission denied'
|
|
|
|
mocked_open.side_effect = exception
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# WHEN: Calling parse_xml
|
|
|
|
result = importer.parse_xml(Path('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.')
|
|
|
|
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 test_set_current_chapter(settings):
|
|
|
|
"""
|
|
|
|
Test set_current_chapter
|
|
|
|
"""
|
|
|
|
# GIVEN: An instance of BibleImport and a mocked wizard
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
importer.wizard = MagicMock()
|
|
|
|
|
|
|
|
# WHEN: Calling set_current_chapter
|
|
|
|
importer.set_current_chapter('Book_Name', 'Chapter')
|
|
|
|
|
|
|
|
# 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...')
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleImport, 'is_compressed', return_value=True)
|
|
|
|
def test_validate_xml_file_compressed_file(mocked_is_compressed, settings):
|
|
|
|
"""
|
|
|
|
Test that validate_xml_file raises a ValidationError when is_compressed returns True
|
|
|
|
"""
|
|
|
|
# GIVEN: A mocked parse_xml which returns None
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# WHEN: Calling is_compressed
|
|
|
|
# THEN: ValidationError should be raised, with the message 'Compressed file'
|
|
|
|
with pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Compressed file')
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleImport, 'parse_xml', return_value=None)
|
|
|
|
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
|
|
|
def test_validate_xml_file_parse_xml_fails(mocked_is_compressed, mocked_parse_xml, settings):
|
|
|
|
"""
|
|
|
|
Test that validate_xml_file raises a ValidationError when parse_xml returns None
|
|
|
|
"""
|
|
|
|
# GIVEN: A mocked parse_xml which returns None
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# 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 pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Error when opening file')
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_is_compressed, mocked_parse_xml, settings):
|
|
|
|
"""
|
|
|
|
Test that validate_xml_file returns True with valid XML
|
|
|
|
"""
|
|
|
|
# GIVEN: Some test data with an OpenSong Bible "bible" root tag
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# WHEN: Calling validate_xml_file
|
|
|
|
result = importer.validate_xml_file('file.name', 'bible')
|
|
|
|
|
|
|
|
# THEN: True should be returned
|
|
|
|
assert result is True
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_is_compressed, mocked_parse_xml, error_message_box):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# 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 pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Invalid xml.')
|
|
|
|
error_message_box.assert_called_once_with(
|
|
|
|
message='Incorrect Bible file type supplied. This looks like an OpenSong XML bible.')
|
|
|
|
|
|
|
|
|
|
|
|
@patch.object(BibleImport, 'parse_xml')
|
|
|
|
@patch.object(BibleImport, 'is_compressed', return_value=False)
|
|
|
|
def test_validate_xml_file_osis_root(mocked_is_compressed, mocked_parse_xml, error_message_box):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
mocked_parse_xml.return_value = objectify.fromstring(
|
|
|
|
'<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# 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 pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Invalid xml.')
|
|
|
|
error_message_box.assert_called_once_with(
|
|
|
|
message='Incorrect Bible file type supplied. This looks like an OSIS XML bible.')
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_is_compressed, mocked_parse_xml, error_message_box):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
|
|
|
|
# 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 pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Invalid xml.')
|
|
|
|
error_message_box.assert_called_once_with(
|
|
|
|
message='Incorrect Bible file type supplied. This looks like an Zefania XML bible.')
|
|
|
|
|
|
|
|
|
|
|
|
@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(mocked_is_compressed, mocked_parse_xml, error_message_box):
|
|
|
|
"""
|
|
|
|
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
|
|
|
|
importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
|
|
|
|
# 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 pytest.raises(ValidationError) as context:
|
|
|
|
importer.validate_xml_file('file.name', 'xbible')
|
|
|
|
assert context.value != ValidationError('Invalid xml.')
|
|
|
|
error_message_box.assert_called_once_with(
|
|
|
|
message='Incorrect Bible file type supplied. This looks like an unknown type of XML bible.')
|