forked from openlp/openlp
Merge head
This commit is contained in:
commit
1ef910463c
@ -83,6 +83,8 @@ class UiStrings(object):
|
||||
self.Error = translate('OpenLP.Ui', 'Error')
|
||||
self.Export = translate('OpenLP.Ui', 'Export')
|
||||
self.File = translate('OpenLP.Ui', 'File')
|
||||
self.FileNotFound = translate('OpenLP.Ui', 'File Not Found')
|
||||
self.FileNotFoundMessage = translate('OpenLP.Ui', 'File %s not found.\nPlease try selecting it individually.')
|
||||
self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
|
||||
self.Help = translate('OpenLP.Ui', 'Help')
|
||||
self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
|
||||
|
@ -336,6 +336,7 @@ def create_separated_list(string_list):
|
||||
|
||||
|
||||
from .registry import Registry
|
||||
from .filedialog import FileDialog
|
||||
from .screen import ScreenList
|
||||
from .listwidgetwithdnd import ListWidgetWithDnD
|
||||
from .treewidgetwithdnd import TreeWidgetWithDnD
|
||||
@ -351,4 +352,3 @@ from .dockwidget import OpenLPDockWidget
|
||||
from .imagemanager import ImageManager
|
||||
from .renderer import Renderer
|
||||
from .mediamanageritem import MediaManagerItem
|
||||
|
||||
|
66
openlp/core/lib/filedialog.py
Normal file
66
openlp/core/lib/filedialog.py
Normal file
@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
Provide a work around for a bug in QFileDialog <https://bugs.launchpad.net/openlp/+bug/1209515>
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from urllib import parse
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.common import UiStrings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class FileDialog(QtGui.QFileDialog):
|
||||
"""
|
||||
Subclass QFileDialog to work round a bug
|
||||
"""
|
||||
@staticmethod
|
||||
def getOpenFileNames(parent, *args, **kwargs):
|
||||
"""
|
||||
Reimplement getOpenFileNames to fix the way it returns some file names that url encoded when selecting multiple
|
||||
files
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(parent, *args, **kwargs)
|
||||
file_list = []
|
||||
for file in files:
|
||||
if not os.path.exists(file):
|
||||
log.info('File %s not found. Attempting to unquote.')
|
||||
file = parse.unquote(file)
|
||||
if not os.path.exists(file):
|
||||
log.error('File %s not found.' % file)
|
||||
QtGui.QMessageBox.information(parent, UiStrings().FileNotFound,
|
||||
UiStrings().FileNotFoundMessage % file)
|
||||
continue
|
||||
log.info('File %s found.')
|
||||
file_list.append(file)
|
||||
return file_list
|
@ -36,7 +36,7 @@ import re
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import Settings, UiStrings, translate
|
||||
from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, ListWidgetWithDnD, \
|
||||
from openlp.core.lib import FileDialog, OpenLPToolbar, ServiceItem, StringContent, ListWidgetWithDnD, \
|
||||
ServiceItemContext, Registry
|
||||
from openlp.core.lib.searchedit import SearchEdit
|
||||
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
|
||||
@ -319,7 +319,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
Add a file to the list widget to make it available for showing
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(self, self.on_new_prompt,
|
||||
files = FileDialog.getOpenFileNames(self, self.on_new_prompt,
|
||||
Settings().value(self.settings_section + '/last directory'), self.on_new_file_masks)
|
||||
log.info('New files(s) %s', files)
|
||||
if files:
|
||||
|
@ -37,7 +37,7 @@ import urllib.request
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
from tempfile import gettempdir
|
||||
from configparser import SafeConfigParser
|
||||
from configparser import ConfigParser
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -68,7 +68,7 @@ class ThemeScreenshotThread(QtCore.QThread):
|
||||
filename = config.get('theme_%s' % theme, 'filename')
|
||||
screenshot = config.get('theme_%s' % theme, 'screenshot')
|
||||
urllib.request.urlretrieve('%s%s' % (self.parent().web, screenshot),
|
||||
os.path.join(gettempdir(), 'openlp', screenshot))
|
||||
os.path.join(gettempdir(), 'openlp', screenshot))
|
||||
item = QtGui.QListWidgetItem(title, self.parent().themes_list_widget)
|
||||
item.setData(QtCore.Qt.UserRole, filename)
|
||||
item.setCheckState(QtCore.Qt.Unchecked)
|
||||
@ -90,14 +90,16 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.screens = screens
|
||||
# check to see if we have web access
|
||||
self.web = 'http://openlp.org/files/frw/'
|
||||
self.config = SafeConfigParser()
|
||||
self.web_access = get_web_page('%s%s' % (self.web, 'download.cfg'))
|
||||
self.config = ConfigParser()
|
||||
user_agent = 'OpenLP/' + Registry().get('application').applicationVersion()
|
||||
self.web_access = get_web_page('%s%s' % (self.web, 'download.cfg'), header=('User-Agent', user_agent))
|
||||
if self.web_access:
|
||||
files = self.web_access.read()
|
||||
self.config.read_string(files.decode())
|
||||
self.update_screen_list_combo()
|
||||
self.was_download_cancelled = False
|
||||
self.theme_screenshot_thread = None
|
||||
self.has_run_wizard = False
|
||||
self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading %s...')
|
||||
self.cancel_button.clicked.connect(self.on_cancel_button_clicked)
|
||||
self.no_internet_finish_button.clicked.connect(self.on_no_internet_finish_button_clicked)
|
||||
|
@ -74,7 +74,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
if event.key() == QtCore.Qt.Key_Space:
|
||||
self.keyReleaseEvent(event)
|
||||
elif self.primaryPushButton.isChecked() or self.alternatePushButton.isChecked():
|
||||
event.ignore()
|
||||
self.keyReleaseEvent(event)
|
||||
elif event.key() == QtCore.Qt.Key_Escape:
|
||||
event.accept()
|
||||
self.close()
|
||||
|
@ -33,13 +33,12 @@ import os
|
||||
import zipfile
|
||||
import shutil
|
||||
import logging
|
||||
import re
|
||||
|
||||
from xml.etree.ElementTree import ElementTree, XML
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import AppLocation, Settings, check_directory_exists, UiStrings, translate
|
||||
from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, get_text_file_string, build_icon, \
|
||||
from openlp.core.lib import FileDialog, ImageSource, OpenLPToolbar, Registry, get_text_file_string, build_icon, \
|
||||
check_item_selected, create_thumb, validate_thumb
|
||||
from openlp.core.lib.theme import ThemeXML, BackgroundType
|
||||
from openlp.core.lib.ui import critical_error_message_box, create_widget_action
|
||||
@ -59,7 +58,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
"""
|
||||
super(ThemeManager, self).__init__(parent)
|
||||
Registry().register('theme_manager', self)
|
||||
Registry().register_function('bootstrap_initialise', self.load_first_time_themes)
|
||||
Registry().register_function('bootstrap_initialise', self.initialise)
|
||||
Registry().register_function('bootstrap_post_set_up', self._push_themes)
|
||||
self.settings_section = 'themes'
|
||||
self.theme_form = ThemeForm(self)
|
||||
@ -135,15 +134,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
Registry().register_function('theme_update_global', self.change_global_from_tab)
|
||||
# Variables
|
||||
self.theme_list = []
|
||||
self.path = AppLocation.get_section_data_path(self.settings_section)
|
||||
check_directory_exists(self.path)
|
||||
self.thumb_path = os.path.join(self.path, 'thumbnails')
|
||||
check_directory_exists(self.thumb_path)
|
||||
self.theme_form.path = self.path
|
||||
self.old_background_image = None
|
||||
self.bad_v1_name_chars = re.compile(r'[%+\[\]]')
|
||||
# Last little bits of setting up
|
||||
self.global_theme = Settings().value(self.settings_section + '/global theme')
|
||||
|
||||
def check_list_state(self, item):
|
||||
"""
|
||||
@ -374,7 +365,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from
|
||||
those files. This process will load both OpenLP version 1 and version 2 themes.
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(self,
|
||||
files = FileDialog.getOpenFileNames(self,
|
||||
translate('OpenLP.ThemeManager', 'Select Theme Import File'),
|
||||
Settings().value(self.settings_section + '/last directory import'),
|
||||
translate('OpenLP.ThemeManager', 'OpenLP Themes (*.theme *.otz)'))
|
||||
@ -392,6 +383,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
"""
|
||||
Imports any themes on start up and makes sure there is at least one theme
|
||||
"""
|
||||
log.debug('load_first_time_themes called')
|
||||
self.application.set_busy_cursor()
|
||||
files = AppLocation.get_files(self.settings_section, '.otz')
|
||||
for theme_file in files:
|
||||
@ -410,8 +402,8 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
|
||||
def load_themes(self):
|
||||
"""
|
||||
Loads the theme lists and triggers updates across the whole system
|
||||
using direct calls or core functions and events for the plugins.
|
||||
Loads the theme lists and triggers updates across the whole system using direct calls or core functions and
|
||||
events for the plugins.
|
||||
The plugins will call back in to get the real list if they want it.
|
||||
"""
|
||||
log.debug('Load themes from dir')
|
||||
@ -636,18 +628,18 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
self.main_window.finished_progress_bar()
|
||||
self.load_themes()
|
||||
|
||||
def generate_image(self, theme_data, forcePage=False):
|
||||
def generate_image(self, theme_data, force_page=False):
|
||||
"""
|
||||
Call the renderer to build a Sample Image
|
||||
|
||||
``theme_data``
|
||||
The theme to generated a preview for.
|
||||
|
||||
``forcePage``
|
||||
``force_page``
|
||||
Flag to tell message lines per page need to be generated.
|
||||
"""
|
||||
log.debug('generate_image \n%s ', theme_data)
|
||||
return self.renderer.generate_preview(theme_data, forcePage)
|
||||
return self.renderer.generate_preview(theme_data, force_page)
|
||||
|
||||
def get_preview_image(self, theme):
|
||||
"""
|
||||
@ -672,7 +664,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
theme.extend_image_filename(path)
|
||||
return theme
|
||||
|
||||
def _validate_theme_action(self, select_text, confirm_title, confirm_text, testPlugin=True, confirm=True):
|
||||
def _validate_theme_action(self, select_text, confirm_title, confirm_text, test_plugin=True, confirm=True):
|
||||
"""
|
||||
Check to see if theme has been selected and the destructive action
|
||||
is allowed.
|
||||
@ -694,7 +686,7 @@ class ThemeManager(QtGui.QWidget, ThemeManagerHelper):
|
||||
message=translate('OpenLP.ThemeManager', 'You are unable to delete the default theme.'))
|
||||
return False
|
||||
# check for use in the system else where.
|
||||
if testPlugin:
|
||||
if test_plugin:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if plugin.uses_theme(theme):
|
||||
critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'),
|
||||
|
@ -29,10 +29,34 @@
|
||||
"""
|
||||
The Theme Controller helps manages adding, deleteing and modifying of themes.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
|
||||
from openlp.core.common import AppLocation, Settings, check_directory_exists
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ThemeManagerHelper(object):
|
||||
"""
|
||||
Manages the non ui theme functions.
|
||||
"""
|
||||
pass
|
||||
def initialise(self):
|
||||
"""
|
||||
Setup the manager
|
||||
"""
|
||||
log.debug('initialise called')
|
||||
self.global_theme = Settings().value(self.settings_section + '/global theme')
|
||||
self.build_theme_path()
|
||||
self.load_first_time_themes()
|
||||
|
||||
def build_theme_path(self):
|
||||
"""
|
||||
Set up the theme path variables
|
||||
"""
|
||||
log.debug('build theme path called')
|
||||
self.path = AppLocation.get_section_data_path(self.settings_section)
|
||||
check_directory_exists(self.path)
|
||||
self.thumb_path = os.path.join(self.path, 'thumbnails')
|
||||
check_directory_exists(self.thumb_path)
|
||||
self.theme_form.path = self.path
|
@ -40,6 +40,7 @@ import sys
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
from random import randint
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
@ -61,10 +62,29 @@ APPLICATION_VERSION = {}
|
||||
IMAGES_FILTER = None
|
||||
ICU_COLLATOR = None
|
||||
UNO_CONNECTION_TYPE = 'pipe'
|
||||
#UNO_CONNECTION_TYPE = u'socket'
|
||||
CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
|
||||
INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
|
||||
DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
|
||||
USER_AGENTS = {
|
||||
'win32': [
|
||||
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36'
|
||||
],
|
||||
'darwin': [
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11',
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11',
|
||||
],
|
||||
'linux2': [
|
||||
'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22',
|
||||
'Mozilla/5.0 (X11; CrOS armv7l 2913.260.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.99 Safari/537.11',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.27 (KHTML, like Gecko) Chrome/26.0.1389.0 Safari/537.27'
|
||||
],
|
||||
'default': [
|
||||
'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0'
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
class VersionThread(QtCore.QThread):
|
||||
@ -298,6 +318,17 @@ def delete_file(file_path_name):
|
||||
return False
|
||||
|
||||
|
||||
def _get_user_agent():
|
||||
"""
|
||||
Return a user agent customised for the platform the user is on.
|
||||
"""
|
||||
browser_list = USER_AGENTS.get(sys.platform, None)
|
||||
if not browser_list:
|
||||
browser_list = USER_AGENTS['default']
|
||||
random_index = randint(0, len(browser_list) - 1)
|
||||
return browser_list[random_index]
|
||||
|
||||
|
||||
def get_web_page(url, header=None, update_openlp=False):
|
||||
"""
|
||||
Attempts to download the webpage at url and returns that page or None.
|
||||
@ -318,6 +349,9 @@ def get_web_page(url, header=None, update_openlp=False):
|
||||
if not url:
|
||||
return None
|
||||
req = urllib.request.Request(url)
|
||||
if not header or header[0].lower() != 'user-agent':
|
||||
user_agent = _get_user_agent()
|
||||
req.add_header('User-Agent', user_agent)
|
||||
if header:
|
||||
req.add_header(header[0], header[1])
|
||||
page = None
|
||||
|
@ -379,7 +379,7 @@ class BSExtract(object):
|
||||
send_error_message('parse')
|
||||
return None
|
||||
content = content.find_all('li')
|
||||
return [book.contents[0].contents[0] for book in content]
|
||||
return [book.contents[0].contents[0] for book in content if len(book.contents[0].contents)]
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
|
@ -281,7 +281,7 @@ class Controller(object):
|
||||
|
||||
class MessageListener(object):
|
||||
"""
|
||||
This is the Presentation listener who acts on events from the slide controller and passes the messages on the the
|
||||
This is the Presentation listener who acts on events from the slide controller and passes the messages on the
|
||||
correct presentation handlers
|
||||
"""
|
||||
log.info('Message Listener loaded')
|
||||
|
@ -337,8 +337,8 @@ class PresentationDocument(object):
|
||||
|
||||
class PresentationController(object):
|
||||
"""
|
||||
This class is used to control interactions with presentation applications by creating a runtime environment. This is
|
||||
a base class for presentation controllers to inherit from.
|
||||
This class is used to control interactions with presentation applications by creating a runtime environment.
|
||||
This is a base class for presentation controllers to inherit from.
|
||||
|
||||
To create a new controller, take a copy of this file and name it so it ends with ``controller.py``, i.e.
|
||||
``foobarcontroller.py``. Make sure it inherits
|
||||
@ -386,8 +386,7 @@ class PresentationController(object):
|
||||
"""
|
||||
log.info('PresentationController loaded')
|
||||
|
||||
def __init__(self, plugin=None, name='PresentationController',
|
||||
document_class=PresentationDocument):
|
||||
def __init__(self, plugin=None, name='PresentationController', document_class=PresentationDocument):
|
||||
"""
|
||||
This is the constructor for the presentationcontroller object. This provides an easy way for descendent plugins
|
||||
to populate common data. This method *must* be overridden, like so::
|
||||
|
@ -39,7 +39,7 @@ import shutil
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import AppLocation, UiStrings, check_directory_exists, translate
|
||||
from openlp.core.lib import Registry, PluginStatus, MediaType, create_separated_list
|
||||
from openlp.core.lib import FileDialog, Registry, PluginStatus, MediaType, create_separated_list
|
||||
from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box
|
||||
from openlp.plugins.songs.lib import VerseType, clean_song
|
||||
from openlp.plugins.songs.lib.db import Book, Song, Author, Topic, MediaFile
|
||||
@ -758,7 +758,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
Loads file(s) from the filesystem.
|
||||
"""
|
||||
filters = '%s (*)' % UiStrings().AllFiles
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self,
|
||||
filenames = FileDialog.getOpenFileNames(self,
|
||||
translate('SongsPlugin.EditSongForm', 'Open File(s)'), '', filters)
|
||||
for filename in filenames:
|
||||
item = QtGui.QListWidgetItem(os.path.split(str(filename))[1])
|
||||
|
@ -37,7 +37,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import UiStrings, translate
|
||||
from openlp.core.common import Settings
|
||||
from openlp.core.lib import Registry
|
||||
from openlp.core.lib import FileDialog, Registry
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||
from openlp.plugins.songs.lib.importer import SongFormat, SongFormatSelect
|
||||
@ -246,7 +246,7 @@ class SongImportForm(OpenLPWizard):
|
||||
if filters:
|
||||
filters += ';;'
|
||||
filters += '%s (*)' % UiStrings().AllFiles
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
|
||||
filenames = FileDialog.getOpenFileNames(self, title,
|
||||
Settings().value(self.plugin.settings_section + '/last directory import'), filters)
|
||||
if filenames:
|
||||
listbox.addItems(filenames)
|
||||
|
@ -11,9 +11,9 @@ import sys
|
||||
from PyQt4 import QtGui
|
||||
|
||||
if sys.version_info[1] >= 3:
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import MagicMock, patch, mock_open
|
||||
else:
|
||||
from mock import patch, MagicMock
|
||||
from mock import MagicMock, patch, mock_open
|
||||
|
||||
# Only one QApplication can be created. Use QtGui.QApplication.instance() when you need to "create" a QApplication.
|
||||
application = QtGui.QApplication([])
|
||||
|
@ -1 +1,28 @@
|
||||
__author__ = 'tim'
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
|
@ -59,7 +59,6 @@ class TestAppLocation(TestCase):
|
||||
|
||||
# WHEN: we call AppLocation.get_data_path()
|
||||
data_path = AppLocation.get_data_path()
|
||||
print(data_path)
|
||||
|
||||
# THEN: check that all the correct methods were called, and the result is correct
|
||||
mocked_settings.contains.assert_called_with('advanced/data path')
|
||||
|
73
tests/functional/openlp_core_lib/test_file_dialog.py
Normal file
73
tests/functional/openlp_core_lib/test_file_dialog.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""
|
||||
Package to test the openlp.core.lib.filedialog package.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.common import UiStrings
|
||||
from openlp.core.lib.filedialog import FileDialog
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
class TestFileDialog(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`filedialog` module.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.os_patcher = patch('openlp.core.lib.filedialog.os')
|
||||
self.qt_gui_patcher = patch('openlp.core.lib.filedialog.QtGui')
|
||||
self.ui_strings_patcher = patch('openlp.core.lib.filedialog.UiStrings')
|
||||
self.mocked_os = self.os_patcher.start()
|
||||
self.mocked_qt_gui = self.qt_gui_patcher.start()
|
||||
self.mocked_ui_strings = self.ui_strings_patcher.start()
|
||||
self.mocked_parent = MagicMock()
|
||||
|
||||
def tearDown(self):
|
||||
self.os_patcher.stop()
|
||||
self.qt_gui_patcher.stop()
|
||||
self.ui_strings_patcher.stop()
|
||||
|
||||
def get_open_file_names_canceled_test(self):
|
||||
"""
|
||||
Test that FileDialog.getOpenFileNames() returns and empty QStringList when QFileDialog is canceled
|
||||
(returns an empty QStringList)
|
||||
"""
|
||||
self.mocked_os.reset()
|
||||
|
||||
# GIVEN: An empty QStringList as a return value from QFileDialog.getOpenFileNames
|
||||
self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = []
|
||||
|
||||
# WHEN: FileDialog.getOpenFileNames is called
|
||||
result = FileDialog.getOpenFileNames(self.mocked_parent)
|
||||
|
||||
# THEN: The returned value should be an empty QStringList and os.path.exists should not have been called
|
||||
assert not self.mocked_os.path.exists.called
|
||||
self.assertEqual(result, [],
|
||||
'FileDialog.getOpenFileNames should return and empty list when QFileDialog.getOpenFileNames is canceled')
|
||||
|
||||
def returned_file_list_test(self):
|
||||
"""
|
||||
Test that FileDialog.getOpenFileNames handles a list of files properly when QFileList.getOpenFileNames
|
||||
returns a good file name, a urlencoded file name and a non-existing file
|
||||
"""
|
||||
self.mocked_os.rest()
|
||||
self.mocked_qt_gui.reset()
|
||||
|
||||
# GIVEN: A List of known values as a return value from QFileDialog.getOpenFileNames and a list of valid
|
||||
# file names.
|
||||
self.mocked_qt_gui.QFileDialog.getOpenFileNames.return_value = [
|
||||
'/Valid File', '/url%20encoded%20file%20%231', '/non-existing']
|
||||
self.mocked_os.path.exists.side_effect = lambda file_name: file_name in [
|
||||
'/Valid File', '/url encoded file #1']
|
||||
|
||||
# WHEN: FileDialog.getOpenFileNames is called
|
||||
result = FileDialog.getOpenFileNames(self.mocked_parent)
|
||||
|
||||
# THEN: os.path.exists should have been called with known args. QmessageBox.information should have been
|
||||
# called. The returned result should corrilate with the input.
|
||||
self.mocked_os.path.exists.assert_callde_with('/Valid File')
|
||||
self.mocked_os.path.exists.assert_callde_with('/url%20encoded%20file%20%231')
|
||||
self.mocked_os.path.exists.assert_callde_with('/url encoded file #1')
|
||||
self.mocked_os.path.exists.assert_callde_with('/non-existing')
|
||||
self.mocked_os.path.exists.assert_callde_with('/non-existing')
|
||||
self.mocked_qt_gui.QmessageBox.information.called_with(self.mocked_parent, UiStrings().FileNotFound,
|
||||
UiStrings().FileNotFoundMessage % '/non-existing')
|
||||
self.assertEqual(result, ['/Valid File', '/url encoded file #1'], 'The returned file list is incorrect')
|
@ -3,13 +3,13 @@ Package to test the openlp.core.lib.htmlbuilder module.
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
from mock import MagicMock, patch
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
|
||||
build_lyrics_format_css, build_footer_css
|
||||
from openlp.core.lib.theme import HorizontalType, VerticalType
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
|
||||
HTML = """
|
||||
|
@ -62,9 +62,11 @@ class TestTheme(TestCase):
|
||||
|
||||
# THEN: We should get some default behaviours
|
||||
self.assertTrue(default_theme.background_border_color == '#000000', 'The theme should have a black border')
|
||||
self.assertTrue(default_theme.background_type == 'solid', 'There theme should have a solid backgrounds')
|
||||
self.assertTrue(default_theme.background_type == 'solid', 'The theme should have a solid backgrounds')
|
||||
self.assertTrue(default_theme.display_vertical_align == 0,
|
||||
'There theme should have display_vertical_align of 0')
|
||||
'The theme should have a display_vertical_align of 0')
|
||||
self.assertTrue(default_theme.font_footer_name == "Arial",
|
||||
'There theme should has font_footer_name of Arial')
|
||||
self.assertTrue(default_theme.font_main_bold is False, 'There theme should has font_main_bold of false')
|
||||
'The theme should have a font_footer_name of Arial')
|
||||
self.assertTrue(default_theme.font_main_bold is False, 'The theme should have a font_main_bold of false')
|
||||
self.assertTrue(len(default_theme.__dict__) == 47, 'The theme should have 47 variables')
|
||||
|
||||
|
@ -32,14 +32,74 @@ Functional tests to test the AppLocation class and related methods.
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.utils import clean_filename, get_filesystem_encoding, get_locale_key, \
|
||||
get_natural_key, split_filename
|
||||
from tests.functional import patch
|
||||
get_natural_key, split_filename, _get_user_agent, get_web_page, get_uno_instance, add_actions
|
||||
from tests.functional import MagicMock, patch
|
||||
|
||||
|
||||
class TestUtils(TestCase):
|
||||
"""
|
||||
A test suite to test out various methods around the AppLocation class.
|
||||
"""
|
||||
def add_actions_empty_list_test(self):
|
||||
"""
|
||||
Test that no actions are added when the list is empty
|
||||
"""
|
||||
# GIVEN: a mocked action list, and an empty list
|
||||
mocked_target = MagicMock()
|
||||
empty_list = []
|
||||
|
||||
# WHEN: The empty list is added to the mocked target
|
||||
add_actions(mocked_target, empty_list)
|
||||
|
||||
# THEN: The add method on the mocked target is never called
|
||||
self.assertEqual(0, mocked_target.addSeparator.call_count, 'addSeparator method should not have been called')
|
||||
self.assertEqual(0, mocked_target.addAction.call_count, 'addAction method should not have been called')
|
||||
|
||||
def add_actions_none_action_test(self):
|
||||
"""
|
||||
Test that a separator is added when a None action is in the list
|
||||
"""
|
||||
# GIVEN: a mocked action list, and a list with None in it
|
||||
mocked_target = MagicMock()
|
||||
separator_list = [None]
|
||||
|
||||
# WHEN: The list is added to the mocked target
|
||||
add_actions(mocked_target, separator_list)
|
||||
|
||||
# THEN: The addSeparator method is called, but the addAction method is never called
|
||||
mocked_target.addSeparator.assert_called_with()
|
||||
self.assertEqual(0, mocked_target.addAction.call_count, 'addAction method should not have been called')
|
||||
|
||||
def add_actions_add_action_test(self):
|
||||
"""
|
||||
Test that an action is added when a valid action is in the list
|
||||
"""
|
||||
# GIVEN: a mocked action list, and a list with an action in it
|
||||
mocked_target = MagicMock()
|
||||
action_list = ['action']
|
||||
|
||||
# WHEN: The list is added to the mocked target
|
||||
add_actions(mocked_target, action_list)
|
||||
|
||||
# THEN: The addSeparator method is not called, and the addAction method is called
|
||||
self.assertEqual(0, mocked_target.addSeparator.call_count, 'addSeparator method should not have been called')
|
||||
mocked_target.addAction.assert_called_with('action')
|
||||
|
||||
def add_actions_action_and_none_test(self):
|
||||
"""
|
||||
Test that an action and a separator are added when a valid action and None are in the list
|
||||
"""
|
||||
# GIVEN: a mocked action list, and a list with an action and None in it
|
||||
mocked_target = MagicMock()
|
||||
action_list = ['action', None]
|
||||
|
||||
# WHEN: The list is added to the mocked target
|
||||
add_actions(mocked_target, action_list)
|
||||
|
||||
# THEN: The addSeparator method is called, and the addAction method is called
|
||||
mocked_target.addSeparator.assert_called_with()
|
||||
mocked_target.addAction.assert_called_with('action')
|
||||
|
||||
def get_filesystem_encoding_sys_function_not_called_test(self):
|
||||
"""
|
||||
Test the get_filesystem_encoding() function does not call the sys.getdefaultencoding() function
|
||||
@ -153,3 +213,211 @@ class TestUtils(TestCase):
|
||||
|
||||
# THEN: We get a properly sorted list
|
||||
self.assertEqual(['1st item', 'item 3b', 'item 10a'], sorted_list, 'Numbers should be sorted naturally')
|
||||
|
||||
def get_uno_instance_pipe_test(self):
|
||||
"""
|
||||
Test that when the UNO connection type is "pipe" the resolver is given the "pipe" URI
|
||||
"""
|
||||
# GIVEN: A mock resolver object and UNO_CONNECTION_TYPE is "pipe"
|
||||
mock_resolver = MagicMock()
|
||||
|
||||
# WHEN: get_uno_instance() is called
|
||||
get_uno_instance(mock_resolver)
|
||||
|
||||
# THEN: the resolve method is called with the correct argument
|
||||
mock_resolver.resolve.assert_called_with('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
|
||||
|
||||
def get_user_agent_linux_test(self):
|
||||
"""
|
||||
Test that getting a user agent on Linux returns a user agent suitable for Linux
|
||||
"""
|
||||
with patch('openlp.core.utils.sys') as mocked_sys:
|
||||
|
||||
# GIVEN: The system is Linux
|
||||
mocked_sys.platform = 'linux2'
|
||||
|
||||
# WHEN: We call _get_user_agent()
|
||||
user_agent = _get_user_agent()
|
||||
|
||||
# THEN: The user agent is a Linux (or ChromeOS) user agent
|
||||
result = 'Linux' in user_agent or 'CrOS' in user_agent
|
||||
self.assertTrue(result, u'The user agent should be a valid Linux user agent')
|
||||
|
||||
def get_user_agent_windows_test(self):
|
||||
"""
|
||||
Test that getting a user agent on Windows returns a user agent suitable for Windows
|
||||
"""
|
||||
with patch('openlp.core.utils.sys') as mocked_sys:
|
||||
|
||||
# GIVEN: The system is Linux
|
||||
mocked_sys.platform = 'win32'
|
||||
|
||||
# WHEN: We call _get_user_agent()
|
||||
user_agent = _get_user_agent()
|
||||
|
||||
# THEN: The user agent is a Linux (or ChromeOS) user agent
|
||||
self.assertIn('Windows', user_agent, u'The user agent should be a valid Windows user agent')
|
||||
|
||||
def get_user_agent_macos_test(self):
|
||||
"""
|
||||
Test that getting a user agent on OS X returns a user agent suitable for OS X
|
||||
"""
|
||||
with patch('openlp.core.utils.sys') as mocked_sys:
|
||||
|
||||
# GIVEN: The system is Linux
|
||||
mocked_sys.platform = 'darwin'
|
||||
|
||||
# WHEN: We call _get_user_agent()
|
||||
user_agent = _get_user_agent()
|
||||
|
||||
# THEN: The user agent is a Linux (or ChromeOS) user agent
|
||||
self.assertIn('Mac OS X', user_agent, u'The user agent should be a valid OS X user agent')
|
||||
|
||||
def get_user_agent_default_test(self):
|
||||
"""
|
||||
Test that getting a user agent on a non-Linux/Windows/OS X platform returns the default user agent
|
||||
"""
|
||||
with patch('openlp.core.utils.sys') as mocked_sys:
|
||||
|
||||
# GIVEN: The system is Linux
|
||||
mocked_sys.platform = 'freebsd'
|
||||
|
||||
# WHEN: We call _get_user_agent()
|
||||
user_agent = _get_user_agent()
|
||||
|
||||
# THEN: The user agent is a Linux (or ChromeOS) user agent
|
||||
self.assertIn('NetBSD', user_agent, u'The user agent should be the default user agent')
|
||||
|
||||
def get_web_page_no_url_test(self):
|
||||
"""
|
||||
Test that sending a URL of None to the get_web_page method returns None
|
||||
"""
|
||||
# GIVEN: A None url
|
||||
test_url = None
|
||||
|
||||
# WHEN: We try to get the test URL
|
||||
result = get_web_page(test_url)
|
||||
|
||||
# THEN: None should be returned
|
||||
self.assertIsNone(result, 'The return value of get_web_page should be None')
|
||||
|
||||
def get_web_page_test(self):
|
||||
"""
|
||||
Test that the get_web_page method works correctly
|
||||
"""
|
||||
with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
|
||||
patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
|
||||
patch('openlp.core.utils._get_user_agent') as mock_get_user_agent, \
|
||||
patch('openlp.core.utils.Registry') as MockRegistry:
|
||||
# GIVEN: Mocked out objects and a fake URL
|
||||
mocked_request_object = MagicMock()
|
||||
MockRequest.return_value = mocked_request_object
|
||||
mocked_page_object = MagicMock()
|
||||
mock_urlopen.return_value = mocked_page_object
|
||||
mock_get_user_agent.return_value = 'user_agent'
|
||||
fake_url = 'this://is.a.fake/url'
|
||||
|
||||
# WHEN: The get_web_page() method is called
|
||||
returned_page = get_web_page(fake_url)
|
||||
|
||||
# THEN: The correct methods are called with the correct arguments and a web page is returned
|
||||
MockRequest.assert_called_with(fake_url)
|
||||
mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
|
||||
self.assertEqual(1, mocked_request_object.add_header.call_count,
|
||||
'There should only be 1 call to add_header')
|
||||
mock_get_user_agent.assert_called_with()
|
||||
mock_urlopen.assert_called_with(mocked_request_object)
|
||||
mocked_page_object.geturl.assert_called_with()
|
||||
self.assertEqual(0, MockRegistry.call_count, 'The Registry() object should have never been called')
|
||||
self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
|
||||
|
||||
def get_web_page_with_header_test(self):
|
||||
"""
|
||||
Test that adding a header to the call to get_web_page() adds the header to the request
|
||||
"""
|
||||
with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
|
||||
patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
|
||||
patch('openlp.core.utils._get_user_agent') as mock_get_user_agent:
|
||||
# GIVEN: Mocked out objects, a fake URL and a fake header
|
||||
mocked_request_object = MagicMock()
|
||||
MockRequest.return_value = mocked_request_object
|
||||
mocked_page_object = MagicMock()
|
||||
mock_urlopen.return_value = mocked_page_object
|
||||
mock_get_user_agent.return_value = 'user_agent'
|
||||
fake_url = 'this://is.a.fake/url'
|
||||
fake_header = ('Fake-Header', 'fake value')
|
||||
|
||||
# WHEN: The get_web_page() method is called
|
||||
returned_page = get_web_page(fake_url, header=fake_header)
|
||||
|
||||
# THEN: The correct methods are called with the correct arguments and a web page is returned
|
||||
MockRequest.assert_called_with(fake_url)
|
||||
mocked_request_object.add_header.assert_called_with(fake_header[0], fake_header[1])
|
||||
self.assertEqual(2, mocked_request_object.add_header.call_count,
|
||||
'There should only be 2 calls to add_header')
|
||||
mock_get_user_agent.assert_called_with()
|
||||
mock_urlopen.assert_called_with(mocked_request_object)
|
||||
mocked_page_object.geturl.assert_called_with()
|
||||
self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
|
||||
|
||||
def get_web_page_with_user_agent_in_headers_test(self):
|
||||
"""
|
||||
Test that adding a user agent in the header when calling get_web_page() adds that user agent to the request
|
||||
"""
|
||||
with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
|
||||
patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
|
||||
patch('openlp.core.utils._get_user_agent') as mock_get_user_agent:
|
||||
# GIVEN: Mocked out objects, a fake URL and a fake header
|
||||
mocked_request_object = MagicMock()
|
||||
MockRequest.return_value = mocked_request_object
|
||||
mocked_page_object = MagicMock()
|
||||
mock_urlopen.return_value = mocked_page_object
|
||||
fake_url = 'this://is.a.fake/url'
|
||||
user_agent_header = ('User-Agent', 'OpenLP/2.1.0')
|
||||
|
||||
# WHEN: The get_web_page() method is called
|
||||
returned_page = get_web_page(fake_url, header=user_agent_header)
|
||||
|
||||
# THEN: The correct methods are called with the correct arguments and a web page is returned
|
||||
MockRequest.assert_called_with(fake_url)
|
||||
mocked_request_object.add_header.assert_called_with(user_agent_header[0], user_agent_header[1])
|
||||
self.assertEqual(1, mocked_request_object.add_header.call_count,
|
||||
'There should only be 1 call to add_header')
|
||||
self.assertEqual(0, mock_get_user_agent.call_count, '_get_user_agent should not have been called')
|
||||
mock_urlopen.assert_called_with(mocked_request_object)
|
||||
mocked_page_object.geturl.assert_called_with()
|
||||
self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
|
||||
|
||||
def get_web_page_update_openlp_test(self):
|
||||
"""
|
||||
Test that passing "update_openlp" as true to get_web_page calls Registry().get('app').process_events()
|
||||
"""
|
||||
with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
|
||||
patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
|
||||
patch('openlp.core.utils._get_user_agent') as mock_get_user_agent, \
|
||||
patch('openlp.core.utils.Registry') as MockRegistry:
|
||||
# GIVEN: Mocked out objects, a fake URL
|
||||
mocked_request_object = MagicMock()
|
||||
MockRequest.return_value = mocked_request_object
|
||||
mocked_page_object = MagicMock()
|
||||
mock_urlopen.return_value = mocked_page_object
|
||||
mock_get_user_agent.return_value = 'user_agent'
|
||||
mocked_registry_object = MagicMock()
|
||||
mocked_application_object = MagicMock()
|
||||
mocked_registry_object.get.return_value = mocked_application_object
|
||||
MockRegistry.return_value = mocked_registry_object
|
||||
fake_url = 'this://is.a.fake/url'
|
||||
|
||||
# WHEN: The get_web_page() method is called
|
||||
returned_page = get_web_page(fake_url, update_openlp=True)
|
||||
|
||||
# THEN: The correct methods are called with the correct arguments and a web page is returned
|
||||
MockRequest.assert_called_with(fake_url)
|
||||
mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
|
||||
self.assertEqual(1, mocked_request_object.add_header.call_count,
|
||||
'There should only be 1 call to add_header')
|
||||
mock_urlopen.assert_called_with(mocked_request_object)
|
||||
mocked_page_object.geturl.assert_called_with()
|
||||
mocked_registry_object.get.assert_called_with('application')
|
||||
mocked_application_object.process_events.assert_called_with()
|
||||
self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
|
||||
|
180
tests/functional/openlp_plugins/bibles/test_http.py
Normal file
180
tests/functional/openlp_plugins/bibles/test_http.py
Normal file
@ -0,0 +1,180 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 http module of the Bibles plugin.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from tests.functional import patch, MagicMock
|
||||
from openlp.plugins.bibles.lib.http import BSExtract
|
||||
|
||||
#TODO: Items left to test
|
||||
# BGExtract
|
||||
# __init__
|
||||
# _remove_elements
|
||||
# _extract_verse
|
||||
# _clean_soup
|
||||
# _extract_verses
|
||||
# _extract_verses_old
|
||||
# get_bible_chapter
|
||||
# get_books_from_http
|
||||
# _get_application
|
||||
# CWExtract
|
||||
# __init__
|
||||
# get_bible_chapter
|
||||
# get_books_from_http
|
||||
# _get_application
|
||||
# HTTPBible
|
||||
# __init__
|
||||
# do_import
|
||||
# get_verses
|
||||
# get_chapter
|
||||
# get_books
|
||||
# get_chapter_count
|
||||
# get_verse_count
|
||||
# _get_application
|
||||
# get_soup_for_bible_ref
|
||||
# send_error_message
|
||||
|
||||
class TestBSExtract(TestCase):
|
||||
"""
|
||||
Test the BSExtractClass
|
||||
"""
|
||||
#TODO: Items left to test
|
||||
# BSExtract
|
||||
# __init__
|
||||
# get_bible_chapter
|
||||
# get_books_from_http
|
||||
# _get_application
|
||||
def setUp(self):
|
||||
self.get_soup_for_bible_ref_patcher = patch('openlp.plugins.bibles.lib.http.get_soup_for_bible_ref')
|
||||
self.log_patcher = patch('openlp.plugins.bibles.lib.http.log')
|
||||
self.send_error_message_patcher = patch('openlp.plugins.bibles.lib.http.send_error_message')
|
||||
self.socket_patcher = patch('openlp.plugins.bibles.lib.http.socket')
|
||||
self.urllib_patcher = patch('openlp.plugins.bibles.lib.http.urllib')
|
||||
|
||||
self.mock_get_soup_for_bible_ref = self.get_soup_for_bible_ref_patcher.start()
|
||||
self.mock_log = self.log_patcher.start()
|
||||
self.mock_send_error_message = self.send_error_message_patcher.start()
|
||||
self.mock_socket = self.socket_patcher.start()
|
||||
self.mock_soup = MagicMock()
|
||||
self.mock_urllib = self.urllib_patcher.start()
|
||||
|
||||
def tearDown(self):
|
||||
self.get_soup_for_bible_ref_patcher.stop()
|
||||
self.log_patcher.stop()
|
||||
self.send_error_message_patcher.stop()
|
||||
self.socket_patcher.stop()
|
||||
self.urllib_patcher.stop()
|
||||
|
||||
def get_books_from_http_no_soup_test(self):
|
||||
"""
|
||||
Test the get_books_from_http method when get_soup_for_bible_ref returns a falsey value
|
||||
"""
|
||||
# GIVEN: An instance of BSExtract, and reset log, urllib & get_soup_for_bible_ref mocks
|
||||
instance = BSExtract()
|
||||
self.mock_log.debug.reset_mock()
|
||||
self.mock_urllib.reset_mock()
|
||||
self.mock_get_soup_for_bible_ref.reset_mock()
|
||||
|
||||
# WHEN: get_books_from_http is called with 'NIV' and get_soup_for_bible_ref returns a None value
|
||||
self.mock_urllib.parse.quote.return_value = 'NIV'
|
||||
self.mock_get_soup_for_bible_ref.return_value = None
|
||||
result = instance.get_books_from_http('NIV')
|
||||
|
||||
# THEN: The rest mocks should be called with known values and get_books_from_http should return None
|
||||
self.mock_log.debug.assert_called_once_with('BSExtract.get_books_from_http("%s")', 'NIV')
|
||||
self.mock_urllib.parse.quote.assert_called_once_with(b'NIV')
|
||||
self.mock_get_soup_for_bible_ref.assert_called_once_with(
|
||||
'http://m.bibleserver.com/overlay/selectBook?translation=NIV')
|
||||
self.assertIsNone(result,
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value')
|
||||
|
||||
def get_books_from_http_no_content_test(self):
|
||||
"""
|
||||
Test the get_books_from_http method when the specified element cannot be found in the tag object returned from
|
||||
get_soup_for_bible_ref
|
||||
"""
|
||||
# GIVEN: An instance of BSExtract, and reset log, urllib, get_soup_for_bible_ref & soup mocks
|
||||
instance = BSExtract()
|
||||
self.mock_log.reset_mock()
|
||||
self.mock_urllib.reset_mock()
|
||||
self.mock_get_soup_for_bible_ref.reset_mock()
|
||||
self.mock_soup.reset_mock()
|
||||
|
||||
# WHEN: get_books_from_http is called with 'NIV', get_soup_for_bible_ref returns a mocked_soup object and
|
||||
# mocked_soup.find returns None
|
||||
self.mock_urllib.parse.quote.return_value = 'NIV'
|
||||
self.mock_soup.find.return_value = None
|
||||
self.mock_get_soup_for_bible_ref.return_value = self.mock_soup
|
||||
result = instance.get_books_from_http('NIV')
|
||||
|
||||
# THEN: The rest mocks should be called with known values and get_books_from_http should return None
|
||||
self.mock_log.debug.assert_called_once_with('BSExtract.get_books_from_http("%s")', 'NIV')
|
||||
self.mock_urllib.parse.quote.assert_called_once_with(b'NIV')
|
||||
self.mock_get_soup_for_bible_ref.assert_called_once_with(
|
||||
'http://m.bibleserver.com/overlay/selectBook?translation=NIV')
|
||||
self.mock_soup.find.assert_called_once_with('ul')
|
||||
self.mock_log.error.assert_called_once_with('No books found in the Bibleserver response.')
|
||||
self.mock_send_error_message.assert_called_once_with('parse')
|
||||
self.assertIsNone(result,
|
||||
'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value')
|
||||
|
||||
def get_books_from_http_content_test(self):
|
||||
"""
|
||||
Test the get_books_from_http method with sample HTML
|
||||
Also a regression test for bug #1184869. (The anchor tag in the second list item is empty)
|
||||
"""
|
||||
# GIVEN: An instance of BSExtract, and reset log, urllib & get_soup_for_bible_ref mocks and sample HTML data
|
||||
self.test_html = '<ul><li><a href="/overlay/selectChapter?tocBook=1">Genesis</a></li>' \
|
||||
'<li><a href="/overlay/selectChapter?tocBook=2"></a></li>' \
|
||||
'<li><a href="/overlay/selectChapter?tocBook=3">Leviticus</a></li></ul>'
|
||||
self.test_soup = BeautifulSoup(self.test_html)
|
||||
instance = BSExtract()
|
||||
self.mock_log.reset_mock()
|
||||
self.mock_urllib.reset_mock()
|
||||
self.mock_get_soup_for_bible_ref.reset_mock()
|
||||
self.mock_send_error_message.reset_mock()
|
||||
|
||||
# WHEN: get_books_from_http is called with 'NIV' and get_soup_for_bible_ref returns tag object based on the
|
||||
# supplied test data.
|
||||
self.mock_urllib.parse.quote.return_value = 'NIV'
|
||||
self.mock_get_soup_for_bible_ref.return_value = self.test_soup
|
||||
result = instance.get_books_from_http('NIV')
|
||||
|
||||
# THEN: The rest mocks should be called with known values and get_books_from_http should return the two books
|
||||
# in the test data
|
||||
self.mock_log.debug.assert_called_once_with('BSExtract.get_books_from_http("%s")', 'NIV')
|
||||
self.mock_urllib.parse.quote.assert_called_once_with(b'NIV')
|
||||
self.mock_get_soup_for_bible_ref.assert_called_once_with(
|
||||
'http://m.bibleserver.com/overlay/selectBook?translation=NIV')
|
||||
self.assertFalse(self.mock_log.error.called, 'log.error should not have been called')
|
||||
self.assertFalse(self.mock_send_error_message.called, 'send_error_message should not have been called')
|
||||
self.assertEquals(result, ['Genesis', 'Leviticus'])
|
@ -1,165 +1,181 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
Functional tests to test the PresentationController and PresentationDocument
|
||||
classes and related methods.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
import os
|
||||
from mock import MagicMock, patch, mock_open
|
||||
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
||||
|
||||
class TestLibModule(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
mocked_plugin = MagicMock()
|
||||
mocked_plugin.settings_section = 'presentations'
|
||||
self.presentation = PresentationController(mocked_plugin)
|
||||
self.document = PresentationDocument(self.presentation, '')
|
||||
|
||||
def save_titles_and_notes_test(self):
|
||||
"""
|
||||
Test PresentationDocument.save_titles_and_notes method with two valid lists
|
||||
"""
|
||||
# GIVEN: two lists of length==2 and a mocked open and get_thumbnail_folder
|
||||
mocked_open = mock_open()
|
||||
with patch('builtins.open', mocked_open), \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder:
|
||||
titles = ['uno', 'dos']
|
||||
notes = ['one', 'two']
|
||||
# WHEN: calling save_titles_and_notes
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
self.document.save_titles_and_notes(titles, notes)
|
||||
# THEN: the last call to open should have been for slideNotes2.txt
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'titles.txt'), mode='w')
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'slideNotes1.txt'), mode='w')
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'slideNotes2.txt'), mode='w')
|
||||
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')
|
||||
|
||||
def save_titles_and_notes_with_None_test(self):
|
||||
"""
|
||||
Test PresentationDocument.save_titles_and_notes method with no data
|
||||
"""
|
||||
# GIVEN: None and an empty list and a mocked open and get_thumbnail_folder
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder:
|
||||
titles = None
|
||||
notes = None
|
||||
# WHEN: calling save_titles_and_notes
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
self.document.save_titles_and_notes(titles, notes)
|
||||
# THEN: No file should have been created
|
||||
self.assertEqual(mocked_open.call_count, 0,
|
||||
'No file should be created')
|
||||
|
||||
|
||||
def get_titles_and_notes_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open', mock_open(read_data='uno\ndos\n')) as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = True
|
||||
# WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two items for the titles and two empty strings for the notes
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be of type list')
|
||||
self.assertEqual(len(result_titles), 2,
|
||||
'There should be two items in the titles')
|
||||
self.assertIs(type(result_notes), list,
|
||||
'result_notes should be of type list')
|
||||
self.assertEqual(len(result_notes), 2,
|
||||
'There should be two items in the notes')
|
||||
self.assertEqual(mocked_open.call_count, 3,
|
||||
'Three files should be opened')
|
||||
mocked_open.assert_any_call(os.path.join('test', 'titles.txt'))
|
||||
mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'))
|
||||
mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'))
|
||||
self.assertEqual(mocked_exists.call_count, 3,
|
||||
'Three files should have been checked')
|
||||
|
||||
def get_titles_and_notes_with_file_not_found_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method with file not found
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = False
|
||||
#WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two empty lists
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be of type list')
|
||||
self.assertEqual(len(result_titles), 0,
|
||||
'there be no titles')
|
||||
self.assertIs(type(result_notes), list,
|
||||
'result_notes should be a list')
|
||||
self.assertEqual(len(result_notes), 0,
|
||||
'but the list should be empty')
|
||||
self.assertEqual(mocked_open.call_count, 0,
|
||||
'No calls to open files')
|
||||
self.assertEqual(mocked_exists.call_count, 1,
|
||||
'There should be one call to file exists')
|
||||
|
||||
def get_titles_and_notes_with_file_error_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method with file errors
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = True
|
||||
mocked_open.side_effect = IOError()
|
||||
# WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two empty lists
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be a list')
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
Functional tests to test the PresentationController and PresentationDocument
|
||||
classes and related methods.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
import os
|
||||
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
||||
from tests.functional import MagicMock, patch, mock_open
|
||||
|
||||
class TestPresentationController(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
mocked_plugin = MagicMock()
|
||||
mocked_plugin.settings_section = 'presentations'
|
||||
self.presentation = PresentationController(mocked_plugin)
|
||||
self.document = PresentationDocument(self.presentation, '')
|
||||
|
||||
|
||||
"""
|
||||
Test the PresentationController.
|
||||
"""
|
||||
def constructor_test(self):
|
||||
"""
|
||||
Test the Constructor
|
||||
"""
|
||||
# GIVEN: A mocked plugin
|
||||
|
||||
# WHEN: The PresentationController is created
|
||||
|
||||
# THEN: The name of the presentation controller should be correct
|
||||
self.assertEqual('PresentationController', self.presentation.name,
|
||||
'The name of the presentation controller should be correct')
|
||||
|
||||
def save_titles_and_notes_test(self):
|
||||
"""
|
||||
Test PresentationDocument.save_titles_and_notes method with two valid lists
|
||||
"""
|
||||
# GIVEN: two lists of length==2 and a mocked open and get_thumbnail_folder
|
||||
mocked_open = mock_open()
|
||||
with patch('builtins.open', mocked_open), \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder:
|
||||
titles = ['uno', 'dos']
|
||||
notes = ['one', 'two']
|
||||
# WHEN: calling save_titles_and_notes
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
self.document.save_titles_and_notes(titles, notes)
|
||||
# THEN: the last call to open should have been for slideNotes2.txt
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'titles.txt'), mode='w')
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'slideNotes1.txt'), mode='w')
|
||||
mocked_open.assert_any_call(
|
||||
os.path.join('test', 'slideNotes2.txt'), mode='w')
|
||||
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')
|
||||
|
||||
def save_titles_and_notes_with_None_test(self):
|
||||
"""
|
||||
Test PresentationDocument.save_titles_and_notes method with no data
|
||||
"""
|
||||
# GIVEN: None and an empty list and a mocked open and get_thumbnail_folder
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder:
|
||||
titles = None
|
||||
notes = None
|
||||
# WHEN: calling save_titles_and_notes
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
self.document.save_titles_and_notes(titles, notes)
|
||||
# THEN: No file should have been created
|
||||
self.assertEqual(mocked_open.call_count, 0,
|
||||
'No file should be created')
|
||||
|
||||
|
||||
def get_titles_and_notes_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open', mock_open(read_data='uno\ndos\n')) as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = True
|
||||
# WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two items for the titles and two empty strings for the notes
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be of type list')
|
||||
self.assertEqual(len(result_titles), 2,
|
||||
'There should be two items in the titles')
|
||||
self.assertIs(type(result_notes), list,
|
||||
'result_notes should be of type list')
|
||||
self.assertEqual(len(result_notes), 2,
|
||||
'There should be two items in the notes')
|
||||
self.assertEqual(mocked_open.call_count, 3,
|
||||
'Three files should be opened')
|
||||
mocked_open.assert_any_call(os.path.join('test', 'titles.txt'))
|
||||
mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'))
|
||||
mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'))
|
||||
self.assertEqual(mocked_exists.call_count, 3,
|
||||
'Three files should have been checked')
|
||||
|
||||
def get_titles_and_notes_with_file_not_found_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method with file not found
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = False
|
||||
#WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two empty lists
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be of type list')
|
||||
self.assertEqual(len(result_titles), 0,
|
||||
'there be no titles')
|
||||
self.assertIs(type(result_notes), list,
|
||||
'result_notes should be a list')
|
||||
self.assertEqual(len(result_notes), 0,
|
||||
'but the list should be empty')
|
||||
self.assertEqual(mocked_open.call_count, 0,
|
||||
'No calls to open files')
|
||||
self.assertEqual(mocked_exists.call_count, 1,
|
||||
'There should be one call to file exists')
|
||||
|
||||
def get_titles_and_notes_with_file_error_test(self):
|
||||
"""
|
||||
Test PresentationDocument.get_titles_and_notes method with file errors
|
||||
"""
|
||||
# GIVEN: A mocked open, get_thumbnail_folder and exists
|
||||
with patch('builtins.open') as mocked_open, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') \
|
||||
as mocked_get_thumbnail_folder, \
|
||||
patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists:
|
||||
mocked_get_thumbnail_folder.return_value = 'test'
|
||||
mocked_exists.return_value = True
|
||||
mocked_open.side_effect = IOError()
|
||||
# WHEN: calling get_titles_and_notes
|
||||
result_titles, result_notes = self.document.get_titles_and_notes()
|
||||
# THEN: it should return two empty lists
|
||||
self.assertIs(type(result_titles), list,
|
||||
'result_titles should be a list')
|
||||
|
||||
|
@ -39,9 +39,8 @@ from PyQt4 import QtGui
|
||||
from openlp.core.lib import Registry
|
||||
from openlp.core.common import Settings
|
||||
from openlp.plugins.remotes.lib.httpserver import HttpRouter
|
||||
from tests.functional import MagicMock, patch
|
||||
from mock import mock_open
|
||||
from urllib.parse import urlparse
|
||||
from tests.functional import MagicMock, patch, mock_open
|
||||
|
||||
__default_settings__ = {
|
||||
'remotes/twelve hour': True,
|
||||
@ -56,6 +55,7 @@ __default_settings__ = {
|
||||
|
||||
TEST_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class TestRouter(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`lib` module.
|
||||
@ -94,7 +94,7 @@ class TestRouter(TestCase):
|
||||
|
||||
# THEN: the function should return the correct password
|
||||
self.assertEqual(router.auth, test_value,
|
||||
'The result for make_sha_hash should return the correct encrypted password')
|
||||
'The result for make_sha_hash should return the correct encrypted password')
|
||||
|
||||
def process_http_request_test(self):
|
||||
"""
|
||||
@ -112,10 +112,8 @@ class TestRouter(TestCase):
|
||||
function, args = router.process_http_request('/stage/api/poll', None)
|
||||
|
||||
# THEN: the function should have been called only once
|
||||
assert function['function'] == mocked_function, \
|
||||
'The mocked function should match defined value.'
|
||||
assert function['secure'] == False, \
|
||||
'The mocked function should not require any security.'
|
||||
self.assertEqual(mocked_function, function['function'], 'The mocked function should match defined value.')
|
||||
self.assertFalse(function['secure'], 'The mocked function should not require any security.')
|
||||
|
||||
def get_content_type_test(self):
|
||||
"""
|
||||
@ -127,10 +125,12 @@ class TestRouter(TestCase):
|
||||
['test.gif', 'image/gif'], ['test.ico', 'image/x-icon'],
|
||||
['test.png', 'image/png'], ['test.whatever', 'text/plain'],
|
||||
['test', 'text/plain'], ['', 'text/plain'],
|
||||
[os.path.join(TEST_PATH,'test.html'), 'text/html']]
|
||||
[os.path.join(TEST_PATH, 'test.html'), 'text/html']]
|
||||
|
||||
# WHEN: calling each file type
|
||||
for header in headers:
|
||||
ext, content_type = self.router.get_content_type(header[0])
|
||||
|
||||
# THEN: all types should match
|
||||
self.assertEqual(content_type, header[1], 'Mismatch of content type')
|
||||
|
||||
@ -145,13 +145,14 @@ class TestRouter(TestCase):
|
||||
self.router.wfile = MagicMock()
|
||||
self.router.html_dir = os.path.normpath('test/dir')
|
||||
self.router.template_vars = MagicMock()
|
||||
|
||||
# WHEN: call serve_file with no file_name
|
||||
self.router.serve_file()
|
||||
|
||||
# THEN: it should return a 404
|
||||
self.router.send_response.assert_called_once_with(404)
|
||||
self.router.send_header.assert_called_once_with('Content-type','text/html')
|
||||
self.assertEqual(self.router.end_headers.call_count, 1,
|
||||
'end_headers called once')
|
||||
self.assertEqual(self.router.end_headers.call_count, 1, 'end_headers called once')
|
||||
|
||||
def serve_file_with_valid_params_test(self):
|
||||
"""
|
||||
@ -165,16 +166,16 @@ class TestRouter(TestCase):
|
||||
self.router.html_dir = os.path.normpath('test/dir')
|
||||
self.router.template_vars = MagicMock()
|
||||
with patch('openlp.core.lib.os.path.exists') as mocked_exists, \
|
||||
patch('builtins.open', mock_open(read_data='123')):
|
||||
patch('builtins.open', mock_open(read_data='123')):
|
||||
mocked_exists.return_value = True
|
||||
|
||||
# WHEN: call serve_file with an existing html file
|
||||
self.router.serve_file(os.path.normpath('test/dir/test.html'))
|
||||
|
||||
# THEN: it should return a 200 and the file
|
||||
self.router.send_response.assert_called_once_with(200)
|
||||
self.router.send_header.assert_called_once_with(
|
||||
'Content-type','text/html')
|
||||
self.assertEqual(self.router.end_headers.call_count, 1,
|
||||
'end_headers called once')
|
||||
self.router.send_header.assert_called_once_with('Content-type', 'text/html')
|
||||
self.assertEqual(self.router.end_headers.call_count, 1, 'end_headers called once')
|
||||
|
||||
def serve_thumbnail_without_params_test(self):
|
||||
"""
|
||||
|
99
tests/interfaces/openlp_core_ui/test_thememanagerhelper.py
Normal file
99
tests/interfaces/openlp_core_ui/test_thememanagerhelper.py
Normal file
@ -0,0 +1,99 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
Interface tests to test the thememanagerhelper class and related methods.
|
||||
"""
|
||||
import os
|
||||
from unittest import TestCase
|
||||
from tempfile import mkstemp
|
||||
|
||||
from openlp.core.common import Settings
|
||||
from openlp.core.ui import ThemeManagerHelper
|
||||
from tests.functional import patch, MagicMock
|
||||
|
||||
|
||||
class TestThemeManagerHelper(TestCase):
|
||||
"""
|
||||
Test the functions in the ThemeManagerHelp[er module
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Create the UI
|
||||
"""
|
||||
fd, self.ini_file = mkstemp('.ini')
|
||||
Settings().set_filename(self.ini_file)
|
||||
self.helper = ThemeManagerHelper()
|
||||
self.helper.settings_section = "themes"
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
Delete all the C++ objects at the end so that we don't have a segfault
|
||||
"""
|
||||
os.unlink(self.ini_file)
|
||||
os.unlink(Settings().fileName())
|
||||
|
||||
def test_initialise(self):
|
||||
"""
|
||||
Test the thememanagerhelper initialise - basic test
|
||||
"""
|
||||
# GIVEN: A new a call to initialise
|
||||
Settings().setValue('themes/global theme', 'my_theme')
|
||||
self.helper.build_theme_path = MagicMock()
|
||||
self.helper.load_first_time_themes = MagicMock()
|
||||
|
||||
# WHEN: the initialistion is run
|
||||
self.helper.initialise()
|
||||
|
||||
# THEN:
|
||||
self.assertEqual(1, self.helper.build_theme_path.call_count,
|
||||
'The function build_theme_path should have been called')
|
||||
self.assertEqual(1, self.helper.load_first_time_themes.call_count,
|
||||
'The function load_first_time_themes should have been called only once')
|
||||
self.assertEqual(self.helper.global_theme, 'my_theme',
|
||||
'The global theme should have been set to my_theme')
|
||||
|
||||
def test_build_theme_path(self):
|
||||
"""
|
||||
Test the thememanagerhelper build_theme_path - basic test
|
||||
"""
|
||||
# GIVEN: A new a call to initialise
|
||||
with patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists:
|
||||
# GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory()
|
||||
mocked_check_directory_exists.return_value = True
|
||||
Settings().setValue('themes/global theme', 'my_theme')
|
||||
|
||||
self.helper.theme_form = MagicMock()
|
||||
#self.helper.load_first_time_themes = MagicMock()
|
||||
|
||||
# WHEN: the build_theme_path is run
|
||||
self.helper.build_theme_path()
|
||||
|
||||
# THEN:
|
||||
self.assertEqual(self.helper.path, self.helper.theme_form.path,
|
||||
'The theme path and the main path should be the same value')
|
Loading…
Reference in New Issue
Block a user