~trb143/openlp/more_media

« back to all changes in this revision

Viewing changes to tests/functional/openlp_plugins/presentations/test_libreofficeserver.py

  • Committer: Tim Bentley
  • Date: 2019-06-11 18:08:21 UTC
  • mfrom: (2876.1.2 openlp)
  • Revision ID: tim.bentley@gmail.com-20190611180821-m0viu2wi93p2o97k
Head

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
 
3
 
 
4
##########################################################################
 
5
# OpenLP - Open Source Lyrics Projection                                 #
 
6
# ---------------------------------------------------------------------- #
 
7
# Copyright (c) 2008-2019 OpenLP Developers                              #
 
8
# ---------------------------------------------------------------------- #
 
9
# This program is free software: you can redistribute it and/or modify   #
 
10
# it under the terms of the GNU General Public License as published by   #
 
11
# the Free Software Foundation, either version 3 of the License, or      #
 
12
# (at your option) any later version.                                    #
 
13
#                                                                        #
 
14
# This program is distributed in the hope that it will be useful,        #
 
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of         #
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
 
17
# GNU General Public License for more details.                           #
 
18
#                                                                        #
 
19
# You should have received a copy of the GNU General Public License      #
 
20
# along with this program.  If not, see <https://www.gnu.org/licenses/>. #
 
21
##########################################################################
 
22
"""
 
23
Functional tests to test the LibreOffice Pyro server
 
24
"""
 
25
from unittest.mock import MagicMock, patch, call
 
26
 
 
27
from openlp.plugins.presentations.lib.libreofficeserver import LibreOfficeServer, TextType, main
 
28
 
 
29
 
 
30
def test_constructor():
 
31
    """
 
32
    Test the Constructor from the server
 
33
    """
 
34
    # GIVEN: No server
 
35
    # WHEN: The server object is created
 
36
    server = LibreOfficeServer()
 
37
 
 
38
    # THEN: The server should have been set up correctly
 
39
    assert server._control is None
 
40
    # assert server._desktop is None
 
41
    assert server._document is None
 
42
    assert server._presentation is None
 
43
    assert server._process is None
 
44
 
 
45
 
 
46
@patch('openlp.plugins.presentations.lib.libreofficeserver.Popen')
 
47
def test_start_process(MockedPopen):
 
48
    """
 
49
    Test that the correct command is issued to run LibreOffice
 
50
    """
 
51
    # GIVEN: A LOServer
 
52
    mocked_process = MagicMock()
 
53
    MockedPopen.return_value = mocked_process
 
54
    server = LibreOfficeServer()
 
55
 
 
56
    # WHEN: The start_process() method is run
 
57
    server.start_process()
 
58
 
 
59
    # THEN: The correct command line should run and the process should have started
 
60
    MockedPopen.assert_called_with([
 
61
        '/Applications/LibreOffice.app/Contents/MacOS/soffice',
 
62
        '--nologo',
 
63
        '--norestore',
 
64
        '--minimized',
 
65
        '--nodefault',
 
66
        '--nofirststartwizard',
 
67
        '--accept=pipe,name=openlp_maclo;urp;StarOffice.ServiceManager'
 
68
    ])
 
69
    assert server._process is mocked_process
 
70
 
 
71
 
 
72
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
73
def test_desktop_already_has_desktop(mocked_uno):
 
74
    """
 
75
    Test that setup_desktop() exits early when there's already a desktop
 
76
    """
 
77
    # GIVEN: A LibreOfficeServer instance
 
78
    server = LibreOfficeServer()
 
79
    server._desktop = MagicMock()
 
80
 
 
81
    # WHEN: the desktop property is called
 
82
    desktop = server.desktop
 
83
 
 
84
    # THEN: setup_desktop() exits early
 
85
    assert desktop is server._desktop
 
86
    assert server._manager is None
 
87
 
 
88
 
 
89
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
90
def test_desktop_exception(mocked_uno):
 
91
    """
 
92
    Test that setting up the desktop works correctly when an exception occurs
 
93
    """
 
94
    # GIVEN: A LibreOfficeServer instance
 
95
    server = LibreOfficeServer()
 
96
    mocked_context = MagicMock()
 
97
    mocked_resolver = MagicMock()
 
98
    mocked_uno_instance = MagicMock()
 
99
    MockedServiceManager = MagicMock()
 
100
    mocked_uno.getComponentContext.return_value = mocked_context
 
101
    mocked_context.ServiceManager.createInstanceWithContext.return_value = mocked_resolver
 
102
    mocked_resolver.resolve.side_effect = [Exception, mocked_uno_instance]
 
103
    mocked_uno_instance.ServiceManager = MockedServiceManager
 
104
    MockedServiceManager.createInstanceWithContext.side_effect = Exception()
 
105
 
 
106
    # WHEN: the desktop property is called
 
107
    server.desktop
 
108
 
 
109
    # THEN: A desktop object was created
 
110
    mocked_uno.getComponentContext.assert_called_once_with()
 
111
    mocked_context.ServiceManager.createInstanceWithContext.assert_called_once_with(
 
112
        'com.sun.star.bridge.UnoUrlResolver', mocked_context)
 
113
    expected_calls = [
 
114
        call('uno:pipe,name=openlp_maclo;urp;StarOffice.ComponentContext'),
 
115
        call('uno:pipe,name=openlp_maclo;urp;StarOffice.ComponentContext')
 
116
    ]
 
