merge trunk

This commit is contained in:
Jonathan Springer 2015-11-29 17:57:37 -05:00
commit 3b3c8a35b6
14 changed files with 284 additions and 25 deletions

View File

@ -514,9 +514,14 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
:param display: Which display to use
:param service_item: The ServiceItem containing the details to be played.
"""
used_players = get_media_players()[0]
used_players = get_media_players()
default_player = used_players[0]
if service_item.processor and service_item.processor != UiStrings().Automatic:
used_players = [service_item.processor.lower()]
# check to see if the player is usable else use the default one.
if not service_item.processor.lower() in used_players:
used_players = default_player
else:
used_players = [service_item.processor.lower()]
# If no player, we can't play
if not used_players:
return False

View File

@ -50,7 +50,11 @@ class AlertsManager(OpenLPMixin, RegistryMixin, QtCore.QObject, RegistryProperti
:param message: The message text to be displayed
"""
if message:
self.display_alert(message[0])
text = message[0]
# remove line breaks as these crash javascript code on display
while '\n' in text:
text = text.replace('\n', ' ')
self.display_alert(text)
def display_alert(self, text=''):
"""

View File

@ -27,7 +27,6 @@ import re
import socket
import urllib.parse
import urllib.error
from html.parser import HTMLParseError
from bs4 import BeautifulSoup, NavigableString, Tag
@ -290,7 +289,7 @@ class BGExtract(RegistryProperties):
page_source = str(page_source, 'cp1251')
try:
soup = BeautifulSoup(page_source)
except HTMLParseError:
except Exception:
log.error('BeautifulSoup could not parse the Bible page.')
send_error_message('parse')
return None
@ -762,7 +761,7 @@ def get_soup_for_bible_ref(reference_url, header=None, pre_parse_regex=None, pre
try:
soup = BeautifulSoup(page_source)
CLEANER_REGEX.sub('', str(soup))
except HTMLParseError:
except Exception:
log.exception('BeautifulSoup could not parse the bible page.')
if not soup:
send_error_message('parse')

View File

@ -290,6 +290,13 @@ class MessageListener(object):
log.info('Message Listener loaded')
def __init__(self, media_item):
self._setup(media_item)
def _setup(self, media_item):
"""
Start up code moved out to make mocking easier
:param media_item: The plugin media item handing Presentations
"""
self.controllers = media_item.controllers
self.media_item = media_item
self.preview_handler = Controller(False)
@ -346,6 +353,12 @@ class MessageListener(object):
self.handler = self.media_item.find_controller_by_type(file)
if not self.handler:
return
else:
# the saved handler is not present so need to use one based on file suffix.
if not self.controllers[self.handler].available:
self.handler = self.media_item.find_controller_by_type(file)
if not self.handler:
return
if is_live:
controller = self.live_handler
else:

View File

@ -23,11 +23,12 @@
The :mod:`~openlp.plugins.songs.lib.songselect` module contains the SongSelect importer itself.
"""
import logging
import sys
from http.cookiejar import CookieJar
from urllib.parse import urlencode
from urllib.request import HTTPCookieProcessor, URLError, build_opener
from html.parser import HTMLParser
from html import unescape
from bs4 import BeautifulSoup, NavigableString
@ -130,8 +131,8 @@ class SongSelectImport(object):
break
for result in search_results:
song = {
'title': self.html_parser.unescape(result.find('h3').string),
'authors': [self.html_parser.unescape(author.string) for author in result.find_all('li')],
'title': unescape(result.find('h3').string),
'authors': [unescape(author.string) for author in result.find_all('li')],
'link': BASE_URL + result.find('a')['href']
}
if callback:
@ -167,7 +168,7 @@ class SongSelectImport(object):
if callback:
callback()
song['copyright'] = '/'.join([li.string for li in song_page.find('ul', 'copyright').find_all('li')])
song['copyright'] = self.html_parser.unescape(song['copyright'])
song['copyright'] = unescape(song['copyright'])
song['ccli_number'] = song_page.find('ul', 'info').find('li').string.split(':')[1].strip()
song['verses'] = []
verses = lyrics_page.find('section', 'lyrics').find_all('p')
@ -180,9 +181,9 @@ class SongSelectImport(object):
else:
verse['lyrics'] += '\n'
verse['lyrics'] = verse['lyrics'].strip(' \n\r\t')
song['verses'].append(self.html_parser.unescape(verse))
song['verses'].append(unescape(verse))
for counter, author in enumerate(song['authors']):
song['authors'][counter] = self.html_parser.unescape(author)
song['authors'][counter] = unescape(author)
return song
def save_song(self, song):

