Now with tests

This commit is contained in:
Raoul Snyman 2016-11-02 23:46:00 +02:00
parent 96246c991a
commit eb6945b6e9
2 changed files with 294 additions and 9 deletions

View File

@ -10,12 +10,24 @@ import time
# Add the vendor directory to sys.path so that we can load Pyro4 # Add the vendor directory to sys.path so that we can load Pyro4
sys.path.append(os.path.join(os.path.dirname(__file__), 'vendor')) sys.path.append(os.path.join(os.path.dirname(__file__), 'vendor'))
from Pyro4 import Daemon, expose
try:
# Wrap these imports in a try so that we can run the tests on macOS
import uno import uno
from com.sun.star.beans import PropertyValue from com.sun.star.beans import PropertyValue
from com.sun.star.task import ErrorCodeIOException from com.sun.star.task import ErrorCodeIOException
from Pyro4 import Daemon, expose, locateNS except:
# But they need to be defined for mocking
uno = None
PropertyValue = None
ErrorCodeIOException = Exception
if sys.platform.startswith('darwin') and uno is not None:
# Only make the log file on OS X when running as a server
logfile = os.path.join(str(os.getenv('HOME')), 'Library', 'Application Support', 'openlp', 'libreofficeserver.log')
logging.basicConfig(filename=logfile, level=logging.INFO)
logging.basicConfig(filename=os.path.dirname(__file__) + '/libreofficeserver.log', level=logging.INFO)
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -37,9 +49,9 @@ class LibreOfficeServer(object):
""" """
Set up the server Set up the server
""" """
self._control = None
self._desktop = None self._desktop = None
self._document = None self._document = None
self._control = None
self._presentation = None self._presentation = None
self._process = None self._process = None
@ -77,7 +89,7 @@ class LibreOfficeServer(object):
try: try:
self._manager = uno_instance.ServiceManager self._manager = uno_instance.ServiceManager
log.debug('get UNO Desktop Openoffice - createInstanceWithContext - Desktop') log.debug('get UNO Desktop Openoffice - createInstanceWithContext - Desktop')
self._desktop = self._manager.createInstanceWithContext("com.sun.star.frame.Desktop", uno_instance) self._desktop = self._manager.createInstanceWithContext('com.sun.star.frame.Desktop', uno_instance)
except Exception as e: except Exception as e:
log.warning('Failed to get UNO desktop') log.warning('Failed to get UNO desktop')
@ -109,9 +121,9 @@ class LibreOfficeServer(object):
for index in range(page.getCount()): for index in range(page.getCount()):
shape = page.getByIndex(index) shape = page.getByIndex(index)
shape_type = shape.getShapeType() shape_type = shape.getShapeType()
if shape.supportsService("com.sun.star.drawing.Text"): if shape.supportsService('com.sun.star.drawing.Text'):
# if they requested title, make sure it is the title # if they requested title, make sure it is the title
if text_type != TextType.Title or shape_type == "com.sun.star.presentation.TitleTextShape": if text_type != TextType.Title or shape_type == 'com.sun.star.presentation.TitleTextShape':
text += shape.getString() + '\n' text += shape.getString() + '\n'
return text return text

View File