117
    assert mocked_resolver.resolve.call_args_list == expected_calls
 
118
    MockedServiceManager.createInstanceWithContext.assert_called_once_with(
 
119
        'com.sun.star.frame.Desktop', mocked_uno_instance)
 
120
    assert server._manager is MockedServiceManager
 
121
    assert server._desktop is None
 
122
 
 
123
 
 
124
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
125
def test_desktop(mocked_uno):
 
126
    """
 
127
    Test that setting up the desktop works correctly
 
128
    """
 
129
    # GIVEN: A LibreOfficeServer instance
 
130
    server = LibreOfficeServer()
 
131
    mocked_context = MagicMock()
 
132
    mocked_resolver = MagicMock()
 
133
    mocked_uno_instance = MagicMock()
 
134
    MockedServiceManager = MagicMock()
 
135
    mocked_desktop = MagicMock()
 
136
    mocked_uno.getComponentContext.return_value = mocked_context
 
137
    mocked_context.ServiceManager.createInstanceWithContext.return_value = mocked_resolver
 
138
    mocked_resolver.resolve.side_effect = [Exception, mocked_uno_instance]
 
139
    mocked_uno_instance.ServiceManager = MockedServiceManager
 
140
    MockedServiceManager.createInstanceWithContext.return_value = mocked_desktop
 
141
 
 
142
    # WHEN: the desktop property is called
 
143
    server.desktop
 
144
 
 
145
    # THEN: A desktop object was created
 
146
    mocked_uno.getComponentContext.assert_called_once_with()
 
147
    mocked_context.ServiceManager.createInstanceWithContext.assert_called_once_with(
 
148
        'com.sun.star.bridge.UnoUrlResolver', mocked_context)
 
149
    expected_calls = [
 
150
        call('uno:pipe,name=openlp_maclo;urp;StarOffice.ComponentContext'),
 
151
        call('uno:pipe,name=openlp_maclo;urp;StarOffice.ComponentContext')
 
152
    ]
 
153
    assert mocked_resolver.resolve.call_args_list == expected_calls
 
154
    MockedServiceManager.createInstanceWithContext.assert_called_once_with(
 
155
        'com.sun.star.frame.Desktop', mocked_uno_instance)
 
156
    assert server._manager is MockedServiceManager
 
157
    assert server._desktop is mocked_desktop
 
158
 
 
159
 
 
160
@patch('openlp.plugins.presentations.lib.libreofficeserver.PropertyValue')
 
161
def test_create_property(MockedPropertyValue):
 
162
    """
 
163
    Test that the _create_property() method works correctly
 
164
    """
 
165
    # GIVEN: A server amnd property to set
 
166
    server = LibreOfficeServer()
 
167
    name = 'Hidden'
 
168
    value = True
 
169
 
 
170
    # WHEN: The _create_property() method is called
 
171
    prop = server._create_property(name, value)
 
172
 
 
173
    # THEN: The property should have the correct attributes
 
174
    assert prop.Name == name
 
175
    assert prop.Value == value
 
176
 
 
177
 
 
178
def test_get_text_from_page_slide_text():
 
179
    """
 
180
    Test that the _get_text_from_page() method gives us nothing for slide text
 
181
    """
 
182
    # GIVEN: A LibreOfficeServer object and some mocked objects
 
183
    text_type = TextType.SlideText
 
184
    slide_no = 1
 
185
    server = LibreOfficeServer()
 
186
    server._document = MagicMock()
 
187
    mocked_pages = MagicMock()
 
188
    mocked_page = MagicMock()
 
189
    mocked_shape = MagicMock()
 
190
    server._document.getDrawPages.return_value = mocked_pages
 
191
    mocked_pages.getCount.return_value = 1
 
192
    mocked_pages.getByIndex.return_value = mocked_page
 
193
    mocked_page.getByIndex.return_value = mocked_shape
 
194
    mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
 
195
    mocked_shape.supportsService.return_value = True
 
196
    mocked_shape.getString.return_value = 'Page Text'
 
197
 
 
198
    # WHEN: _get_text_from_page() is run for slide text
 
199
    text = server._get_text_from_page(slide_no, text_type)
 
200
 
 
201
    # THE: The text is correct
 
202
    assert text == 'Page Text\n'
 
203
 
 
204
 
 
205
def test_get_text_from_page_title():
 
206
    """
 
207
    Test that the _get_text_from_page() method gives us the text from the titles
 
208
    """
 
209
    # GIVEN: A LibreOfficeServer object and some mocked objects
 
210
    text_type = TextType.Title
 
211
    slide_no = 1
 
212
    server = LibreOfficeServer()
 
213
    server._document = MagicMock()
 
214
    mocked_pages = MagicMock()
 
215
    mocked_page = MagicMock()
 
216
    mocked_shape = MagicMock()
 
217
    server._document.getDrawPages.return_value = mocked_pages
 
218
    mocked_pages.getCount.return_value = 1
 
219
    mocked_pages.getByIndex.return_value = mocked_page
 
220
    mocked_page.getByIndex.return_value = mocked_shape
 
221
    mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
 
222
    mocked_shape.supportsService.return_value = True
 
223
    mocked_shape.getString.return_value = 'Page Title'
 