View File

@ -94,6 +94,12 @@ class TestProjectorDB(TestCase):
mocked_init_url.return_value = 'sqlite:///%s' % tmpfile
self.projector = ProjectorDB()
def tearDown(self):
"""
Clean up
"""
self.projector = None
def find_record_by_ip_test(self):
"""
Test find record by IP

View File

@ -240,4 +240,4 @@ class TestThemeManager(TestCase):
theme_manager.unzip_theme('theme.file', 'folder')
# THEN: The critical_error_message_box should have been called
mocked_critical_error_message_box.assert_called_once(ANY, ANY)
self.assertEqual(mocked_critical_error_message_box.call_count, 1, 'Should have been called once')

View File

@ -25,7 +25,7 @@ Package to test the openlp.core.ui.media.vlcplayer package.
import os
import sys
from datetime import datetime, timedelta
from unittest import TestCase
from unittest import TestCase, skip
from openlp.core.common import Registry
from openlp.core.ui.media import MediaState, MediaType
@ -50,6 +50,22 @@ class TestVLCPlayer(TestCase, TestMixin):
del sys.modules['openlp.core.ui.media.vendor.vlc']
MockDateTime.revert()
@skip('No way to test this')
@patch('openlp.core.ui.media.vlcplayer.vlc')
def get_vlc_fails_and_removes_module_test(self, mocked_vlc):
"""
Test that when the VLC import fails, it removes the module from sys.modules
"""
# GIVEN: We're on OS X and we don't have the VLC plugin path set
mocked_vlc.Instance.side_effect = NameError
mocked_vlc.libvlc_get_version.return_value = b'0.0.0'
# WHEN: An checking if the player is available
get_vlc()
# THEN: The extra environment variable should be there
self.assertNotIn('openlp.core.ui.media.vendor.vlc', sys.modules)
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
def fix_vlc_22_plugin_path_test(self, mocked_is_macosx):
"""
@ -74,10 +90,6 @@ class TestVLCPlayer(TestCase, TestMixin):
"""
# GIVEN: We're not on OS X and we don't have the VLC plugin path set
mocked_is_macosx.return_value = False
if 'VLC_PLUGIN_PATH' in os.environ:
del os.environ['VLC_PLUGIN_PATH']
if 'openlp.core.ui.media.vendor.vlc' in sys.modules:
del sys.modules['openlp.core.ui.media.vendor.vlc']
# WHEN: An checking if the player is available
get_vlc()

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2015 OpenLP Developers #
# --------------------------------------------------------------------------- #
# 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; version 2 of the License. #
# #
# 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, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################

View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2015 OpenLP Developers #
# --------------------------------------------------------------------------- #
# 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; version 2 of the License. #
# #
# 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, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
This module contains tests for the CSV Bible importer.
"""
import os
import json
from unittest import TestCase
from tests.functional import MagicMock, patch
from openlp.core.common.registry import Registry
from openlp.plugins.alerts.lib.alertsmanager import AlertsManager
class TestAlertManager(TestCase):
def setUp(self):
"""
Create the UI
"""
Registry.create()
def remove_message_text_test(self):
"""
Test that Alerts are not triggered with empty strings
"""
# GIVEN: A valid Alert Manager
alert_manager = AlertsManager(None)
alert_manager.display_alert = MagicMock()
# WHEN: Called with an empty string
alert_manager.alert_text('')
# THEN: the display should not have been triggered
self.assertFalse(alert_manager.display_alert.called, 'The Alert should not have been called')
def trigger_message_text_test(self):
"""
Test that Alerts are triggered with a text string
"""
# GIVEN: A valid Alert Manager
alert_manager = AlertsManager(None)
alert_manager.display_alert = MagicMock()
# WHEN: Called with an empty string
alert_manager.alert_text(['This is a string'])
# THEN: the display should have been triggered
self.assertTrue(alert_manager.display_alert.called, 'The Alert should have been called')
def line_break_message_text_test(self):
"""
Test that Alerts are triggered with a text string but line breaks are removed
"""
# GIVEN: A valid Alert Manager
alert_manager = AlertsManager(None)
alert_manager.display_alert = MagicMock()
# WHEN: Called with an empty string
alert_manager.alert_text(['This is \n a string'])
# THEN: the display should have been triggered
self.assertTrue(alert_manager.display_alert.called, 'The Alert should have been called')
alert_manager.display_alert.assert_called_once_with('This is a string')

