diff --git a/tests/functional/openlp_plugins/bibles/test_lib.py b/tests/functional/openlp_plugins/bibles/test_lib.py index 27d7f5e51..d678ceb7e 100644 --- a/tests/functional/openlp_plugins/bibles/test_lib.py +++ b/tests/functional/openlp_plugins/bibles/test_lib.py @@ -25,11 +25,12 @@ This module contains tests for the lib submodule of the Bibles plugin. from unittest import TestCase from openlp.plugins.bibles import lib -from openlp.plugins.bibles.lib import SearchResults -from tests.functional import patch +from openlp.plugins.bibles.lib import SearchResults, get_reference_match +from tests.functional import MagicMock, patch +from tests.helpers.testmixin import TestMixin -class TestLib(TestCase): +class TestLib(TestCase, TestMixin): """ Test the functions in the :mod:`lib` module. """ @@ -60,6 +61,142 @@ class TestLib(TestCase): self.assertEqual(separators[key], value) mocked_update_reference_separators.assert_called_once_with() + def test_reference_matched_full(self): + """ + Test that the 'full' regex parses bible verse references correctly. + """ + # GIVEN: Some test data which contains different references to parse, with the expected results. + with patch('openlp.plugins.bibles.lib.Settings', return_value=MagicMock(**{'value.return_value':''})): + # The following test data tests with 222 variants when using the default 'separators' + test_data = [ + # Input reference, book name, chapter + verse reference + ('Psalm 23', 'Psalm', '23'), + ('Psalm. 23', 'Psalm', '23'), + ('Psalm 23{to}24', 'Psalm', '23-24'), + ('Psalm 23{verse}1{to}2', 'Psalm', '23:1-2'), + ('Psalm 23{verse}1{to}{end}', 'Psalm', '23:1-end'), + ('Psalm 23{verse}1{to}2{_and}5{to}6', 'Psalm', '23:1-2,5-6'), + ('Psalm 23{verse}1{to}2{_and}5{to}{end}', 'Psalm', '23:1-2,5-end'), + ('Psalm 23{verse}1{to}2{_and}24{verse}1{to}3', 'Psalm', '23:1-2,24:1-3'), + ('Psalm 23{verse}1{to}{end}{_and}24{verse}1{to}{end}', 'Psalm', '23:1-end,24:1-end'), + ('Psalm 23{verse}1{to}24{verse}1', 'Psalm', '23:1-24:1'), + ('Psalm 23{_and}24', 'Psalm', '23,24'), + ('1 John 23', '1 John', '23'), + ('1 John. 23', '1 John', '23'), + ('1 John 23{to}24', '1 John', '23-24'), + ('1 John 23{verse}1{to}2', '1 John', '23:1-2'), + ('1 John 23{verse}1{to}{end}', '1 John', '23:1-end'), + ('1 John 23{verse}1{to}2{_and}5{to}6', '1 John', '23:1-2,5-6'), + ('1 John 23{verse}1{to}2{_and}5{to}{end}', '1 John', '23:1-2,5-end'), + ('1 John 23{verse}1{to}2{_and}24{verse}1{to}3', '1 John', '23:1-2,24:1-3'), + ('1 John 23{verse}1{to}{end}{_and}24{verse}1{to}{end}', '1 John', '23:1-end,24:1-end'), + ('1 John 23{verse}1{to}24{verse}1', '1 John', '23:1-24:1'), + ('1 John 23{_and}24', '1 John', '23,24')] + + full_reference_match = get_reference_match('full') + for reference_text, book_result, ranges_result in test_data: + to_separators = ['-', ' - ', 'to', ' to '] if '{to}' in reference_text else [''] + verse_separators = [':', ' : ', 'v', ' v ', 'V', ' V ', 'verse', ' verse ', 'verses', ' verses '] \ + if '{verse}' in reference_text else [''] + and_separators = [',', ' , ', 'and', ' and '] if '{_and}' in reference_text else [''] + end_separators = ['end', ' end '] if '{end}' in reference_text else ['']; + + for to in to_separators: + for verse in verse_separators: + for _and in and_separators: + for end in end_separators: + reference_text = reference_text.format(to=to, verse=verse, _and=_and, end=end) + + # WHEN: Attempting to parse the input string + match = full_reference_match.match(reference_text) + + # THEN: A match should be returned, and the book and reference should match the + # expected result + self.assertIsNotNone(match, '{text} should provide a match'.format(text=reference_text)) + self.assertEqual(book_result, match.group('book'), + '{text} does not provide the expected result for the book group.' + .format(text=reference_text)) + self.assertEqual(ranges_result, match.group('ranges'), + '{text} does not provide the expected result for the ranges group.' + .format(text=reference_text)) + + def test_reference_matched_range(self): + """ + Test that the 'range' regex parses bible verse references correctly. + Note: This test takes in to account that the regex does not work quite as expected! + see https://bugs.launchpad.net/openlp/+bug/1638620 + """ + # GIVEN: Some test data which contains different references to parse, with the expected results. + with patch('openlp.plugins.bibles.lib.Settings', return_value=MagicMock(**{'value.return_value':''})): + # The following test data tests with 45 variants when using the default 'separators' + test_data = [ + ('23', None, '23', None, None, None), + ('23{to}24', None, '23', '-24', None, '24'), + ('23{verse}1{to}2', '23', '1', '-2', None, '2'), + ('23{verse}1{to}{end}', '23', '1', '-end', None, None), + ('23{verse}1{to}24{verse}1', '23', '1', '-24:1', '24', '1')] + full_reference_match = get_reference_match('range') + for reference_text, from_chapter, from_verse, range_to, to_chapter, to_verse in test_data: + to_separators = ['-', ' - ', 'to', ' to '] if '{to}' in reference_text else [''] + verse_separators = [':', ' : ', 'v', ' v ', 'V', ' V ', 'verse', ' verse ', 'verses', ' verses '] \ + if '{verse}' in reference_text else [''] + and_separators = [',', ' , ', 'and', ' and '] if '{_and}' in reference_text else [''] + end_separators = ['end', ' end '] if '{end}' in reference_text else ['']; + + for to in to_separators: + for verse in verse_separators: + for _and in and_separators: + for end in end_separators: + reference_text = reference_text.format(to=to, verse=verse, _and=_and, end=end) + + # WHEN: Attempting to parse the input string + match = full_reference_match.match(reference_text) + + # THEN: A match should be returned, and the to/from chapter/verses should match as + # expected + self.assertIsNotNone(match, '{text} should provide a match'.format(text=reference_text)) + self.assertEqual(match.group('from_chapter'), from_chapter) + self.assertEqual(match.group('from_verse'), from_verse) + self.assertEqual(match.group('range_to'), range_to) + self.assertEqual(match.group('to_chapter'), to_chapter) + self.assertEqual(match.group('to_verse'), to_verse) + + def test_reference_matched_range_separator(self): + # GIVEN: Some test data which contains different references to parse, with the expected results. + with patch('openlp.plugins.bibles.lib.Settings', return_value=MagicMock(**{'value.return_value': ''})): + # The following test data tests with 111 variants when using the default 'separators' + # The regex for handling ranges is a bit screwy, see https://bugs.launchpad.net/openlp/+bug/1638620 + test_data = [ + ('23',['23']), + ('23{to}24',['23-24']), + ('23{verse}1{to}2', ['23:1-2']), + ('23{verse}1{to}{end}', ['23:1-end']), + ('23{verse}1{to}2{_and}5{to}6', ['23:1-2', '5-6']), + ('23{verse}1{to}2{_and}5{to}{end}', ['23:1-2', '5-end']), + ('23{verse}1{to}2{_and}24{verse}1{to}3', ['23:1-2', '24:1-3']), + ('23{verse}1{to}{end}{_and}24{verse}1{to}{end}', ['23:1-end', '24:1-end']), + ('23{verse}1{to}24{verse}1', ['23:1-24:1']), + ('23,24', ['23', '24'])] + full_reference_match = get_reference_match('range_separator') + for reference_text, ranges in test_data: + to_separators = ['-', ' - ', 'to', ' to '] if '{to}' in reference_text else [''] + verse_separators = [':', ' : ', 'v', ' v ', 'V', ' V ', 'verse', ' verse ', 'verses', ' verses '] \ + if '{verse}' in reference_text else [''] + and_separators = [',', ' , ', 'and', ' and '] if '{_and}' in reference_text else [''] + end_separators = ['end', ' end '] if '{end}' in reference_text else ['']; + + for to in to_separators: + for verse in verse_separators: + for _and in and_separators: + for end in end_separators: + reference_text = reference_text.format(to=to, verse=verse, _and=_and, end=end) + + # WHEN: Attempting to parse the input string + references = full_reference_match.split(reference_text) + + # THEN: The list of references should be as the expected results + self.assertEqual(references, ranges) + def test_search_results_creation(self): """ Test the creation and construction of the SearchResults class