224
 
 
225
    # WHEN: _get_text_from_page() is run for titles
 
226
    text = server._get_text_from_page(slide_no, text_type)
 
227
 
 
228
    # THEN: The text should be correct
 
229
    assert text == 'Page Title\n'
 
230
 
 
231
 
 
232
def test_get_text_from_page_notes():
 
233
    """
 
234
    Test that the _get_text_from_page() method gives us the text from the notes
 
235
    """
 
236
    # GIVEN: A LibreOfficeServer object and some mocked objects
 
237
    text_type = TextType.Notes
 
238
    slide_no = 1
 
239
    server = LibreOfficeServer()
 
240
    server._document = MagicMock()
 
241
    mocked_pages = MagicMock()
 
242
    mocked_page = MagicMock()
 
243
    mocked_notes_page = MagicMock()
 
244
    mocked_shape = MagicMock()
 
245
    server._document.getDrawPages.return_value = mocked_pages
 
246
    mocked_pages.getCount.return_value = 1
 
247
    mocked_pages.getByIndex.return_value = mocked_page
 
248
    mocked_page.getNotesPage.return_value = mocked_notes_page
 
249
    mocked_notes_page.getByIndex.return_value = mocked_shape
 
250
    mocked_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
 
251
    mocked_shape.supportsService.return_value = True
 
252
    mocked_shape.getString.return_value = 'Page Notes'
 
253
 
 
254
    # WHEN: _get_text_from_page() is run for titles
 
255
    text = server._get_text_from_page(slide_no, text_type)
 
256
 
 
257
    # THEN: The text should be correct
 
258
    assert text == 'Page Notes\n'
 
259
 
 
260
 
 
261
def test_shutdown_other_docs():
 
262
    """
 
263
    Test the shutdown method while other documents are open in LibreOffice
 
264
    """
 
265
    def close_docs():
 
266
        server._docs = []
 
267
 
 
268
    # GIVEN: An up an running LibreOfficeServer
 
269
    server = LibreOfficeServer()
 
270
    mocked_doc = MagicMock()
 
271
    mocked_desktop = MagicMock()
 
272
    mocked_docs = MagicMock()
 
273
    mocked_list = MagicMock()
 
274
    mocked_element_doc = MagicMock()
 
275
    server._docs = [mocked_doc]
 
276
    server._desktop = mocked_desktop
 
277
    server._process = MagicMock()
 
278
    mocked_doc.close_presentation.side_effect = close_docs
 
279
    mocked_desktop.getComponents.return_value = mocked_docs
 
280
    mocked_docs.hasElements.return_value = True
 
281
    mocked_docs.createEnumeration.return_value = mocked_list
 
282
    mocked_list.hasMoreElements.side_effect = [True, False]
 
283
    mocked_list.nextElement.return_value = mocked_element_doc
 
284
    mocked_element_doc.getImplementationName.side_effect = [
 
285
        'org.openlp.Nothing',
 
286
        'com.sun.star.comp.framework.BackingComp'
 
287
    ]
 
288
 
 
289
    # WHEN: shutdown() is called
 
290
    server.shutdown()
 
291
 
 
292
    # THEN: The right methods are called and everything works
 
293
    mocked_doc.close_presentation.assert_called_once_with()
 
294
    mocked_desktop.getComponents.assert_called_once_with()
 
295
    mocked_docs.hasElements.assert_called_once_with()
 
296
    mocked_docs.createEnumeration.assert_called_once_with()
 
297
    assert mocked_list.hasMoreElements.call_count == 2
 
298
    mocked_list.nextElement.assert_called_once_with()
 
299
    mocked_element_doc.getImplementationName.assert_called_once_with()
 
300
    assert mocked_desktop.terminate.call_count == 0
 
301
    assert server._process.kill.call_count == 0
 
302
 
 
303
 
 
304
def test_shutdown():
 
305
    """
 
306
    Test the shutdown method
 
307
    """
 
308
    def close_docs():
 
309
        server._docs = []
 
310
 
 
311
    # GIVEN: An up an running LibreOfficeServer
 
312
    server = LibreOfficeServer()
 
313
    mocked_doc = MagicMock()
 
314
    mocked_desktop = MagicMock()
 
315
    mocked_docs = MagicMock()
 
316
    mocked_list = MagicMock()
 
317
    mocked_element_doc = MagicMock()
 
318
    server._docs = [mocked_doc]
 
319
    server._desktop = mocked_desktop
 
320
    server._process = MagicMock()
 
321
    mocked_doc.close_presentation.side_effect = close_docs
 
322
    mocked_desktop.getComponents.return_value = mocked_docs
 
323
    mocked_docs.hasElements.return_value = True
 
324
    mocked_docs.createEnumeration.return_value = mocked_list
 
325
    mocked_list.hasMoreElements.side_effect = [True, False]
 
326
    mocked_list.nextElement.return_value = mocked_element_doc
 
327
    mocked_element_doc.getImplementationName.return_value = 'com.sun.star.comp.framework.BackingComp'
 
328
 
 
329
    # WHEN: shutdown() is called
 
330
    server.shutdown()
 
331
 
 
332
    # THEN: The right methods are called and everything works
 
333
    mocked_doc.close_presentation.assert_called_once_with()
 
334
    mocked_desktop.getComponents.assert_called_once_with()
 