View File

@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2015 OpenLP Developers #
# --------------------------------------------------------------------------- #
# 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; version 2 of the License. #
# #
# 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, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
This module contains tests for the lib submodule of the Presentations plugin.
"""
from unittest import TestCase
from openlp.core.common import Registry
from openlp.plugins.presentations.lib.mediaitem import MessageListener, PresentationMediaItem
from tests.functional import patch, MagicMock
from tests.helpers.testmixin import TestMixin
class TestMessageListener(TestCase, TestMixin):
"""
Test the Presentation Message Listener.
"""
def setUp(self):
"""
Set up the components need for all tests.
"""
Registry.create()
Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def start_presentation_test(self, media_mock):
"""
Find and chose a controller to play a presentations.
"""
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
controllers = {
'Powerpoint': mocked_controller
}
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The controllers will be setup.
self.assertTrue(len(controllers), 'We have loaded a controller')
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def start_presentation_with_no_player_test(self, media_mock):
"""
Find and chose a controller to play a presentations when the player is not available.
"""
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
mocked_controller1 = MagicMock()
mocked_controller1.available = False
mocked_controller1.supports = ['ppt']
controllers = {
'Impress': mocked_controller,
'Powerpoint': mocked_controller1
}
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The controllers will be setup.
self.assertTrue(len(controllers), 'We have loaded a controller')

View File

@ -49,11 +49,17 @@ class TestPresentationController(TestCase):
# _get_plugin_manager
def setUp(self):
self.get_thumbnail_folder_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
self.get_thumbnail_folder_patcher.start()
mocked_plugin = MagicMock()
mocked_plugin.settings_section = 'presentations'
self.presentation = PresentationController(mocked_plugin)
self.document = PresentationDocument(self.presentation, '')
def tearDown(self):
self.get_thumbnail_folder_patcher.stop()
def constructor_test(self):
"""
Test the Constructor
@ -86,8 +92,8 @@ class TestPresentationController(TestCase):
mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), mode='wt', encoding='utf-8')
self.assertEqual(mocked_open.call_count, 3, 'There should be exactly three files opened')
mocked_open().writelines.assert_called_once_with(['uno', 'dos'])
mocked_open().write.assert_called_any('one')
mocked_open().write.assert_called_any('two')
mocked_open().write.assert_any_call('one')
mocked_open().write.assert_any_call('two')
def save_titles_and_notes_with_None_test(self):
"""

View File

@ -273,7 +273,6 @@ class TestRouter(TestCase, TestMixin):
self.router.end_headers = MagicMock()
self.router.wfile = MagicMock()
mocked_image_manager = MagicMock()
Registry.create()
Registry().register('image_manager', mocked_image_manager)
file_name = 'another%20test/slide1.png'
full_path = os.path.normpath(os.path.join('thumbnails', file_name))
@ -296,9 +295,12 @@ class TestRouter(TestCase, TestMixin):
self.assertEqual(self.router.end_headers.call_count, 1, 'end_headers called once')
mocked_exists.assert_called_with(urllib.parse.unquote(full_path))
self.assertEqual(mocked_image_to_byte.call_count, 1, 'Called once')
mocked_image_manager.assert_called_any(os.path.normpath('thumbnails\\another test'),
'slide1.png', None, '120x90')
mocked_image_manager.assert_called_any(os.path.normpath('thumbnails\\another test'), 'slide1.png', '120x90')
mocked_image_manager.add_image.assert_any_call(os.path.normpath(os.path.join('thumbnails', 'another test',
'slide1.png')),
'slide1.png', None, width, height)
mocked_image_manager.get_image.assert_any_call(os.path.normpath(os.path.join('thumbnails', 'another test',
'slide1.png')),
'slide1.png', width, height)
def remote_next_test(self):
"""

View File

@ -403,7 +403,7 @@ class TestEasyWorshipSongImport(TestCase):
# 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_call(encoding)
mocked_retrieve_windows_encoding.assert_any_call(encoding)
def db_file_import_test(self):
"""