@ -0,0 +1,273 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2016 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 #
###############################################################################
"""
Functional tests to test the LibreOffice Pyro server
"""
from unittest import TestCase
from openlp.plugins.presentations.lib.libreofficeserver import LibreOfficeServer, TextType
from tests.functional import MagicMock, patch, call
class TestLibreOfficeServer(TestCase):
"""
Test the LibreOfficeServer Class
"""
def test_constructor(self):
"""
Test the Constructor from the server
"""
# GIVEN: No server
# WHEN: The server object is created
server = LibreOfficeServer()
# THEN: The server should have been set up correctly
self.assertIsNone(server._control)
self.assertIsNone(server._desktop)
self.assertIsNone(server._document)
self.assertIsNone(server._presentation)
self.assertIsNone(server._process)
@patch('openlp.plugins.presentations.lib.libreofficeserver.Popen')
def test_start_process(self, MockedPopen):
"""
Test that the correct command is issued to run LibreOffice
"""
# GIVEN: A LOServer
mocked_process = MagicMock()
MockedPopen.return_value = mocked_process
server = LibreOfficeServer()
# WHEN: The start_process() method is run
server.start_process()
# THEN: The correct command line should run and the process should have started
MockedPopen.assert_called_with([
'/Applications/LibreOffice.app/Contents/MacOS/soffice',
'--nologo',
'--norestore',
'--minimized',
'--nodefault',
'--nofirststartwizard',
'--accept=pipe,name=openlp_pipe;urp;'
])
self.assertEqual(mocked_process, server._process)
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
def test_setup_desktop(self, mocked_uno):
"""
Test that setting up the desktop works correctly
"""
# GIVEN: A LibreOfficeServer instance
server = LibreOfficeServer()
mocked_context = MagicMock()
mocked_resolver = MagicMock()
mocked_uno_instance = MagicMock()
MockedServiceManager = MagicMock()
mocked_desktop = MagicMock()
mocked_uno.getComponentContext.return_value = mocked_context
mocked_context.ServiceManager.createInstanceWithContext.return_value = mocked_resolver
mocked_resolver.resolve.side_effect = [Exception, mocked_uno_instance]
mocked_uno_instance.ServiceManager = MockedServiceManager
MockedServiceManager.createInstanceWithContext.return_value = mocked_desktop
# WHEN: setup_desktop() is called
server.setup_desktop()
# THEN: A desktop object was created
mocked_uno.getComponentContext.assert_called_once_with()
mocked_context.ServiceManager.createInstanceWithContext.assert_called_once_with(
'com.sun.star.bridge.UnoUrlResolver', mocked_context)
self.assertEqual(
[
call('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext'),
call('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
],
mocked_resolver.resolve.call_args_list
)
MockedServiceManager.createInstanceWithContext.assert_called_once_with(
'com.sun.star.frame.Desktop', mocked_uno_instance)
self.assertEqual(MockedServiceManager, server._manager)
self.assertEqual(mocked_desktop, server._desktop)
@patch('openlp.plugins.presentations.lib.libreofficeserver.PropertyValue')
def test_create_property(self, MockedPropertyValue):
"""
Test that the _create_property() method works correctly
"""
# GIVEN: A server amnd property to set
server = LibreOfficeServer()
name = 'Hidden'
value = True
# WHEN: The _create_property() method is called
prop = server._create_property(name, value)
# THEN: The property should have the correct attributes
self.assertEqual(name, prop.Name)
self.assertEqual(value, prop.Value)
def test_get_text_from_page_slide_text(self):
"""
Test that the _get_text_from_page() method gives us nothing for slide text
"""
# GIVEN: A LibreOfficeServer object and some mocked objects
text_type = TextType.SlideText
slide_no = 1
server = LibreOfficeServer()
server._document = MagicMock()
mocked_pages = MagicMock()
mocked_page = MagicMock()
mocked_shape = MagicMock()
server._document.getDrawPages.return_value = mocked_pages
mocked_pages.getCount.return_value = 1
mocked_pages.getByIndex.return_value = mocked_page
mocked_page.getByIndex.return_value = mocked_shape
mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
mocked_shape.supportsService.return_value = True
mocked_shape.getString.return_value = 'Page Text'
# WHEN: _get_text_from_page() is run for slide text
text = server._get_text_from_page(slide_no, text_type)
# THE: The text is correct
self.assertEqual('Page Text\n', text)
def test_get_text_from_page_title(self):
"""
Test that the _get_text_from_page() method gives us the text from the titles
"""
# GIVEN: A LibreOfficeServer object and some mocked objects
text_type = TextType.Title
slide_no = 1
server = LibreOfficeServer()
server._document = MagicMock()
mocked_pages = MagicMock()
mocked_page = MagicMock()
mocked_shape = MagicMock()
server._document.getDrawPages.return_value = mocked_pages
mocked_pages.getCount.return_value = 1
mocked_pages.getByIndex.return_value = mocked_page
mocked_page.getByIndex.return_value = mocked_shape
mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
mocked_shape.supportsService.return_value = True
mocked_shape.getString.return_value = 'Page Title'
# WHEN: _get_text_from_page() is run for titles
text = server._get_text_from_page(slide_no, text_type)
# THEN: The text should be correct
self.assertEqual('Page Title\n', text)
def test_get_text_from_page_notes(self):
"""
Test that the _get_text_from_page() method gives us the text from the notes
"""
# GIVEN: A LibreOfficeServer object and some mocked objects
text_type = TextType.Notes
slide_no = 1
server = LibreOfficeServer()
server._document = MagicMock()
mocked_pages = MagicMock()
mocked_page = MagicMock()
mocked_notes_page = MagicMock()
mocked_shape = MagicMock()
server._document.getDrawPages.return_value = mocked_pages
mocked_pages.getCount.return_value = 1
mocked_pages.getByIndex.return_value = mocked_page
mocked_page.getNotesPage.return_value = mocked_notes_page
mocked_notes_page.getByIndex.return_value = mocked_shape
mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
mocked_shape.supportsService.return_value = True
mocked_shape.getString.return_value = 'Page Notes'
# WHEN: _get_text_from_page() is run for titles
text = server._get_text_from_page(slide_no, text_type)
# THEN: The text should be correct
self.assertEqual('Page Notes\n', text)
def test_has_desktop_no_desktop(self):
"""
Test the has_desktop() method when there's no desktop
"""
# GIVEN: A LibreOfficeServer object
server = LibreOfficeServer()
# WHEN: has_desktop() is called
result = server.has_desktop()
# THEN: The result should be False
self.assertFalse(result)
def test_has_desktop(self):
"""
Test the has_desktop() method
"""
# GIVEN: A LibreOfficeServer object and a desktop
server = LibreOfficeServer()
server._desktop = MagicMock()
# WHEN: has_desktop() is called
result = server.has_desktop()
# THEN: The result should be True
self.assertTrue(result)
def test_shutdown(self):
"""
Test the shutdown method
"""
# GIVEN: An up an running LibreOfficeServer
server = LibreOfficeServer()
mocked_doc = MagicMock()
mocked_desktop = MagicMock()
mocked_docs = MagicMock()
mocked_list = MagicMock()
mocked_element_doc = MagicMock()
server._docs = [mocked_doc]
server._desktop = mocked_desktop
server._process = MagicMock()
def close_docs():
server._docs = []
mocked_doc.close_presentation.side_effect = close_docs
mocked_desktop.getComponents.return_value = mocked_docs
mocked_docs.hasElements.return_value = True
mocked_docs.createEnumeration.return_value = mocked_list
mocked_list.hasMoreElements.side_effect = [True, False]
mocked_list.nextElement.return_value = mocked_element_doc
mocked_element_doc.getImplementationName.return_value = 'com.sun.star.comp.framework.BackingComp'
# WHEN: shutdown() is called
server.shutdown()
# THEN: The right methods are called and everything works
mocked_doc.close_presentation.assert_called_once_with()
mocked_desktop.getComponents.assert_called_once_with()
mocked_docs.hasElements.assert_called_once_with()
mocked_docs.createEnumeration.assert_called_once_with()
self.assertEqual(2, mocked_list.hasMoreElements.call_count)
mocked_list.nextElement.assert_called_once_with()
mocked_element_doc.getImplementationName.assert_called_once_with()
mocked_desktop.terminate.assert_called_once_with()
server._process.kill.assert_called_once_with()