335
    mocked_docs.hasElements.assert_called_once_with()
 
336
    mocked_docs.createEnumeration.assert_called_once_with()
 
337
    assert mocked_list.hasMoreElements.call_count == 2
 
338
    mocked_list.nextElement.assert_called_once_with()
 
339
    mocked_element_doc.getImplementationName.assert_called_once_with()
 
340
    mocked_desktop.terminate.assert_called_once_with()
 
341
    server._process.kill.assert_called_once_with()
 
342
 
 
343
 
 
344
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
345
def test_load_presentation_exception(mocked_uno):
 
346
    """
 
347
    Test the load_presentation() method when an exception occurs
 
348
    """
 
349
    # GIVEN: A LibreOfficeServer object
 
350
    presentation_file = '/path/to/presentation.odp'
 
351
    screen_number = 1
 
352
    server = LibreOfficeServer()
 
353
    mocked_desktop = MagicMock()
 
354
    mocked_uno.systemPathToFileUrl.side_effect = lambda x: x
 
355
    server._desktop = mocked_desktop
 
356
    mocked_desktop.loadComponentFromURL.side_effect = Exception()
 
357
 
 
358
    # WHEN: load_presentation() is called
 
359
    with patch.object(server, '_create_property') as mocked_create_property:
 
360
        mocked_create_property.side_effect = lambda x, y: {x: y}
 
361
        result = server.load_presentation(presentation_file, screen_number)
 
362
 
 
363
    # THEN: A presentation is loaded
 
364
    assert result is False
 
365
 
 
366
 
 
367
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
368
def test_load_presentation(mocked_uno):
 
369
    """
 
370
    Test the load_presentation() method
 
371
    """
 
372
    # GIVEN: A LibreOfficeServer object
 
373
    presentation_file = '/path/to/presentation.odp'
 
374
    screen_number = 1
 
375
    server = LibreOfficeServer()
 
376
    mocked_desktop = MagicMock()
 
377
    mocked_document = MagicMock()
 
378
    mocked_presentation = MagicMock()
 
379
    mocked_uno.systemPathToFileUrl.side_effect = lambda x: x
 
380
    server._desktop = mocked_desktop
 
381
    mocked_desktop.loadComponentFromURL.return_value = mocked_document
 
382
    mocked_document.getPresentation.return_value = mocked_presentation
 
383
 
 
384
    # WHEN: load_presentation() is called
 
385
    with patch.object(server, '_create_property') as mocked_create_property:
 
386
        mocked_create_property.side_effect = lambda x, y: {x: y}
 
387
        result = server.load_presentation(presentation_file, screen_number)
 
388
 
 
389
    # THEN: A presentation is loaded
 
390
    assert result is True
 
391
    mocked_uno.systemPathToFileUrl.assert_called_once_with(presentation_file)
 
392
    mocked_create_property.assert_called_once_with('Hidden', True)
 
393
    mocked_desktop.loadComponentFromURL.assert_called_once_with(
 
394
        presentation_file, '_blank', 0, ({'Hidden': True},))
 
395
    assert server._document is mocked_document
 
396
    mocked_document.getPresentation.assert_called_once_with()
 
397
    assert server._presentation is mocked_presentation
 
398
    assert server._presentation.Display == screen_number
 
399
    assert server._control is None
 
400
 
 
401
 
 
402
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
403
def test_extract_thumbnails_no_pages(mocked_uno):
 
404
    """
 
405
    Test the extract_thumbnails() method when there are no pages
 
406
    """
 
407
    # GIVEN: A LibreOfficeServer instance
 
408
    temp_folder = '/tmp'
 
409
    server = LibreOfficeServer()
 
410
    mocked_document = MagicMock()
 
411
    server._document = mocked_document
 
412
    mocked_uno.systemPathToFileUrl.side_effect = lambda x: x
 
413
    mocked_document.getDrawPages.return_value = None
 
414
 
 
415
    # WHEN: The extract_thumbnails() method is called
 
416
    with patch.object(server, '_create_property') as mocked_create_property:
 
417
        mocked_create_property.side_effect = lambda x, y: {x: y}
 
418
        thumbnails = server.extract_thumbnails(temp_folder)
 
419
 
 
420
    # THEN: Thumbnails have been extracted
 
421
    mocked_uno.systemPathToFileUrl.assert_called_once_with(temp_folder)
 
422
    mocked_create_property.assert_called_once_with('FilterName', 'impress_png_Export')
 
423
    mocked_document.getDrawPages.assert_called_once_with()
 
424
    assert thumbnails == []
 
425
 
 
426
 
 
427
@patch('openlp.plugins.presentations.lib.libreofficeserver.uno')
 
428
@patch('openlp.plugins.presentations.lib.libreofficeserver.os')
 
429
def test_extract_thumbnails(mocked_os, mocked_uno):
 
430
    """
 
431
    Test the extract_thumbnails() method
 
432
    """
 
433
    # GIVEN: A LibreOfficeServer instance
 
434
    temp_folder = '/tmp'
 
435
    server = LibreOfficeServer()
 
436
    mocked_document = MagicMock()
 
437
    mocked_pages = MagicMock()
 
438
    mocked_page_1 = MagicMock()
 
439
    mocked_page_2 = MagicMock()
 
440
    mocked_controller = MagicMock()
 
441
    server._document = mocked_document
 
442
    mocked_uno.systemPathToFileUrl.side_effect = lambda x: x
 
443
    mocked_document.getDrawPages.return_value = mocked_pages
 
444
    mocked_os.path.isdir.return_value = False
 
445
    mocked_pages.getCount.return_value = 2
 
446
    mocked_pages.getByIndex.side_effect = [mocked_page_1, mocked_page_2]
 
447
    mocked_document.getCurrentController.return_value = mocked_controller
 
448
    mocked_os.path.join.side_effect = lambda *x: '/'.join(x)
 
449
 
 
450
    # WHEN: The extract_thumbnails() method is called
 
451
    with patch.object(server, '_create_property') as mocked_create_property:
 
452
        mocked_create_property.side_effect = lambda x, y: {x: y}
 
453
        thumbnails = server.extract_thumbnails(temp_folder)
 
454
 
 
455
    # THEN: Thumbnails have been extracted
 
456
    mocked_uno.systemPathToFileUrl.assert_called_once_with(temp_folder)
 
457
    mocked_create_property.assert_called_once_with('FilterName', 'impress_png_Export')
 
458
    mocked_document.getDrawPages.assert_called_once_with()
 
459
    mocked_pages.getCount.assert_called_once_with()
 
460
    assert mocked_pages.getByIndex.call_args_list == [call(0), call(1)]
 
461
    assert mocked_controller.setCurrentPage.call_args_list == \
 
462
        [call(mocked_page_1), call(mocked_page_2)]
 
463
    assert mocked_document.storeToURL.call_args_list == \
 
464
        [call('/tmp/1.png', ({'FilterName': 'impress_png_Export'},)),
 
465
         call('/tmp/2.png', ({'FilterName': 'impress_png_Export'},))]
 
466
    assert thumbnails == ['/tmp/1.png', '/tmp/2.png']
 
467
 
 
468
 
 
469
def test_get_titles_and_notes():
 
470
    """
 
471
    Test the get_titles_and_notes() method
 
472
    """
 
473
    # GIVEN: A LibreOfficeServer object and a bunch of mocks
 
474
    server = LibreOfficeServer()
 
475
    mocked_document = MagicMock()
 
476
    mocked_pages = MagicMock()
 
477
    server._document = mocked_document
 
478
    mocked_document.getDrawPages.return_value = mocked_pages
 
479
    mocked_pages.getCount.return_value = 2
 
480
 
 
481
    # WHEN: get_titles_and_notes() is called
 
482
    with patch.object(server, '_get_text_from_page') as mocked_get_text_from_page:
 
483
        mocked_get_text_from_page.side_effect = [
 
484
            'OpenLP on Mac OS X',
 
485
            '',
 
486
            '',
 
487
            'Installing is a drag-and-drop affair'
 
488
        ]
 
489
        titles, notes = server.get_titles_and_notes()
 
490
 
 
491
    # THEN: The right calls are made and the right stuff returned
 
492
    mocked_document.getDrawPages.assert_called_once_with()
 
493
    mocked_pages.getCount.assert_called_once_with()
 
494
    assert mocked_get_text_from_page.call_count == 4
 
495
    expected_calls = [
 
496
        call(1, TextType.Title), call(1, TextType.Notes),
 
497
        call(2, TextType.Title), call(2, TextType.Notes),
 
498
    ]
 
499
    assert mocked_get_text_from_page.call_args_list == expected_calls
 
500
    assert titles == ['OpenLP on Mac OS X\n', '\n'], titles
 
501
    assert notes == [' ', 'Installing is a drag-and-drop affair'], notes
 
502
 
 
503
 
 
504
def test_close_presentation():
 
505
    """
 
506
    Test that closing the presentation cleans things up correctly
 
507
    """
 
508
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
509
    server = LibreOfficeServer()
 
510
    mocked_document = MagicMock()
 
511
    mocked_presentation = MagicMock()
 
512
    server._document = mocked_document
 
513
    server._presentation = mocked_presentation
 
514
 
 
515
    # WHEN: close_presentation() is called
 
516
    server.close_presentation()
 
517
 
 
518
    # THEN: The presentation and document should be closed
 
519
    mocked_presentation.end.assert_called_once_with()
 
520
    mocked_document.dispose.assert_called_once_with()
 
521
    assert server._document is None
 
522
    assert server._presentation is None
 
523
 
 
524
 
 
525
def test_is_loaded_no_objects():
 
526
    """
 
527
    Test the is_loaded() method when there's no document or presentation
 
528
    """
 
529
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
530
    server = LibreOfficeServer()
 
531
 
 
532
    # WHEN: The is_loaded() method is called
 
533
    result = server.is_loaded()
 
534
 
 
535
    # THEN: The result should be false
 
536
    assert result is False
 
537
 
 
538
 
 
539
def test_is_loaded_no_presentation():
 
540
    """
 
541
    Test the is_loaded() method when there's no presentation
 
542
    """
 
543
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
544
    server = LibreOfficeServer()
 
545
    mocked_document = MagicMock()
 
546
    server._document = mocked_document
 
547
    server._presentation = MagicMock()
 
548
    mocked_document.getPresentation.return_value = None
 
549
 
 
550
    # WHEN: The is_loaded() method is called
 
551
    result = server.is_loaded()
 
552
 
 
553
    # THEN: The result should be false
 
554
    assert result is False
 
555
    mocked_document.getPresentation.assert_called_once_with()
 
556
 
 
557
 
 
558
def test_is_loaded_exception():
 
559
    """
 
560
    Test the is_loaded() method when an exception is thrown
 
561
    """
 
562
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
563
    server = LibreOfficeServer()
 
564
    mocked_document = MagicMock()
 
565
    server._document = mocked_document
 
566
    server._presentation = MagicMock()
 
567
    mocked_document.getPresentation.side_effect = Exception()
 
568
 
 
569
    # WHEN: The is_loaded() method is called
 
570
    result = server.is_loaded()
 
571
 
 
572
    # THEN: The result should be false
 
573
    assert result is False
 
574
    mocked_document.getPresentation.assert_called_once_with()
 
575
 
 
576
 
 
577
def test_is_loaded():
 
578
    """
 
579
    Test the is_loaded() method
 
580
    """
 
581
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
582
    server = LibreOfficeServer()
 
583
    mocked_document = MagicMock()
 
584
    mocked_presentation = MagicMock()
 
585
    server._document = mocked_document
 
586
    server._presentation = mocked_presentation
 
587
    mocked_document.getPresentation.return_value = mocked_presentation
 
588
 
 
589
    # WHEN: The is_loaded() method is called
 
590
    result = server.is_loaded()
 
591
 
 
592
    # THEN: The result should be false
 
593
    assert result is True
 
594
    mocked_document.getPresentation.assert_called_once_with()
 
595
 
 
596
 
 
597
def test_is_active_not_loaded():
 
598
    """
 
599
    Test is_active() when is_loaded() returns False
 
600
    """
 
601
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
602
    server = LibreOfficeServer()
 
603
 
 
604
    # WHEN: is_active() is called with is_loaded() returns False
 
605
    with patch.object(server, 'is_loaded') as mocked_is_loaded:
 
606
        mocked_is_loaded.return_value = False
 
607
        result = server.is_active()
 
608
 
 
609
    # THEN: It should have returned False
 
610
    assert result is False
 
611
 
 
612
 
 
613
def test_is_active_no_control():
 
614
    """
 
615
    Test is_active() when is_loaded() returns True but there's no control
 
616
    """
 
617
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
618
    server = LibreOfficeServer()
 
619
 
 
620
    # WHEN: is_active() is called with is_loaded() returns False
 
621
    with patch.object(server, 'is_loaded') as mocked_is_loaded:
 
622
        mocked_is_loaded.return_value = True
 
623
        result = server.is_active()
 
624
 
 
625
    # THEN: The result should be False
 
626
    assert result is False
 
627
    mocked_is_loaded.assert_called_once_with()
 
628
 
 
629
 
 
630
def test_is_active():
 
631
    """
 
632
    Test is_active()
 
633
    """
 
634
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
635
    server = LibreOfficeServer()
 
636
    mocked_control = MagicMock()
 
637
    server._control = mocked_control
 
638
    mocked_control.isRunning.return_value = True
 
639
 
 
640
    # WHEN: is_active() is called with is_loaded() returns False
 
641
    with patch.object(server, 'is_loaded') as mocked_is_loaded:
 
642
        mocked_is_loaded.return_value = True
 
643
        result = server.is_active()
 
644
 
 
645
    # THEN: The result should be False
 
646
    assert result is True
 
647
    mocked_is_loaded.assert_called_once_with()
 
648
    mocked_control.isRunning.assert_called_once_with()
 
649
 
 
650
 
 
651
def test_unblank_screen():
 
652
    """
 
653
    Test the unblank_screen() method
 
654
    """
 
655
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
656
    server = LibreOfficeServer()
 
657
    mocked_control = MagicMock()
 
658
    server._control = mocked_control
 
659
 
 
660
    # WHEN: unblank_screen() is run
 
661
    server.unblank_screen()
 
662
 
 
663
    # THEN: The resume method should have been called
 
664
    mocked_control.resume.assert_called_once_with()
 
665
 
 
666
 
 
667
def test_blank_screen():
 
668
    """
 
669
    Test the blank_screen() method
 
670
    """
 
671
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
672
    server = LibreOfficeServer()
 
673
    mocked_control = MagicMock()
 
674
    server._control = mocked_control
 
675
 
 
676
    # WHEN: blank_screen() is run
 
677
    server.blank_screen()
 
678
 
 
679
    # THEN: The resume method should have been called
 
680
    mocked_control.blankScreen.assert_called_once_with(0)
 
681
 
 
682
 
 
683
def test_is_blank_no_control():
 
684
    """
 
685
    Test the is_blank() method when there's no control
 
686
    """
 
687
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
688
    server = LibreOfficeServer()
 
689
 
 
690
    # WHEN: is_blank() is called
 
691
    result = server.is_blank()
 
692
 
 
693
    # THEN: It should have returned False
 
694
    assert result is False
 
695
 
 
696
 
 
697
def test_is_blank_control_is_running():
 
698
    """
 
699
    Test the is_blank() method when the control is running
 
700
    """
 
701
    # GIVEN: A LibreOfficeServer instance and a bunch of mocks
 
702
    server = LibreOfficeServer()
 
703
    mocked_control = MagicMock()
 
704
    server._control = mocked_control
 
705
    mocked_control.isRunning.return_value = True
 
706
    mocked_control.isPaused.return_value = True
 
707
 
 
708
    # WHEN: is_blank() is called
 
709
    result = server.is_blank()
 
710
 
 
711
    # THEN: It should have returned False
 
712
    assert result is True
 
713
    mocked_control.isRunning.assert_called_once_with()
 
714
    mocked_control.isPaused.assert_called_once_with()
 
715
 
 
716
 
 
717
def test_stop_presentation():
 
718
    """
 
719
    Test the stop_presentation() method
 
720
    """
 
721
    # GIVEN: A LibreOfficeServer instance and a mocked presentation
 
722
    server = LibreOfficeServer()
 
723
    mocked_presentation = MagicMock()
 
724
    mocked_control = MagicMock()
 
725
    server._presentation = mocked_presentation
 
726
    server._control = mocked_control
 
727
 
 
728
    # WHEN: stop_presentation() is called
 
729
    server.stop_presentation()
 
730
 
 
731
    # THEN: The presentation is ended and the control is removed
 
732
    mocked_presentation.end.assert_called_once_with()
 
733
    assert server._control is None
 
734
 
 
735
 
 
736
@patch('openlp.plugins.presentations.lib.libreofficeserver.time.sleep')
 
737
def test_start_presentation_no_control(mocked_sleep):
 
738
    """
 
739
    Test the start_presentation() method when there's no control
 
740
    """
 
741
    # GIVEN: A LibreOfficeServer instance and some mocks
 
742
    server = LibreOfficeServer()
 
743
    mocked_control = MagicMock()
 
744
    mocked_document = MagicMock()
 
745
    mocked_presentation = MagicMock()
 
746
    mocked_controller = MagicMock()
 
747
    mocked_frame = MagicMock()
 
748
    mocked_window = MagicMock()
 
749
    server._document = mocked_document
 
750
    server._presentation = mocked_presentation
 
751
    mocked_document.getCurrentController.return_value = mocked_controller
 
752
    mocked_controller.getFrame.return_value = mocked_frame
 
753
    mocked_frame.getContainerWindow.return_value = mocked_window
 
754
    mocked_presentation.getController.side_effect = [None, mocked_control]
 
755
 
 
756
    # WHEN: start_presentation() is called
 
757
    server.start_presentation()
 
758
 
 
759
    # THEN: The slide number should be correct
 
760
    mocked_document.getCurrentController.assert_called_once_with()
 
761
    mocked_controller.getFrame.assert_called_once_with()
 
762
    mocked_frame.getContainerWindow.assert_called_once_with()
 
763
    mocked_presentation.start.assert_called_once_with()
 
764
    assert mocked_presentation.getController.call_count == 2
 
765
    mocked_sleep.assert_called_once_with(0.1)
 
766
    assert mocked_window.setVisible.call_args_list == [call(True), call(False)]
 
767
    assert server._control is mocked_control
 
768
 
 
769
 
 
770
def test_start_presentation():
 
771
    """
 
772
    Test the start_presentation() method when there's a control
 
773
    """
 
774
    # GIVEN: A LibreOfficeServer instance and some mocks
 
775
    server = LibreOfficeServer()
 
776
    mocked_control = MagicMock()
 
777
    server._control = mocked_control
 
778
 
 
779
    # WHEN: start_presentation() is called
 
780
    with patch.object(server, 'goto_slide') as mocked_goto_slide:
 
781
        server.start_presentation()
 
782
 
 
783
    # THEN: The control should have been activated and the first slide selected
 
784
    mocked_control.activate.assert_called_once_with()
 
785
    mocked_goto_slide.assert_called_once_with(1)
 
786
 
 
787
 
 
788
def test_get_slide_number():
 
789
    """
 
790
    Test the get_slide_number() method
 
791
    """
 
792
    # GIVEN: A LibreOfficeServer instance and some mocks
 
793
    server = LibreOfficeServer()
 
794
    mocked_control = MagicMock()
 
795
    mocked_control.getCurrentSlideIndex.return_value = 3
 
796
    server._control = mocked_control
 
797
 
 
798
    # WHEN: get_slide_number() is called
 
799
    result = server.get_slide_number()
 
800
 
 
801
    # THEN: The slide number should be correct
 
802
    assert result == 4
 
803
 
 
804
 
 
805
def test_get_slide_count():
 
806
    """
 
807
    Test the get_slide_count() method
 
808
    """
 
809
    # GIVEN: A LibreOfficeServer instance and some mocks
 
810
    server = LibreOfficeServer()
 
811
    mocked_document = MagicMock()
 
812
    mocked_pages = MagicMock()
 
813
    server._document = mocked_document
 
814
    mocked_document.getDrawPages.return_value = mocked_pages
 
815
    mocked_pages.getCount.return_value = 2
 
816
 
 
817
    # WHEN: get_slide_count() is called
 
818
    result = server.get_slide_count()
 
819
 
 
820
    # THEN: The slide count should be correct
 
821
    assert result == 2
 
822
 
 
823
 
 
824
def test_goto_slide():
 
825
    """
 
826
    Test the goto_slide() method
 
827
    """
 
828
    # GIVEN: A LibreOfficeServer instance and some mocks
 
829
    server = LibreOfficeServer()
 
830
    mocked_control = MagicMock()
 
831
    server._control = mocked_control
 
832
 
 
833
    # WHEN: goto_slide() is called
 
834
    server.goto_slide(1)
 
835
 
 
836
    # THEN: The slide number should be correct
 
837
    mocked_control.gotoSlideIndex.assert_called_once_with(0)
 
838
 
 
839
 
 
840
@patch('openlp.plugins.presentations.lib.libreofficeserver.time.sleep')
 
841
def test_next_step_when_paused(mocked_sleep):
 
842
    """
 
843
    Test the next_step() method when paused
 
844
    """
 
845
    # GIVEN: A LibreOfficeServer instance and a mocked control
 
846
    server = LibreOfficeServer()
 
847
    mocked_control = MagicMock()
 
848
    server._control = mocked_control
 
849
    mocked_control.isPaused.side_effect = [False, True]
 
850
 
 
851
    # WHEN: next_step() is called
 
852
    server.next_step()
 
853
 
 
854
    # THEN: The correct call should be made
 
855
    mocked_control.gotoNextEffect.assert_called_once_with()
 
856
    mocked_sleep.assert_called_once_with(0.1)
 
857
    assert mocked_control.isPaused.call_count == 2
 
858
    mocked_control.gotoPreviousEffect.assert_called_once_with()
 
859
 
 
860
 
 
861
@patch('openlp.plugins.presentations.lib.libreofficeserver.time.sleep')
 
862
def test_next_step(mocked_sleep):
 
863
    """
 
864
    Test the next_step() method when paused
 
865
    """
 
866
    # GIVEN: A LibreOfficeServer instance and a mocked control
 
867
    server = LibreOfficeServer()
 
868
    mocked_control = MagicMock()
 
869
    server._control = mocked_control
 
870
    mocked_control.isPaused.side_effect = [True, True]
 
871
 
 
872
    # WHEN: next_step() is called
 
873
    server.next_step()
 
874
 
 
875
    # THEN: The correct call should be made
 
876
    mocked_control.gotoNextEffect.assert_called_once_with()
 
877
    mocked_sleep.assert_called_once_with(0.1)
 
878
    assert mocked_control.isPaused.call_count == 1
 
879
    assert mocked_control.gotoPreviousEffect.call_count == 0
 
880
 
 
881
 
 
882
def test_previous_step():
 
883
    """
 
884
    Test the previous_step() method
 
885
    """
 
886
    # GIVEN: A LibreOfficeServer instance and a mocked control
 
887
    server = LibreOfficeServer()
 
888
    mocked_control = MagicMock()
 
889
    server._control = mocked_control
 
890
 
 
891
    # WHEN: previous_step() is called
 
892
    server.previous_step()
 
893
 
 
894
    # THEN: The correct call should be made
 
895
    mocked_control.gotoPreviousEffect.assert_called_once_with()
 
896
 
 
897
 
 
898
def test_get_slide_text():
 
899
    """
 
900
    Test the get_slide_text() method
 
901
    """
 
902
    # GIVEN: A LibreOfficeServer instance
 
903
    server = LibreOfficeServer()
 
904
 
 
905
    # WHEN: get_slide_text() is called for a particular slide
 
906
    with patch.object(server, '_get_text_from_page') as mocked_get_text_from_page:
 
907
        mocked_get_text_from_page.return_value = 'OpenLP on Mac OS X'
 
908
        result = server.get_slide_text(5)
 
909
 
 
910
    # THEN: The text should be returned
 
911
    mocked_get_text_from_page.assert_called_once_with(5)
 
912
    assert result == 'OpenLP on Mac OS X'
 
913
 
 
914
 
 
915
def test_get_slide_notes():
 
916
    """
 
917
    Test the get_slide_notes() method
 
918
    """
 
919
    # GIVEN: A LibreOfficeServer instance
 
920
    server = LibreOfficeServer()
 
921
 
 
922
    # WHEN: get_slide_notes() is called for a particular slide
 
923
    with patch.object(server, '_get_text_from_page') as mocked_get_text_from_page:
 
924
        mocked_get_text_from_page.return_value = 'Installing is a drag-and-drop affair'
 
925
        result = server.get_slide_notes(3)
 
926
 
 
927
    # THEN: The text should be returned
 
928
    mocked_get_text_from_page.assert_called_once_with(3, TextType.Notes)
 
929
    assert result == 'Installing is a drag-and-drop affair'
 
930
 
 
931
 
 
932
@patch('openlp.plugins.presentations.lib.libreofficeserver.Daemon')
 
933
def test_main(MockedDaemon):
 
934
    """
 
935
    Test the main() function
 
936
    """
 
937
    # GIVEN: Mocked out Pyro objects
 
938
    mocked_daemon = MagicMock()
 
939
    MockedDaemon.return_value = mocked_daemon
 
940
 
 
941
    # WHEN: main() is run
 
942
    main()
 
943
 
 
944
    # THEN: The correct calls are made
 
945
    MockedDaemon.assert_called_once_with(host='localhost', port=4310)
 
946
    mocked_daemon.register.assert_called_once_with(LibreOfficeServer, 'openlp.libreofficeserver')
 
947
    mocked_daemon.requestLoop.assert_called_once_with()
 
948
    mocked_daemon.close.assert_called_once_with()