Tests plugin 2

This commit is contained in:
Tim Bentley 2020-03-05 20:34:08 +00:00
parent 79950b6a85
commit 7d532778bd
8 changed files with 945 additions and 1286 deletions

View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2020 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, either version 3 of the License, or #
# (at your option) any later version. #
# #
# 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, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
For the Presentation tests
"""
import pytest
import shutil
from unittest.mock import MagicMock, patch
from tempfile import mkdtemp
from openlp.core.common.registry import Registry
from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem
@pytest.fixture
def media_item(settings):
"""Local test setup"""
Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
m_item = PresentationMediaItem(None, MagicMock, MagicMock())
m_item.settings_section = 'media'
return m_item
@pytest.yield_fixture()
def mock_plugin():
m_plugin = MagicMock()
temp_folder = mkdtemp()
m_plugin.settings_section = temp_folder
yield m_plugin
shutil.rmtree(temp_folder)

View File

@ -21,295 +21,271 @@
"""
Functional tests to test the Impress class and related methods.
"""
import shutil
from tempfile import mkdtemp
from unittest import TestCase
import pytest
from unittest.mock import MagicMock, call, patch
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType
from tests.helpers.testmixin import TestMixin
from tests.utils.constants import RESOURCE_PATH
class TestImpressController(TestCase, TestMixin):
@pytest.fixture()
def doc(settings):
mocked_plugin = MagicMock()
mocked_plugin.settings_section = 'presentations'
file_name = RESOURCE_PATH / 'presentations' / 'test.pptx'
ppc = ImpressController(mocked_plugin)
return ImpressDocument(ppc, file_name)
def test_constructor(settings, mock_plugin):
"""
Test the ImpressController Class
Test the Constructor from the ImpressController
"""
# GIVEN: No presentation controller
controller = None
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
self.setup_application()
self.build_settings()
self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp()
self.mock_plugin.settings_section = self.temp_folder
Registry.create()
Registry().register('settings', Settings())
# WHEN: The presentation controller object is created
controller = ImpressController(plugin=mock_plugin)
def tearDown(self):
"""
Stop the patches
"""
self.destroy_settings()
shutil.rmtree(self.temp_folder)
def test_constructor(self):
"""
Test the Constructor from the ImpressController
"""
# GIVEN: No presentation controller
controller = None
# WHEN: The presentation controller object is created
controller = ImpressController(plugin=self.mock_plugin)
# THEN: The name of the presentation controller should be correct
assert 'Impress' == controller.name, 'The name of the presentation controller should be correct'
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
def test_check_available(self, mocked_log):
"""
Test `ImpressController.check_available` on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=self.mock_plugin)
# WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns None
with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \
patch.object(controller, 'get_com_servicemanager', return_value=None) as mocked_get_com_servicemanager:
result = controller.check_available()
# THEN: `check_available` should return False
assert mocked_get_com_servicemanager.called is True
assert result is False
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
def test_check_available_on_windows(self, mocked_log):
"""
Test `ImpressController.check_available` on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=self.mock_plugin)
# WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns an object
mocked_com_object = MagicMock()
with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \
patch.object(controller, 'get_com_servicemanager', return_value=mocked_com_object) \
as mocked_get_com_servicemanager:
result = controller.check_available()
# THEN: `check_available` should return True
assert mocked_get_com_servicemanager.called is True
assert result is True
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
def test_check_available_on_linux(self, mocked_is_win, mocked_log):
"""
Test `ImpressController.check_available` when not on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=self.mock_plugin)
# WHEN: `check_available` is called on Windows and `uno_available` is True
with patch('openlp.plugins.presentations.lib.impresscontroller.uno_available', True), \
patch.object(controller, 'get_com_servicemanager') as mocked_get_com_servicemanager:
result = controller.check_available()
# THEN: `check_available` should return True
assert mocked_get_com_servicemanager.called is False
assert result is True
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True)
def test_start_process_on_windows(self, mocked_is_win):
"""
Test that start_process() on Windows starts the process
"""
# GIVEN: An ImpressController object
controller = ImpressController(plugin=self.mock_plugin)
controller.get_com_servicemanager = MagicMock(return_value=MagicMock())
# WHEN: start_process() is called
controller.start_process()
# THEN: The correct methods should have been called
controller.get_com_servicemanager.assert_called_once()
assert controller.manager._FlagAsMethod.call_args_list == [call('Bridge_GetStruct'),
call('Bridge_GetValueObject')]
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
@patch('openlp.plugins.presentations.lib.impresscontroller.get_uno_command', return_value='libreoffice')
@patch('openlp.plugins.presentations.lib.impresscontroller.QtCore.QProcess')
def test_start_process_on_linux(self, MockQProcess, mocked_get_uno_command, mocked_is_win):
"""
Test that start_process() on Linux starts the process
"""
# GIVEN: An ImpressController object
mocked_process = MagicMock()
MockQProcess.return_value = mocked_process
controller = ImpressController(plugin=self.mock_plugin)
# WHEN: start_process() is called
controller.start_process()
# THEN: The correct methods should have been called
mocked_get_uno_command.assert_called_once()
MockQProcess.assert_called_once()
assert controller.process is mocked_process
mocked_process.startDetached.assert_called_once_with('libreoffice')
# THEN: The name of the presentation controller should be correct
assert 'Impress' == controller.name, 'The name of the presentation controller should be correct'
class TestImpressDocument(TestCase):
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
def test_check_available(mocked_log, settings, mock_plugin):
"""
Test the ImpressDocument Class
Test `ImpressController.check_available` on Windows
"""
def setUp(self):
mocked_plugin = MagicMock()
mocked_plugin.settings_section = 'presentations'
self.file_name = RESOURCE_PATH / 'presentations' / 'test.pptx'
self.settings = Settings()
Registry.create()
Registry().register('settings', self.settings)
self.ppc = ImpressController(mocked_plugin)
self.doc = ImpressDocument(self.ppc, self.file_name)
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=mock_plugin)
def test_create_titles_and_notes(self):
"""
Test ImpressDocument.create_titles_and_notes
"""
# GIVEN: mocked PresentationController.save_titles_and_notes with
# 0 pages and the LibreOffice Document
self.doc.save_titles_and_notes = MagicMock()
self.doc.document = MagicMock()
self.doc.document.getDrawPages.return_value = MagicMock()
self.doc.document.getDrawPages().getCount.return_value = 0
# WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns None
with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \
patch.object(controller, 'get_com_servicemanager', return_value=None) as mocked_get_com_servicemanager:
result = controller.check_available()
# WHEN reading the titles and notes
self.doc.create_titles_and_notes()
# THEN: `check_available` should return False
assert mocked_get_com_servicemanager.called is True
assert result is False
# THEN save_titles_and_notes should have been called with empty arrays
self.doc.save_titles_and_notes.assert_called_once_with([], [])
# GIVEN: reset mock and set it to 2 pages
self.doc.save_titles_and_notes.reset_mock()
self.doc.document.getDrawPages().getCount.return_value = 2
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
def test_check_available_on_windows(mocked_log, settings, mock_plugin):
"""
Test `ImpressController.check_available` on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=mock_plugin)
# WHEN: a new call to create_titles_and_notes
self.doc.create_titles_and_notes()
# WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns an object
mocked_com_object = MagicMock()
with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \
patch.object(controller, 'get_com_servicemanager', return_value=mocked_com_object) \
as mocked_get_com_servicemanager:
result = controller.check_available()
# THEN: save_titles_and_notes should have been called once with
# two arrays of two elements
# self.doc.save_titles_and_notes.assert_called_once_with(['\n', '\n'], [' ', ' '])
self.doc.save_titles_and_notes.assert_called_once_with(['', ''], [' ', ' '])
# THEN: `check_available` should return True
assert mocked_get_com_servicemanager.called is True
assert result is True
def test_get_text_from_page_out_of_bound(self):
"""
Test ImpressDocument.__get_text_from_page with out-of-bounds index
"""
# GIVEN: mocked LibreOffice Document with one slide,
# two notes and three texts
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
# WHEN: __get_text_from_page is called with an index of 0x00
result = self.doc._ImpressDocument__get_text_from_page(0, TextType.Notes)
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
def test_check_available_on_linux(mocked_is_win, mocked_log, settings, mock_plugin):
"""
Test `ImpressController.check_available` when not on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=mock_plugin)
# THEN: the result should be an empty string
assert result == '', 'Result should be an empty string'
# WHEN: `check_available` is called on Windows and `uno_available` is True
with patch('openlp.plugins.presentations.lib.impresscontroller.uno_available', True), \
patch.object(controller, 'get_com_servicemanager') as mocked_get_com_servicemanager:
result = controller.check_available()
# WHEN: regardless of the type of text, index 0x00 is out of bounds
result = self.doc._ImpressDocument__get_text_from_page(0, TextType.Title)
# THEN: `check_available` should return True
assert mocked_get_com_servicemanager.called is False
assert result is True
# THEN: result should be an empty string
assert result == '', 'Result should be an empty string'
# WHEN: when called with 2, it should also be out of bounds
result = self.doc._ImpressDocument__get_text_from_page(2, TextType.SlideText)
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True)
def test_start_process_on_windows(mocked_is_win, settings, mock_plugin):
"""
Test that start_process() on Windows starts the process
"""
# GIVEN: An ImpressController object
controller = ImpressController(plugin=mock_plugin)
controller.get_com_servicemanager = MagicMock(return_value=MagicMock())
# THEN: result should be an empty string ... and, getByIndex should
# have never been called
assert result == '', 'Result should be an empty string'
assert self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
# WHEN: start_process() is called
controller.start_process()
def test_get_text_from_page_wrong_type(self):
"""
Test ImpressDocument.__get_text_from_page with wrong TextType
"""
# GIVEN: mocked LibreOffice Document with one slide, two notes and
# three texts
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
# THEN: The correct methods should have been called
controller.get_com_servicemanager.assert_called_once()
assert controller.manager._FlagAsMethod.call_args_list == [call('Bridge_GetStruct'),
call('Bridge_GetValueObject')]
# WHEN: called with TextType 3
result = self.doc._ImpressDocument__get_text_from_page(1, 3)
# THEN: result should be an empty string
assert result == '', 'Result should be and empty string'
assert self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
@patch('openlp.plugins.presentations.lib.impresscontroller.get_uno_command', return_value='libreoffice')
@patch('openlp.plugins.presentations.lib.impresscontroller.QtCore.QProcess')
def test_start_process_on_linux(MockQProcess, mocked_get_uno_command, mocked_is_win, settings, mock_plugin):
"""
Test that start_process() on Linux starts the process
"""
# GIVEN: An ImpressController object
mocked_process = MagicMock()
MockQProcess.return_value = mocked_process
controller = ImpressController(plugin=mock_plugin)
def test_get_text_from_page_valid_params(self):
"""
Test ImpressDocument.__get_text_from_page with valid parameters
"""
# GIVEN: mocked LibreOffice Document with one slide,
# two notes and three texts
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
# WHEN: start_process() is called
controller.start_process()
# WHEN: __get_text_from_page is called to get the Notes
result = self.doc._ImpressDocument__get_text_from_page(1, TextType.Notes)
# THEN: The correct methods should have been called
mocked_get_uno_command.assert_called_once()
MockQProcess.assert_called_once()
assert controller.process is mocked_process
mocked_process.startDetached.assert_called_once_with('libreoffice')
# THEN: result should be 'Note\nNote\n'
assert result == 'Note\nNote\n', 'Result should be \'Note\\n\' times the count of notes in the page'
# WHEN: get the Title
result = self.doc._ImpressDocument__get_text_from_page(1, TextType.Title)
def test_create_titles_and_notes(doc):
"""
Test ImpressDocument.create_titles_and_notes
"""
# GIVEN: mocked PresentationController.save_titles_and_notes with
# 0 pages and the LibreOffice Document
doc.save_titles_and_notes = MagicMock()
doc.document = MagicMock()
doc.document.getDrawPages.return_value = MagicMock()
doc.document.getDrawPages().getCount.return_value = 0
# THEN: result should be 'Title\n'
assert result == 'Title\n', 'Result should be exactly \'Title\\n\''
# WHEN reading the titles and notes
doc.create_titles_and_notes()
# WHEN: get all text
result = self.doc._ImpressDocument__get_text_from_page(1, TextType.SlideText)
# THEN save_titles_and_notes should have been called with empty arrays
doc.save_titles_and_notes.assert_called_once_with([], [])
# THEN: result should be 'Title\nString\nString\n'
assert result == 'Title\nString\nString\n', 'Result should be exactly \'Title\\nString\\nString\\n\''
# GIVEN: reset mock and set it to 2 pages
doc.save_titles_and_notes.reset_mock()
doc.document.getDrawPages().getCount.return_value = 2
def _mock_a_LibreOffice_document(self, page_count, note_count, text_count):
"""
Helper function, creates a mock libreoffice document.
# WHEN: a new call to create_titles_and_notes
doc.create_titles_and_notes()
:param page_count: Number of pages in the document
:param note_count: Number of note pages in the document
:param text_count: Number of text pages in the document
"""
pages = MagicMock()
page = MagicMock()
pages.getByIndex.return_value = page
notes_page = MagicMock()
notes_page.getCount.return_value = note_count
shape = MagicMock()
shape.supportsService.return_value = True
shape.getString.return_value = 'Note'
notes_page.getByIndex.return_value = shape
page.getNotesPage.return_value = notes_page
page.getCount.return_value = text_count
page.getByIndex.side_effect = self._get_page_shape_side_effect
pages.getCount.return_value = page_count
document = MagicMock()
document.getDrawPages.return_value = pages
document.getByIndex.return_value = page
return document
# THEN: save_titles_and_notes should have been called once with
# two arrays of two elements
# self.doc.save_titles_and_notes.assert_called_once_with(['\n', '\n'], [' ', ' '])
doc.save_titles_and_notes.assert_called_once_with(['', ''], [' ', ' '])
def _get_page_shape_side_effect(*args):
"""
Helper function.
"""
page_shape = MagicMock()
page_shape.supportsService.return_value = True
if args[1] == 0:
page_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
page_shape.getString.return_value = 'Title'
else:
page_shape.getString.return_value = 'String'
return page_shape
def test_get_text_from_page_out_of_bound(doc):
"""
Test ImpressDocument.__get_text_from_page with out-of-bounds index
"""
# GIVEN: mocked LibreOffice Document with one slide,
# two notes and three texts
doc.document = _mock_a_LibreOffice_document(1, 2, 3)
# WHEN: __get_text_from_page is called with an index of 0x00
result = doc._ImpressDocument__get_text_from_page(0, TextType.Notes)
# THEN: the result should be an empty string
assert result == '', 'Result should be an empty string'
# WHEN: regardless of the type of text, index 0x00 is out of bounds
result = doc._ImpressDocument__get_text_from_page(0, TextType.Title)
# THEN: result should be an empty string
assert result == '', 'Result should be an empty string'
# WHEN: when called with 2, it should also be out of bounds
result = doc._ImpressDocument__get_text_from_page(2, TextType.SlideText)
# THEN: result should be an empty string ... and, getByIndex should
# have never been called
assert result == '', 'Result should be an empty string'
assert doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
def test_get_text_from_page_wrong_type(doc):
"""
Test ImpressDocument.__get_text_from_page with wrong TextType
"""
# GIVEN: mocked LibreOffice Document with one slide, two notes and
# three texts
doc.document = _mock_a_LibreOffice_document(1, 2, 3)
# WHEN: called with TextType 3
result = doc._ImpressDocument__get_text_from_page(1, 3)
# THEN: result should be an empty string
assert result == '', 'Result should be and empty string'
assert doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
def test_get_text_from_page_valid_params(doc):
"""
Test ImpressDocument.__get_text_from_page with valid parameters
"""
# GIVEN: mocked LibreOffice Document with one slide,
# two notes and three texts
doc.document = _mock_a_LibreOffice_document(1, 2, 3)
# WHEN: __get_text_from_page is called to get the Notes
result = doc._ImpressDocument__get_text_from_page(1, TextType.Notes)
# THEN: result should be 'Note\nNote\n'
assert result == 'Note\nNote\n', 'Result should be \'Note\\n\' times the count of notes in the page'
# WHEN: get the Title
result = doc._ImpressDocument__get_text_from_page(1, TextType.Title)
# THEN: result should be 'Title\n'
assert result == 'Title\n', 'Result should be exactly \'Title\\n\''
# WHEN: get all text
result = doc._ImpressDocument__get_text_from_page(1, TextType.SlideText)
# THEN: result should be 'Title\nString\nString\n'
assert result == 'Title\nString\nString\n', 'Result should be exactly \'Title\\nString\\nString\\n\''
def _mock_a_LibreOffice_document(page_count, note_count, text_count):
"""
Helper function, creates a mock libreoffice document.
:param page_count: Number of pages in the document
:param note_count: Number of note pages in the document
:param text_count: Number of text pages in the document
"""
pages = MagicMock()
page = MagicMock()
pages.getByIndex.return_value = page
notes_page = MagicMock()
notes_page.getCount.return_value = note_count
shape = MagicMock()
shape.supportsService.return_value = True
shape.getString.return_value = 'Note'
notes_page.getByIndex.return_value = shape
page.getNotesPage.return_value = notes_page
page.getCount.return_value = text_count
page.getByIndex.side_effect = _get_page_shape_side_effect
pages.getCount.return_value = page_count
document = MagicMock()
document.getDrawPages.return_value = pages
document.getByIndex.return_value = page
return document
def _get_page_shape_side_effect(*args):
"""
Helper function.
"""
page_shape = MagicMock()
page_shape.supportsService.return_value = True
if args[0] == 0:
page_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
page_shape.getString.return_value = 'Title'
else:
page_shape.getString.return_value = 'String'
return page_shape

View File

@ -22,145 +22,130 @@
This module contains tests for the lib submodule of the Presentations plugin.
"""
from pathlib import Path
from unittest import TestCase
from unittest.mock import MagicMock, PropertyMock, call, patch
from openlp.core.common.registry import Registry
from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem
from tests.helpers.testmixin import TestMixin
class TestMediaItem(TestCase, TestMixin):
def test_build_file_mask_string(media_item):
"""
Test the mediaitem methods.
Test the build_file_mask_string() method
"""
def setUp(self):
"""
Set up the components need for all tests.
"""
Registry.create()
Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
self.setup_application()
# GIVEN: Different controllers.
impress_controller = MagicMock()
impress_controller.enabled.return_value = True
impress_controller.supports = ['odp']
impress_controller.also_supports = ['ppt']
presentation_controller = MagicMock()
presentation_controller.enabled.return_value = True
presentation_controller.supports = ['ppt']
presentation_controller.also_supports = []
presentation_viewer_controller = MagicMock()
presentation_viewer_controller.enabled.return_value = False
pdf_controller = MagicMock()
pdf_controller.enabled.return_value = True
pdf_controller.supports = ['pdf']
pdf_controller.also_supports = ['xps', 'oxps', 'epub', 'cbz', 'fb2']
# Mock the controllers.
media_item.controllers = {
'Impress': impress_controller,
'Powerpoint': presentation_controller,
'Powerpoint Viewer': presentation_viewer_controller,
'Pdf': pdf_controller
}
def test_build_file_mask_string(self):
"""
Test the build_file_mask_string() method
"""
# GIVEN: Different controllers.
impress_controller = MagicMock()
impress_controller.enabled.return_value = True
impress_controller.supports = ['odp']
impress_controller.also_supports = ['ppt']
presentation_controller = MagicMock()
presentation_controller.enabled.return_value = True
presentation_controller.supports = ['ppt']
presentation_controller.also_supports = []
presentation_viewer_controller = MagicMock()
presentation_viewer_controller.enabled.return_value = False
pdf_controller = MagicMock()
pdf_controller.enabled.return_value = True
pdf_controller.supports = ['pdf']
pdf_controller.also_supports = ['xps', 'oxps', 'epub', 'cbz', 'fb2']
# Mock the controllers.
self.media_item.controllers = {
'Impress': impress_controller,
'Powerpoint': presentation_controller,
'Powerpoint Viewer': presentation_viewer_controller,
'Pdf': pdf_controller
}
# WHEN: Build the file mask.
with patch('openlp.plugins.presentations.lib.mediaitem.translate') as mocked_translate:
mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate
media_item.build_file_mask_string()
# WHEN: Build the file mask.
with patch('openlp.plugins.presentations.lib.mediaitem.translate') as mocked_translate:
mocked_translate.side_effect = lambda module, string_to_translate: string_to_translate
self.media_item.build_file_mask_string()
# THEN: The file mask should be generated correctly
assert '*.odp' in media_item.on_new_file_masks, 'The file mask should contain the odp extension'
assert '*.ppt' in media_item.on_new_file_masks, 'The file mask should contain the ppt extension'
assert '*.pdf' in media_item.on_new_file_masks, 'The file mask should contain the pdf extension'
assert '*.xps' in media_item.on_new_file_masks, 'The file mask should contain the xps extension'
assert '*.oxps' in media_item.on_new_file_masks, 'The file mask should contain the oxps extension'
assert '*.epub' in media_item.on_new_file_masks, 'The file mask should contain the epub extension'
assert '*.cbz' in media_item.on_new_file_masks, 'The file mask should contain the cbz extension'
assert '*.fb2' in media_item.on_new_file_masks, 'The file mask should contain the fb2 extension'
# THEN: The file mask should be generated correctly
assert '*.odp' in self.media_item.on_new_file_masks, 'The file mask should contain the odp extension'
assert '*.ppt' in self.media_item.on_new_file_masks, 'The file mask should contain the ppt extension'
assert '*.pdf' in self.media_item.on_new_file_masks, 'The file mask should contain the pdf extension'
assert '*.xps' in self.media_item.on_new_file_masks, 'The file mask should contain the xps extension'
assert '*.oxps' in self.media_item.on_new_file_masks, 'The file mask should contain the oxps extension'
assert '*.epub' in self.media_item.on_new_file_masks, 'The file mask should contain the epub extension'
assert '*.cbz' in self.media_item.on_new_file_masks, 'The file mask should contain the cbz extension'
assert '*.fb2' in self.media_item.on_new_file_masks, 'The file mask should contain the fb2 extension'
def test_clean_up_thumbnails(self):
"""
Test that the clean_up_thumbnails method works as expected when files exists.
"""
# GIVEN: A mocked controller, and mocked os.path.getmtime
mocked_disabled_controller = MagicMock()
mocked_disabled_controller.enabled.return_value = False
mocked_disabled_supports = PropertyMock()
type(mocked_disabled_controller).supports = mocked_disabled_supports
mocked_enabled_controller = MagicMock()
mocked_enabled_controller.enabled.return_value = True
mocked_doc = MagicMock(**{'get_thumbnail_path.return_value': Path()})
mocked_enabled_controller.add_document.return_value = mocked_doc
mocked_enabled_controller.supports = ['tmp']
self.media_item.controllers = {
'Enabled': mocked_enabled_controller,
'Disabled': mocked_disabled_controller
}
def test_clean_up_thumbnails(media_item):
"""
Test that the clean_up_thumbnails method works as expected when files exists.
"""
# GIVEN: A mocked controller, and mocked os.path.getmtime
mocked_disabled_controller = MagicMock()
mocked_disabled_controller.enabled.return_value = False
mocked_disabled_supports = PropertyMock()
type(mocked_disabled_controller).supports = mocked_disabled_supports
mocked_enabled_controller = MagicMock()
mocked_enabled_controller.enabled.return_value = True
mocked_doc = MagicMock(**{'get_thumbnail_path.return_value': Path()})
mocked_enabled_controller.add_document.return_value = mocked_doc
mocked_enabled_controller.supports = ['tmp']
media_item.controllers = {
'Enabled': mocked_enabled_controller,
'Disabled': mocked_disabled_controller
}
thumb_path = MagicMock(st_mtime=100)
file_path = MagicMock(st_mtime=400)
with patch.object(Path, 'stat', side_effect=[thumb_path, file_path]), \
patch.object(Path, 'exists', return_value=True):
presentation_file = Path('file.tmp')
# WHEN: calling clean_up_thumbnails
self.media_item.clean_up_thumbnails(presentation_file, True)
# THEN: doc.presentation_deleted should have been called since the thumbnails mtime will be greater than
# the presentation_file's mtime.
mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
assert mocked_disabled_supports.call_count == 0
def test_clean_up_thumbnails_missing_file(self):
"""
Test that the clean_up_thumbnails method works as expected when file is missing.
"""
# GIVEN: A mocked controller, and mocked os.path.exists
mocked_controller = MagicMock()
mocked_doc = MagicMock()
mocked_controller.add_document.return_value = mocked_doc
mocked_controller.supports = ['tmp']
self.media_item.controllers = {
'Mocked': mocked_controller
}
thumb_path = MagicMock(st_mtime=100)
file_path = MagicMock(st_mtime=400)
with patch.object(Path, 'stat', side_effect=[thumb_path, file_path]), \
patch.object(Path, 'exists', return_value=True):
presentation_file = Path('file.tmp')
with patch.object(Path, 'exists', return_value=False):
# WHEN: calling clean_up_thumbnails
self.media_item.clean_up_thumbnails(presentation_file, True)
# WHEN: calling clean_up_thumbnails
media_item.clean_up_thumbnails(presentation_file, True)
# THEN: doc.presentation_deleted should have been called since the presentation file did not exists.
mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
# THEN: doc.presentation_deleted should have been called since the thumbnails mtime will be greater than
# the presentation_file's mtime.
mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
assert mocked_disabled_supports.call_count == 0
@patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup')
@patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item')
def test_search(self, *unreferenced_mocks):
"""
Test that the search method finds the correct results
"""
# GIVEN: A mocked Settings class which returns a list of Path objects,
# and an instance of the PresentationMediaItem
path_1 = Path('some_dir', 'Impress_file_1')
path_2 = Path('some_other_dir', 'impress_file_2')
path_3 = Path('another_dir', 'ppt_file')
mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = [path_1, path_2, path_3]
Registry().register('settings', mocked_returned_settings)
media_item = PresentationMediaItem(None, MagicMock(), None)
media_item.settings_section = ''
# WHEN: Calling search
results = media_item.search('IMPRE', False)
def test_clean_up_thumbnails_missing_file(media_item):
"""
Test that the clean_up_thumbnails method works as expected when file is missing.
"""
# GIVEN: A mocked controller, and mocked os.path.exists
mocked_controller = MagicMock()
mocked_doc = MagicMock()
mocked_controller.add_document.return_value = mocked_doc
mocked_controller.supports = ['tmp']
media_item.controllers = {
'Mocked': mocked_controller
}
presentation_file = Path('file.tmp')
with patch.object(Path, 'exists', return_value=False):
# THEN: The first two results should have been returned
assert results == [[str(path_1), 'Impress_file_1'], [str(path_2), 'impress_file_2']]
# WHEN: calling clean_up_thumbnails
media_item.clean_up_thumbnails(presentation_file, True)
# THEN: doc.presentation_deleted should have been called since the presentation file did not exists.
mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
@patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup')
@patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item')
def test_search(mock_setup, mock_item, registry):
"""
Test that the search method finds the correct results
"""
# GIVEN: A mocked Settings class which returns a list of Path objects,
# and an instance of the PresentationMediaItem
path_1 = Path('some_dir', 'Impress_file_1')
path_2 = Path('some_other_dir', 'impress_file_2')
path_3 = Path('another_dir', 'ppt_file')
mocked_returned_settings = MagicMock()
mocked_returned_settings.value.return_value = [path_1, path_2, path_3]
Registry().register('settings', mocked_returned_settings)
media_item = PresentationMediaItem(None, MagicMock(), None)
media_item.settings_section = ''
# WHEN: Calling search
results = media_item.search('IMPRE', False)
# THEN: The first two results should have been returned
assert results == [[str(path_1), 'Impress_file_1'], [str(path_2), 'impress_file_2']]

View File

@ -21,129 +21,108 @@
"""
This module contains tests for the lib submodule of the Presentations plugin.
"""
from unittest import TestCase
from unittest.mock import MagicMock, patch
from openlp.core.common.registry import Registry
from openlp.plugins.presentations.lib.mediaitem import MessageListener, PresentationMediaItem
from openlp.plugins.presentations.lib.mediaitem import MessageListener
from openlp.plugins.presentations.lib.messagelistener import Controller
from tests.helpers.testmixin import TestMixin
class TestMessageListener(TestCase, TestMixin):
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_presentation(media_mock, media_item):
"""
Test the Presentation Message Listener.
Find and chose a controller to play a presentations.
"""
def setUp(self):
"""
Set up the components need for all tests.
"""
Registry.create()
Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
controllers = {
'Powerpoint': mocked_controller
}
ml = MessageListener(media_item)
ml.media_item = media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_presentation(self, media_mock):
"""
Find and chose a controller to play a presentations.
"""
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
controllers = {
'Powerpoint': mocked_controller
}
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The controllers will be setup.
assert len(controllers) > 0, 'We have loaded a controller'
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_presentation_with_no_player(self, media_mock):
"""
Find and chose a controller to play a presentations when the player is not available.
"""
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
mocked_controller1 = MagicMock()
mocked_controller1.available = False
mocked_controller1.supports = ['ppt']
controllers = {
'Impress': mocked_controller,
'Powerpoint': mocked_controller1
}
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The controllers will be setup.
assert len(controllers) > 0, 'We have loaded a controller'
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_pdf_presentation(self, media_mock):
"""
Test the startup of pdf presentation succeed.
"""
# GIVEN: A sservice item with a pdf
mock_item = MagicMock()
mock_item.processor = 'Pdf'
mock_item.get_frame_path.return_value = "test.pdf"
self.media_item.generate_slide_data = MagicMock()
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml.preview_handler = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The handler should be set to None
assert ml.handler is None, 'The handler should be None'
# THEN: The controllers will be setup.
assert len(controllers) > 0, 'We have loaded a controller'
class TestController(TestCase, TestMixin):
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_presentation_with_no_player(media_mock, media_item):
"""
Test the Presentation Controller.
Find and chose a controller to play a presentations when the player is not available.
"""
# GIVEN: A single controller and service item wanting to use the controller
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
mocked_controller1 = MagicMock()
mocked_controller1.available = False
mocked_controller1.supports = ['ppt']
controllers = {
'Impress': mocked_controller,
'Powerpoint': mocked_controller1
}
ml = MessageListener(media_item)
ml.media_item = media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
def test_add_handler_failure(self):
"""
Test that add_handler does set doc.slidenumber to 0 in case filed loading
"""
# GIVEN: A Controller, a mocked doc-controller
controller = Controller(True)
mocked_doc_controller = MagicMock()
mocked_doc = MagicMock()
mocked_doc.load_presentation.return_value = False
mocked_doc_controller.add_document.return_value = mocked_doc
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# WHEN: calling add_handler that fails
controller.add_handler(mocked_doc_controller, MagicMock(), True, 0)
# THEN: The controllers will be setup.
assert len(controllers) > 0, 'We have loaded a controller'
# THEN: slidenumber should be 0
assert controller.doc.slidenumber == 0, 'doc.slidenumber should be 0'
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_pdf_presentation(media_mock, media_item):
"""
Test the startup of pdf presentation succeed.
"""
# GIVEN: A sservice item with a pdf
mock_item = MagicMock()
mock_item.processor = 'Pdf'
mock_item.get_frame_path.return_value = "test.pdf"
media_item.generate_slide_data = MagicMock()
ml = MessageListener(media_item)
ml.media_item = media_item
ml.preview_handler = MagicMock()
# WHEN: request the presentation to start
ml.startup([mock_item, False, False, False])
# THEN: The handler should be set to None
assert ml.handler is None, 'The handler should be None'
def test_add_handler_failure():
"""
Test that add_handler does set doc.slidenumber to 0 in case filed loading
"""
# GIVEN: A Controller, a mocked doc-controller
controller = Controller(True)
mocked_doc_controller = MagicMock()
mocked_doc = MagicMock()
mocked_doc.load_presentation.return_value = False
mocked_doc_controller.add_document.return_value = mocked_doc
# WHEN: calling add_handler that fails
controller.add_handler(mocked_doc_controller, MagicMock(), True, 0)
# THEN: slidenumber should be 0
assert controller.doc.slidenumber == 0, 'doc.slidenumber should be 0'

View File

@ -26,25 +26,30 @@ import pytest
from pathlib import Path
from shutil import rmtree, which
from tempfile import mkdtemp
from unittest import TestCase, skipIf
from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtGui
from openlp.core.common import is_macosx, is_linux, is_win
from openlp.core.common.settings import Settings
from openlp.core.common.registry import Registry
from openlp.core.display.screens import ScreenList
from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument
from tests.helpers.testmixin import TestMixin
from tests.utils.constants import RESOURCE_PATH
__default_settings__ = {
'presentations/enable_pdf_program': True,
'presentations/pdf_program': None,
'presentations/thumbnail_scheme': ''
}
@pytest.yield_fixture()
def pdf_env(settings, mock_plugin):
temp_folder_path = Path(mkdtemp())
thumbnail_folder_path = Path(mkdtemp())
desktop = MagicMock()
desktop.primaryScreen.return_value = SCREEN['primary']
desktop.screenCount.return_value = SCREEN['number']
desktop.screenGeometry.return_value = SCREEN['size']
ScreenList.create(desktop)
yield settings, mock_plugin, temp_folder_path, thumbnail_folder_path
rmtree(thumbnail_folder_path)
rmtree(temp_folder_path)
SCREEN = {
'primary': False,
@ -66,195 +71,178 @@ def get_screen_resolution():
from win32api import GetSystemMetrics
return GetSystemMetrics(0), GetSystemMetrics(1)
elif is_linux():
from Xlib.display import Display
resolution = Display().screen().root.get_geometry()
return resolution.width, resolution.height
if IS_CI:
return 1024, 768
else:
from Xlib.display import Display
resolution = Display().screen().root.get_geometry()
return resolution.width, resolution.height
else:
return 1024, 768
class TestPdfController(TestCase, TestMixin):
def test_constructor(settings, mock_plugin):
"""
Test the PdfController.
Test the Constructor from the PdfController
"""
def setUp(self):
"""
Set up the components need for all tests.
"""
Registry().create()
self.setup_application()
self.build_settings()
# Mocked out desktop object
self.desktop = MagicMock()
self.desktop.primaryScreen.return_value = SCREEN['primary']
self.desktop.screenCount.return_value = SCREEN['number']
self.desktop.screenGeometry.return_value = SCREEN['size']
Settings().extend_default_settings(__default_settings__)
Registry().register('settings', Settings())
self.screens = ScreenList.create(self.desktop)
self.temp_folder_path = Path(mkdtemp())
self.thumbnail_folder_path = Path(mkdtemp())
self.mock_plugin = MagicMock()
self.mock_plugin.settings_section = self.temp_folder_path
# GIVEN: No presentation controller
controller = None
def tearDown(self):
"""
Delete all the C++ objects at the end so that we don't have a segfault
"""
del self.screens
Registry().remove('settings')
self.destroy_settings()
rmtree(self.thumbnail_folder_path)
rmtree(self.temp_folder_path)
# WHEN: The presentation controller object is created
controller = PdfController(plugin=mock_plugin)
def test_constructor(self):
"""
Test the Constructor from the PdfController
"""
# GIVEN: No presentation controller
controller = None
# THEN: The name of the presentation controller should be correct
assert 'Pdf' == controller.name, 'The name of the presentation controller should be correct'
# WHEN: The presentation controller object is created
controller = PdfController(plugin=self.mock_plugin)
# THEN: The name of the presentation controller should be correct
assert 'Pdf' == controller.name, 'The name of the presentation controller should be correct'
def load_pdf(exe_path, pdf_env):
"""
Test loading a Pdf using the PdfController
"""
# GIVEN: A Pdf-file
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
@skipIf(IS_CI, "This is failing on CI, skip until we can figure out what the problem is")
def load_pdf(self, exe_path):
"""
Test loading a Pdf using the PdfController
"""
# GIVEN: A Pdf-file
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
# WHEN: The Pdf is loaded
settings = pdf_env[0]
mock_plugin = pdf_env[1]
temp_folder_path = pdf_env[2]
thumbnail_folder_path = pdf_env[3]
settings.setValue('presentations/pdf_program', exe_path)
controller = PdfController(plugin=mock_plugin)
controller.temp_folder = temp_folder_path
controller.thumbnail_folder = thumbnail_folder_path
document = PdfDocument(controller, test_file_path)
loaded = document.load_presentation()
# WHEN: The Pdf is loaded
Settings().setValue('presentations/pdf_program', exe_path)
controller = PdfController(plugin=self.mock_plugin)
controller.temp_folder = self.temp_folder_path
controller.thumbnail_folder = self.thumbnail_folder_path
document = PdfDocument(controller, test_file_path)
loaded = document.load_presentation()
# THEN: The load should succeed and we should be able to get a pagecount
assert loaded is True, 'The loading of the PDF should succeed.'
assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.'
# THEN: The load should succeed and we should be able to get a pagecount
assert loaded is True, 'The loading of the PDF should succeed.'
assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.'
def load_pdf_pictures(self, exe_path):
"""
Test loading a Pdf and check the generated pictures' size
"""
# GIVEN: A Pdf-file
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
def load_pdf_pictures(exe_path, pdf_env):
"""
Test loading a Pdf and check the generated pictures' size
"""
# GIVEN: A Pdf-file
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
# WHEN: The Pdf is loaded
Settings().setValue('presentations/pdf_program', exe_path)
controller = PdfController(plugin=self.mock_plugin)
controller.temp_folder = self.temp_folder_path
controller.thumbnail_folder = self.thumbnail_folder_path
document = PdfDocument(controller, test_file_path)
loaded = document.load_presentation()
# WHEN: The Pdf is loaded
mock_plugin = pdf_env[1]
temp_folder_path = pdf_env[2]
thumbnail_folder_path = pdf_env[3]
Settings().setValue('presentations/pdf_program', exe_path)
controller = PdfController(plugin=mock_plugin)
controller.temp_folder = temp_folder_path
controller.thumbnail_folder = thumbnail_folder_path
document = PdfDocument(controller, test_file_path)
loaded = document.load_presentation()
# THEN: The load should succeed and pictures should be created and have been scaled to fit the screen
assert loaded is True, 'The loading of the PDF should succeed.'
image = QtGui.QImage(os.path.join(str(self.temp_folder_path), 'pdf_test1.pdf', 'mainslide001.png'))
# Based on the converter used the resolution will differ a bit
if controller.gsbin:
assert 1076 == image.height(), 'The height should be 1076'
assert 760 == image.width(), 'The width should be 760'
else:
width, height = get_screen_resolution()
# Calculate the width of the PDF based on the aspect ratio of the PDF
width = int(round(height * 0.70703125, 0))
assert image.height() == height, 'The height should be {height}'.format(height=height)
assert image.width() == width, 'The width should be {width}'.format(width=width)
# THEN: The load should succeed and pictures should be created and have been scaled to fit the screen
assert loaded is True, 'The loading of the PDF should succeed.'
image = QtGui.QImage(os.path.join(str(temp_folder_path), 'pdf_test1.pdf', 'mainslide001.png'))
# Based on the converter used the resolution will differ a bit
if controller.gsbin:
assert 1076 == image.height(), 'The height should be 1076'
assert 760 == image.width(), 'The width should be 760'
else:
width, height = get_screen_resolution()
# Calculate the width of the PDF based on the aspect ratio of the PDF
width = int(round(height * 0.70703125, 0))
assert image.height() == height, 'The height should be {height}'.format(height=height)
assert image.width() == width, 'The width should be {width}'.format(width=width)
def test_load_pdf(self):
"""
Test loading a Pdf with each of the installed backends
"""
for exe_name in ['gs', 'mutool', 'mudraw']:
exe_path = which(exe_name)
if exe_path:
self.load_pdf(exe_path)
self.load_pdf_pictures(exe_path)
def test_loading_pdf_using_pymupdf(self):
try:
import fitz # noqa: F401
except ImportError:
pytest.skip('PyMuPDF is not installed')
def test_load_pdf(pdf_env):
"""
Test loading a Pdf with each of the installed backends
"""
for exe_name in ['gs', 'mutool', 'mudraw']:
exe_path = which(exe_name)
if exe_path:
load_pdf(exe_path, pdf_env)
load_pdf_pictures(exe_path, pdf_env)
self.load_pdf(None)
self.load_pdf_pictures(None)
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_mudraw(self, mocked_check_binary_exists):
"""
Test that the correct output from mudraw is detected
"""
# GIVEN: A mocked check_binary_exists that returns mudraw output
mudraw_output = (b'usage: mudraw [options] input [pages]\n\t-o -\toutput filename (%d for page number)n\t\tsupp'
b'orted formats: pgm, ppm, pam, png, pbmn\t-p -\tpasswordn\t-r -\tresolution in dpi (default: '
b'72)n\t-w -\twidth (in pixels) (maximum width if -r is specified)n\t-h -\theight (in pixels) '
b'(maximum height if -r is specified)')
mocked_check_binary_exists.return_value = mudraw_output
def test_loading_pdf_using_pymupdf():
try:
import fitz # noqa: F401
except ImportError:
pytest.skip('PyMuPDF is not installed')
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
load_pdf(None)
load_pdf_pictures(None)
# THEN: mudraw should be detected
assert 'mudraw' == ret, 'mudraw should have been detected'
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_new_motool(self, mocked_check_binary_exists):
"""
Test that the correct output from the new mutool is detected
"""
# GIVEN: A mocked check_binary_exists that returns new mutool output
new_mutool_output = (b'usage: mutool <command> [options]\n\tdraw\t-- convert document\n\trun\t-- run javascript'
b'\n\tclean\t-- rewrite pdf file\n\textract\t-- extract font and image resources\n\tinfo\t'
b'-- show information about pdf resources\n\tpages\t-- show information about pdf pages\n'
b'\tposter\t-- split large page into many tiles\n\tshow\t-- show internal pdf objects\n\t'
b'create\t-- create pdf document\n\tmerge\t-- merge pages from multiple pdf sources into a'
b'new pdf\n')
mocked_check_binary_exists.return_value = new_mutool_output
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_mudraw(mocked_check_binary_exists):
"""
Test that the correct output from mudraw is detected
"""
# GIVEN: A mocked check_binary_exists that returns mudraw output
mudraw_output = (b'usage: mudraw [options] input [pages]\n\t-o -\toutput filename (%d for page number)n\t\tsupp'
b'orted formats: pgm, ppm, pam, png, pbmn\t-p -\tpasswordn\t-r -\tresolution in dpi (default: '
b'72)n\t-w -\twidth (in pixels) (maximum width if -r is specified)n\t-h -\theight (in pixels) '
b'(maximum height if -r is specified)')
mocked_check_binary_exists.return_value = mudraw_output
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
# THEN: mutool should be detected
assert 'mutool' == ret, 'mutool should have been detected'
# THEN: mudraw should be detected
assert 'mudraw' == ret, 'mudraw should have been detected'
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_old_motool(self, mocked_check_binary_exists):
"""
Test that the output from the old mutool is not accepted
"""
# GIVEN: A mocked check_binary_exists that returns old mutool output
old_mutool_output = (b'usage: mutool <command> [options]\n\tclean\t-- rewrite pdf file\n\textract\t-- extract '
b'font and image resources\n\tinfo\t-- show information about pdf resources\n\tposter\t-- '
b'split large page into many tiles\n\tshow\t-- show internal pdf objects')
mocked_check_binary_exists.return_value = old_mutool_output
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_new_motool(mocked_check_binary_exists):
"""
Test that the correct output from the new mutool is detected
"""
# GIVEN: A mocked check_binary_exists that returns new mutool output
new_mutool_output = (b'usage: mutool <command> [options]\n\tdraw\t-- convert document\n\trun\t-- run javascript'
b'\n\tclean\t-- rewrite pdf file\n\textract\t-- extract font and image resources\n\tinfo\t'
b'-- show information about pdf resources\n\tpages\t-- show information about pdf pages\n'
b'\tposter\t-- split large page into many tiles\n\tshow\t-- show internal pdf objects\n\t'
b'create\t-- create pdf document\n\tmerge\t-- merge pages from multiple pdf sources into a'
b'new pdf\n')
mocked_check_binary_exists.return_value = new_mutool_output
# THEN: mutool should be detected
assert ret is None, 'old mutool should not be accepted!'
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_gs(self, mocked_check_binary_exists):
"""
Test that the correct output from gs is detected
"""
# GIVEN: A mocked check_binary_exists that returns gs output
gs_output = (b'GPL Ghostscript 9.19 (2016-03-23)\nCopyright (C) 2016 Artifex Software, Inc. All rights reserv'
b'ed.\nUsage: gs [switches] [file1.ps file2.ps ...]')
mocked_check_binary_exists.return_value = gs_output
# THEN: mutool should be detected
assert 'mutool' == ret, 'mutool should have been detected'
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
# THEN: mutool should be detected
assert 'gs' == ret, 'mutool should have been detected'
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_old_motool(mocked_check_binary_exists):
"""
Test that the output from the old mutool is not accepted
"""
# GIVEN: A mocked check_binary_exists that returns old mutool output
old_mutool_output = (b'usage: mutool <command> [options]\n\tclean\t-- rewrite pdf file\n\textract\t-- extract '
b'font and image resources\n\tinfo\t-- show information about pdf resources\n\tposter\t-- '
b'split large page into many tiles\n\tshow\t-- show internal pdf objects')
mocked_check_binary_exists.return_value = old_mutool_output
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
# THEN: mutool should be detected
assert ret is None, 'old mutool should not be accepted!'
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_gs(mocked_check_binary_exists):
"""
Test that the correct output from gs is detected
"""
# GIVEN: A mocked check_binary_exists that returns gs output
gs_output = (b'GPL Ghostscript 9.19 (2016-03-23)\nCopyright (C) 2016 Artifex Software, Inc. All rights reserv'
b'ed.\nUsage: gs [switches] [file1.ps file2.ps ...]')
mocked_check_binary_exists.return_value = gs_output
# WHEN: Calling process_check_binary
ret = PdfController.process_check_binary('test')
# THEN: mutool should be detected
assert 'gs' == ret, 'mutool should have been detected'

View File

@ -21,287 +21,208 @@
"""
Functional tests to test the PowerPointController class and related methods.
"""
import os
import shutil
from tempfile import mkdtemp
from unittest import TestCase
import pytest
from unittest.mock import MagicMock, patch
from openlp.core.common import is_win
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.plugins.presentations.lib.powerpointcontroller import PowerpointController, PowerpointDocument, \
_get_text_from_shapes
from tests.helpers.testmixin import TestMixin
from tests.utils.constants import TEST_RESOURCES_PATH
if is_win():
import pywintypes
__default_settings__ = {
'presentations/powerpoint slide click advance': True
}
@pytest.fixture()
def get_thumbnail_folder(settings):
gtf = patch('openlp.plugins.presentations.lib.powerpointcontroller.PresentationDocument._setup')
yield gtf.start()
gtf.stop()
class TestPowerpointController(TestCase, TestMixin):
def test_constructor(settings, mock_plugin):
"""
Test the PowerpointController Class
Test the Constructor from the PowerpointController
"""
# GIVEN: No presentation controller
controller = None
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
self.setup_application()
self.build_settings()
self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp()
self.mock_plugin.settings_section = self.temp_folder
Registry.create()
Registry().register('settings', Settings())
# WHEN: The presentation controller object is created
controller = PowerpointController(plugin=mock_plugin)
def tearDown(self):
"""
Stop the patches
"""
self.destroy_settings()
shutil.rmtree(self.temp_folder)
def test_constructor(self):
"""
Test the Constructor from the PowerpointController
"""
# GIVEN: No presentation controller
controller = None
# WHEN: The presentation controller object is created
controller = PowerpointController(plugin=self.mock_plugin)
# THEN: The name of the presentation controller should be correct
assert 'Powerpoint' == controller.name, 'The name of the presentation controller should be correct'
# THEN: The name of the presentation controller should be correct
assert 'Powerpoint' == controller.name, 'The name of the presentation controller should be correct'
class TestPowerpointDocument(TestCase, TestMixin):
def test_show_error_msg():
"""
Test the PowerpointDocument Class
Test the PowerpointDocument.show_error_msg() method gets called on com exception
"""
if is_win():
# GIVEN: A PowerpointDocument with mocked controller and presentation
with patch('openlp.plugins.presentations.lib.powerpointcontroller.critical_error_message_box') as \
mocked_critical_error_message_box:
instance = PowerpointDocument(MagicMock(), MagicMock())
instance.presentation = MagicMock()
instance.presentation.SlideShowWindow.View.GotoSlide = MagicMock(side_effect=pywintypes.com_error('1'))
instance.index_map[42] = 42
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
Registry.create()
Registry().register('settings', Settings())
self.setup_application()
self.build_settings()
self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp()
self.mock_plugin.settings_section = self.temp_folder
self.powerpoint_document_stop_presentation_patcher = patch(
'openlp.plugins.presentations.lib.powerpointcontroller.PowerpointDocument.stop_presentation')
self.presentation_document_get_temp_folder_patcher = patch(
'openlp.plugins.presentations.lib.powerpointcontroller.PresentationDocument.get_temp_folder')
self.presentation_document_setup_patcher = patch(
'openlp.plugins.presentations.lib.powerpointcontroller.PresentationDocument._setup')
self.mock_powerpoint_document_stop_presentation = self.powerpoint_document_stop_presentation_patcher.start()
self.mock_presentation_document_get_temp_folder = self.presentation_document_get_temp_folder_patcher.start()
self.mock_presentation_document_setup = self.presentation_document_setup_patcher.start()
self.mock_controller = MagicMock()
self.mock_presentation = MagicMock()
self.mock_presentation_document_get_temp_folder.return_value = 'temp folder'
self.file_name = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx')
self.real_controller = PowerpointController(self.mock_plugin)
Settings().extend_default_settings(__default_settings__)
# WHEN: Calling goto_slide which will throw an exception
instance.goto_slide(42)
def tearDown(self):
"""
Stop the patches
"""
self.powerpoint_document_stop_presentation_patcher.stop()
self.presentation_document_get_temp_folder_patcher.stop()
self.presentation_document_setup_patcher.stop()
self.destroy_settings()
shutil.rmtree(self.temp_folder)
# THEN: mocked_critical_error_message_box should have been called
mocked_critical_error_message_box.assert_called_with('Error', 'An error occurred in the PowerPoint '
'integration and the presentation will be stopped.'
' Restart the presentation if you wish to '
'present it.')
def test_show_error_msg(self):
"""
Test the PowerpointDocument.show_error_msg() method gets called on com exception
"""
if is_win():
# GIVEN: A PowerpointDocument with mocked controller and presentation
with patch('openlp.plugins.presentations.lib.powerpointcontroller.critical_error_message_box') as \
mocked_critical_error_message_box:
instance = PowerpointDocument(self.mock_controller, self.mock_presentation)
instance.presentation = MagicMock()
instance.presentation.SlideShowWindow.View.GotoSlide = MagicMock(side_effect=pywintypes.com_error('1'))
instance.index_map[42] = 42
# WHEN: Calling goto_slide which will throw an exception
instance.goto_slide(42)
def test_create_titles_and_notes(get_thumbnail_folder):
"""
Test creating the titles from PowerPoint
"""
# GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.get_slide_count = MagicMock()
doc.get_slide_count.return_value = 2
doc.index_map = {1: 1, 2: 2}
doc.save_titles_and_notes = MagicMock()
doc._PowerpointDocument__get_text_from_shapes = MagicMock()
slide = MagicMock()
slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText'
pres = MagicMock()
pres.Slides = MagicMock(side_effect=[slide, slide])
doc.presentation = pres
# THEN: mocked_critical_error_message_box should have been called
mocked_critical_error_message_box.assert_called_with('Error', 'An error occurred in the PowerPoint '
'integration and the presentation will be stopped.'
' Restart the presentation if you wish to '
'present it.')
# WHEN reading the titles and notes
doc.create_titles_and_notes()
# add _test to the following if necessary
def verify_loading_document(self):
"""
Test loading a document in PowerPoint
"""
if is_win() and self.real_controller.check_available():
# GIVEN: A PowerpointDocument and a presentation
doc = PowerpointDocument(self.real_controller, self.file_name)
# THEN the save should have been called exactly once with 2 titles and 2 notes
doc.save_titles_and_notes.assert_called_once_with(['SlideText', 'SlideText'], [' ', ' '])
# WHEN: loading the filename
doc.load_presentation()
result = doc.is_loaded()
# THEN: result should be true
assert result is True, 'The result should be True'
else:
self.skipTest('Powerpoint not available, skipping test.')
def test_create_titles_and_notes_with_no_slides(get_thumbnail_folder):
"""
Test creating the titles from PowerPoint when it returns no slides
"""
# GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.save_titles_and_notes = MagicMock()
doc._PowerpointDocument__get_text_from_shapes = MagicMock()
pres = MagicMock()
pres.Slides = []
doc.presentation = pres
def test_create_titles_and_notes(self):
"""
Test creating the titles from PowerPoint
"""
# GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
self.doc = PowerpointDocument(self.mock_controller, self.file_name)
self.doc.get_slide_count = MagicMock()
self.doc.get_slide_count.return_value = 2
self.doc.index_map = {1: 1, 2: 2}
self.doc.save_titles_and_notes = MagicMock()
self.doc._PowerpointDocument__get_text_from_shapes = MagicMock()
slide = MagicMock()
slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText'
pres = MagicMock()
pres.Slides = MagicMock(side_effect=[slide, slide])
self.doc.presentation = pres
# WHEN reading the titles and notes
doc.create_titles_and_notes()
# WHEN reading the titles and notes
self.doc.create_titles_and_notes()
# THEN the save should have been called exactly once with empty titles and notes
doc.save_titles_and_notes.assert_called_once_with([], [])
# THEN the save should have been called exactly once with 2 titles and 2 notes
self.doc.save_titles_and_notes.assert_called_once_with(['SlideText', 'SlideText'], [' ', ' '])
def test_create_titles_and_notes_with_no_slides(self):
"""
Test creating the titles from PowerPoint when it returns no slides
"""
# GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides
doc = PowerpointDocument(self.mock_controller, self.file_name)
doc.save_titles_and_notes = MagicMock()
doc._PowerpointDocument__get_text_from_shapes = MagicMock()
pres = MagicMock()
pres.Slides = []
doc.presentation = pres
def test_get_text_from_shapes():
"""
Test getting text from powerpoint shapes
"""
# GIVEN: mocked shapes
shape = MagicMock()
shape.PlaceholderFormat.Type = 2
shape.HasTextFrame = shape.TextFrame.HasText = True
shape.TextFrame.TextRange.Text = 'slideText'
shapes = [shape, shape]
# WHEN reading the titles and notes
doc.create_titles_and_notes()
# WHEN: getting the text
result = _get_text_from_shapes(shapes)
# THEN the save should have been called exactly once with empty titles and notes
doc.save_titles_and_notes.assert_called_once_with([], [])
# THEN: it should return the text
assert result == 'slideText\nslideText\n', 'result should match \'slideText\nslideText\n\''
def test_get_text_from_shapes(self):
"""
Test getting text from powerpoint shapes
"""
# GIVEN: mocked shapes
shape = MagicMock()
shape.PlaceholderFormat.Type = 2
shape.HasTextFrame = shape.TextFrame.HasText = True
shape.TextFrame.TextRange.Text = 'slideText'
shapes = [shape, shape]
# WHEN: getting the text
result = _get_text_from_shapes(shapes)
def test_get_text_from_shapes_with_no_shapes():
"""
Test getting text from powerpoint shapes with no shapes
"""
# GIVEN: empty shapes array
shapes = []
# THEN: it should return the text
assert result == 'slideText\nslideText\n', 'result should match \'slideText\nslideText\n\''
# WHEN: getting the text
result = _get_text_from_shapes(shapes)
def test_get_text_from_shapes_with_no_shapes(self):
"""
Test getting text from powerpoint shapes with no shapes
"""
# GIVEN: empty shapes array
shapes = []
# THEN: it should not fail but return empty string
assert result == '', 'result should be empty'
# WHEN: getting the text
result = _get_text_from_shapes(shapes)
# THEN: it should not fail but return empty string
assert result == '', 'result should be empty'
def test_goto_slide(get_thumbnail_folder):
"""
Test that goto_slide goes to next effect if the slide is already displayed
"""
# GIVEN: A Document with mocked controller, presentation, and mocked functions get_slide_number and next_step
Registry().get('settings').setValue('presentations/powerpoint slide click advance', True)
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 1
doc.presentation.SlideShowWindow.View.GetClickCount.return_value = 2
doc.get_slide_number = MagicMock()
doc.get_slide_number.return_value = 1
doc.next_step = MagicMock()
doc.index_map[1] = 1
def test_goto_slide(self):
"""
Test that goto_slide goes to next effect if the slide is already displayed
"""
# GIVEN: A Document with mocked controller, presentation, and mocked functions get_slide_number and next_step
doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 1
doc.presentation.SlideShowWindow.View.GetClickCount.return_value = 2
doc.get_slide_number = MagicMock()
doc.get_slide_number.return_value = 1
doc.next_step = MagicMock()
doc.index_map[1] = 1
# WHEN: Calling goto_slide
doc.goto_slide(1)
# WHEN: Calling goto_slide
doc.goto_slide(1)
# THEN: next_step() should be call to try to advance to the next effect.
assert doc.next_step.called is True, 'next_step() should have been called!'
# THEN: next_step() should be call to try to advance to the next effect.
assert doc.next_step.called is True, 'next_step() should have been called!'
def test_blank_screen(self):
"""
Test that blank_screen works as expected
"""
# GIVEN: A Document with mocked controller, presentation, and mocked function get_slide_number
doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
def test_blank_screen(get_thumbnail_folder):
"""
Test that blank_screen works as expected
"""
# GIVEN: A Document with mocked controller, presentation, and mocked function get_slide_number
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
doc.presentation.Application.Version = 14.0
doc.get_slide_number = MagicMock()
doc.get_slide_number.return_value = 2
# WHEN: Calling goto_slide
doc.blank_screen()
# THEN: The view state, doc.blank_slide and doc.blank_click should have new values
assert doc.presentation.SlideShowWindow.View.State == 3, 'The View State should be 3'
assert doc.blank_slide == 2, 'doc.blank_slide should be 2 because of the PowerPoint version'
assert doc.blank_click == 3, 'doc.blank_click should be 3 because of the PowerPoint version'
def test_unblank_screen(get_thumbnail_folder):
"""
Test that unblank_screen works as expected
"""
# GIVEN: A Document with mocked controller, presentation, ScreenList, and mocked function get_slide_number
with patch('openlp.plugins.presentations.lib.powerpointcontroller.ScreenList') as mocked_screen_list:
mocked_screen_list_ret = MagicMock()
mocked_screen_list_ret.screen_list = [1]
mocked_screen_list.return_value = mocked_screen_list_ret
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
doc.presentation.Application.Version = 14.0
doc.get_slide_number = MagicMock()
doc.get_slide_number.return_value = 2
doc.index_map[1] = 1
doc.blank_slide = 1
doc.blank_click = 1
# WHEN: Calling goto_slide
doc.blank_screen()
doc.unblank_screen()
# THEN: The view state, doc.blank_slide and doc.blank_click should have new values
assert doc.presentation.SlideShowWindow.View.State == 3, 'The View State should be 3'
assert doc.blank_slide == 2, 'doc.blank_slide should be 2 because of the PowerPoint version'
assert doc.blank_click == 3, 'doc.blank_click should be 3 because of the PowerPoint version'
def test_unblank_screen(self):
"""
Test that unblank_screen works as expected
"""
# GIVEN: A Document with mocked controller, presentation, ScreenList, and mocked function get_slide_number
with patch('openlp.plugins.presentations.lib.powerpointcontroller.ScreenList') as mocked_screen_list:
mocked_screen_list_ret = MagicMock()
mocked_screen_list_ret.screen_list = [1]
mocked_screen_list.return_value = mocked_screen_list_ret
doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
doc.presentation.Application.Version = 14.0
doc.get_slide_number = MagicMock()
doc.get_slide_number.return_value = 2
doc.index_map[1] = 1
doc.blank_slide = 1
doc.blank_click = 1
# WHEN: Calling goto_slide
doc.unblank_screen()
# THEN: The view state have new value, and several function should have been called
assert doc.presentation.SlideShowWindow.View.State == 1, 'The View State should be 1'
assert doc.presentation.SlideShowWindow.Activate.called is True, \
'SlideShowWindow.Activate should have been called'
assert doc.presentation.SlideShowWindow.View.GotoSlide.called is True, \
'View.GotoSlide should have been called because of the PowerPoint version'
assert doc.presentation.SlideShowWindow.View.GotoClick.called is True, \
'View.GotoClick should have been called because of the PowerPoint version'
# THEN: The view state have new value, and several function should have been called
assert doc.presentation.SlideShowWindow.View.State == 1, 'The View State should be 1'
assert doc.presentation.SlideShowWindow.Activate.called is True, \
'SlideShowWindow.Activate should have been called'
assert doc.presentation.SlideShowWindow.View.GotoSlide.called is True, \
'View.GotoSlide should have been called because of the PowerPoint version'
assert doc.presentation.SlideShowWindow.View.GotoClick.called is True, \
'View.GotoClick should have been called because of the PowerPoint version'

View File

@ -1,224 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2020 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, either version 3 of the License, or #
# (at your option) any later version. #
# #
# 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, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
This module contains tests for the pptviewcontroller module of the Presentations plugin.
"""
import shutil
from tempfile import mkdtemp
from unittest import TestCase, skipIf
from unittest.mock import MagicMock, patch
from openlp.core.common import is_win
from openlp.core.common.path import Path
from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument, PptviewController
from tests.helpers.testmixin import TestMixin
from tests.utils.constants import RESOURCE_PATH
class TestPptviewController(TestCase, TestMixin):
"""
Test the PptviewController Class
"""
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
self.setup_application()
self.build_settings()
self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp()
self.mock_plugin.settings_section = self.temp_folder
def tearDown(self):
"""
Stop the patches
"""
self.destroy_settings()
shutil.rmtree(self.temp_folder)
def test_constructor(self):
"""
Test the Constructor from the PptViewController
"""
# GIVEN: No presentation controller
controller = None
# WHEN: The presentation controller object is created
controller = PptviewController(plugin=self.mock_plugin)
# THEN: The name of the presentation controller should be correct
assert 'Powerpoint Viewer' == controller.name, 'The name of the presentation controller should be correct'
@skipIf(not is_win(), 'Not Windows')
@patch('openlp.plugins.presentations.lib.pptviewcontroller.cdll.LoadLibrary')
def test_check_available(self, mocked_load_library):
"""
Test check_available / check_installed
"""
# GIVEN: A mocked dll loader and a controller
mocked_process = MagicMock()
mocked_process.CheckInstalled.return_value = True
mocked_load_library.return_value = mocked_process
controller = PptviewController(plugin=self.mock_plugin)
# WHEN: check_available is called
available = controller.check_available()
# THEN: On windows it should return True, on other platforms False
assert available is True, 'check_available should return True on windows.'
class TestPptviewDocument(TestCase):
"""
Test the PptviewDocument Class
"""
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
self.pptview_document_create_thumbnails_patcher = patch(
'openlp.plugins.presentations.lib.pptviewcontroller.PptviewDocument.create_thumbnails')
self.pptview_document_stop_presentation_patcher = patch(
'openlp.plugins.presentations.lib.pptviewcontroller.PptviewDocument.stop_presentation')
self.presentation_document_get_temp_folder_patcher = patch(
'openlp.plugins.presentations.lib.pptviewcontroller.PresentationDocument.get_temp_folder')
self.presentation_document_setup_patcher = patch(
'openlp.plugins.presentations.lib.pptviewcontroller.PresentationDocument._setup')
self.screen_list_patcher = patch('openlp.plugins.presentations.lib.pptviewcontroller.ScreenList')
self.rect_patcher = MagicMock()
self.mock_pptview_document_create_thumbnails = self.pptview_document_create_thumbnails_patcher.start()
self.mock_pptview_document_stop_presentation = self.pptview_document_stop_presentation_patcher.start()
self.mock_presentation_document_get_temp_folder = self.presentation_document_get_temp_folder_patcher.start()
self.mock_presentation_document_setup = self.presentation_document_setup_patcher.start()
self.mock_rect = self.rect_patcher.start()
self.mock_screen_list = self.screen_list_patcher.start()
self.mock_controller = MagicMock()
self.mock_presentation = MagicMock()
self.temp_folder = mkdtemp()
self.mock_presentation_document_get_temp_folder.return_value = self.temp_folder
def tearDown(self):
"""
Stop the patches
"""
self.pptview_document_create_thumbnails_patcher.stop()
self.pptview_document_stop_presentation_patcher.stop()
self.presentation_document_get_temp_folder_patcher.stop()
self.presentation_document_setup_patcher.stop()
self.rect_patcher.stop()
self.screen_list_patcher.stop()
shutil.rmtree(self.temp_folder)
@skipIf(not is_win(), 'Not Windows')
def test_load_presentation_succesful(self):
"""
Test the PptviewDocument.load_presentation() method when the PPT is successfully opened
"""
# GIVEN: A reset mocked_os
self.mock_controller.process.OpenPPT.return_value = 0
instance = PptviewDocument(self.mock_controller, self.mock_presentation)
instance.file_path = 'test\path.ppt'
# WHEN: The temporary directory exists and OpenPPT returns successfully (not -1)
result = instance.load_presentation()
# THEN: PptviewDocument.load_presentation should return True
assert result is True
@skipIf(not is_win(), 'Not Windows')
def test_load_presentation_un_succesful(self):
"""
Test the PptviewDocument.load_presentation() method when the temporary directory does not exist and the PPT is
not successfully opened
"""
# GIVEN: A reset mock_os_isdir
self.mock_controller.process.OpenPPT.return_value = -1
instance = PptviewDocument(self.mock_controller, self.mock_presentation)
instance.file_path = 'test\path.ppt'
# WHEN: The temporary directory does not exist and OpenPPT returns unsuccessfully (-1)
with patch.object(instance, 'get_temp_folder') as mocked_get_folder:
mocked_get_folder.return_value = MagicMock(spec=Path)
result = instance.load_presentation()
# THEN: The temp folder should be created and PptviewDocument.load_presentation should return False
assert result is False
def test_create_titles_and_notes(self):
"""
Test PowerpointController.create_titles_and_notes
"""
# GIVEN: mocked PresentationController.save_titles_and_notes and a pptx file
doc = PptviewDocument(self.mock_controller, self.mock_presentation)
doc.file_path = RESOURCE_PATH / 'presentations' / 'test.pptx'
doc.save_titles_and_notes = MagicMock()
# WHEN reading the titles and notes
doc.create_titles_and_notes()
# THEN save_titles_and_notes should have been called once with empty arrays
doc.save_titles_and_notes.assert_called_once_with(['Test 1\n', '\n', 'Test 2\n', 'Test 4\n', 'Test 3\n'],
['Notes for slide 1', 'Inserted', 'Notes for slide 2',
'Notes \nfor slide 4', 'Notes for slide 3'])
def test_create_titles_and_notes_nonexistent_file(self):
"""
Test PowerpointController.create_titles_and_notes with nonexistent file
"""
# GIVEN: mocked PresentationController.save_titles_and_notes and an nonexistent file
with patch('builtins.open') as mocked_open, \
patch.object(Path, 'exists') as mocked_path_exists, \
patch('openlp.plugins.presentations.lib.presentationcontroller.create_paths') as \
mocked_dir_exists:
mocked_path_exists.return_value = False
mocked_dir_exists.return_value = False
doc = PptviewDocument(self.mock_controller, self.mock_presentation)
doc.file_path = Path('Idontexist.pptx')
doc.save_titles_and_notes = MagicMock()
# WHEN: Reading the titles and notes
doc.create_titles_and_notes()
# THEN: File existens should have been checked, and not have been opened.
doc.save_titles_and_notes.assert_called_once_with(None, None)
mocked_path_exists.assert_called_with()
assert mocked_open.call_count == 0, 'There should be no calls to open a file.'
def test_create_titles_and_notes_invalid_file(self):
"""
Test PowerpointController.create_titles_and_notes with invalid file
"""
# GIVEN: mocked PresentationController.save_titles_and_notes and an invalid file
with patch('builtins.open') as mocked_open, \
patch('openlp.plugins.presentations.lib.pptviewcontroller.zipfile.is_zipfile') as mocked_is_zf:
mocked_is_zf.return_value = False
mocked_open.filesize = 10
doc = PptviewDocument(self.mock_controller, self.mock_presentation)
doc.file_path = RESOURCE_PATH / 'presentations' / 'test.ppt'
doc.save_titles_and_notes = MagicMock()
# WHEN: reading the titles and notes
doc.create_titles_and_notes()
# THEN:
doc.save_titles_and_notes.assert_called_once_with(None, None)
assert mocked_is_zf.call_count == 1, 'is_zipfile should have been called once'

View File

@ -22,213 +22,196 @@
Functional tests to test the PresentationController and PresentationDocument
classes and related methods.
"""
import pytest
from pathlib import Path
from unittest import TestCase
from unittest.mock import MagicMock, call, patch
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
FOLDER_TO_PATCH = 'openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder'
class TestPresentationController(TestCase):
@pytest.yield_fixture()
def get_thumbnail_folder(settings):
gtf = patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder',
return_value=Path())
yield gtf.start()
gtf.stop()
@pytest.yield_fixture()
def create_paths(settings):
c_paths = patch('openlp.plugins.presentations.lib.presentationcontroller.create_paths')
yield c_paths.start()
c_paths.stop()
@pytest.yield_fixture()
def setup(settings):
s_up = patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument._setup')
yield s_up.start()
s_up.stop()
@pytest.fixture()
def presentation(settings, get_thumbnail_folder):
mocked_plugin = MagicMock()
mocked_plugin.settings_section = 'presentations'
return PresentationController(mocked_plugin)
@pytest.fixture()
def document(presentation):
return PresentationDocument(presentation, Path(''))
def test_constructor(presentation):
"""
Test the PresentationController.
Test the Constructor
"""
def setUp(self):
Registry().create()
Registry().register('settings', Settings())
self.get_thumbnail_folder_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder',
return_value=Path())
self.get_thumbnail_folder_patcher.start()
mocked_plugin = MagicMock()
mocked_plugin.settings_section = 'presentations'
self.presentation = PresentationController(mocked_plugin)
self.document = PresentationDocument(self.presentation, '')
# GIVEN: A mocked plugin
def tearDown(self):
self.get_thumbnail_folder_patcher.stop()
# WHEN: The PresentationController is created
def test_constructor(self):
"""
Test the Constructor
"""
# GIVEN: A mocked plugin
# WHEN: The PresentationController is created
# THEN: The name of the presentation controller should be correct
assert 'PresentationController' == self.presentation.name, \
'The name of the presentation controller should be correct'
def test_save_titles_and_notes(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
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.write_text') as mocked_write_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
titles = ['uno', 'dos']
notes = ['one', 'two']
# WHEN: calling save_titles_and_notes
mocked_get_thumbnail_folder.return_value = Path('test')
self.document.save_titles_and_notes(titles, notes)
# THEN: the last call to open should have been for slideNotes2.txt
assert mocked_write_text.call_count == 3, 'There should be exactly three files written'
mocked_write_text.assert_has_calls([call('uno\ndos'), call('one'), call('two')])
def test_save_titles_and_notes_with_None(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(FOLDER_TO_PATCH) 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
assert mocked_open.call_count == 0, 'No file should be created'
def test_get_titles_and_notes(self):
"""
Test PresentationDocument.get_titles_and_notes method
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text',
return_value='uno\ndos\n') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder, \
patch('openlp.plugins.presentations.lib.presentationcontroller.Path.exists') as mocked_exists:
mocked_get_thumbnail_folder.return_value = Path('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
assert type(result_titles) is list, 'result_titles should be of type list'
assert len(result_titles) == 2, 'There should be two items in the titles'
assert type(result_notes) is list, 'result_notes should be of type list'
assert len(result_notes) == 2, 'There should be two items in the notes'
assert mocked_read_text.call_count == 3, 'Three files should be read'
def test_get_titles_and_notes_with_file_not_found(self):
"""
Test PresentationDocument.get_titles_and_notes method with file not found
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
mocked_read_text.side_effect = FileNotFoundError()
mocked_get_thumbnail_folder.return_value = Path('test')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = self.document.get_titles_and_notes()
# THEN: it should return two empty lists
assert isinstance(result_titles, list), 'result_titles should be of type list'
assert len(result_titles) == 0, 'there be no titles'
assert isinstance(result_notes, list), 'result_notes should be a list'
assert len(result_notes) == 0, 'but the list should be empty'
def test_get_titles_and_notes_with_file_error(self):
"""
Test PresentationDocument.get_titles_and_notes method with file errors
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
mocked_read_text.side_effect = OSError()
mocked_get_thumbnail_folder.return_value = Path('test')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = self.document.get_titles_and_notes()
# THEN: it should return two empty lists
assert type(result_titles) is list, 'result_titles should be a list'
# THEN: The name of the presentation controller should be correct
assert 'PresentationController' == presentation.name, \
'The name of the presentation controller should be correct'
class TestPresentationDocument(TestCase):
def test_save_titles_and_notes(document):
"""
Test the PresentationDocument Class
Test PresentationDocument.save_titles_and_notes method with two valid lists
"""
def setUp(self):
"""
Set up the patches and mocks need for all tests.
"""
Registry().create()
self.create_paths_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.create_paths')
self.get_thumbnail_folder_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
self._setup_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument._setup')
# GIVEN: two lists of length==2 and a mocked open and get_thumbnail_folder
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.write_text') as mocked_write_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
titles = ['uno', 'dos']
notes = ['one', 'two']
self.mock_create_paths = self.create_paths_patcher.start()
self.mock_get_thumbnail_folder = self.get_thumbnail_folder_patcher.start()
self.mock_setup = self._setup_patcher.start()
# WHEN: calling save_titles_and_notes
mocked_get_thumbnail_folder.return_value = Path('test')
document.save_titles_and_notes(titles, notes)
self.mock_controller = MagicMock()
# THEN: the last call to open should have been for slideNotes2.txt
assert mocked_write_text.call_count == 3, 'There should be exactly three files written'
mocked_write_text.assert_has_calls([call('uno\ndos'), call('one'), call('two')])
self.mock_get_thumbnail_folder.return_value = Path('returned/path/')
def tearDown(self):
"""
Stop the patches
"""
self.create_paths_patcher.stop()
self.get_thumbnail_folder_patcher.stop()
self._setup_patcher.stop()
def test_save_titles_and_notes_with_none(document):
"""
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(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
titles = None
notes = None
def test_initialise_presentation_document(self):
"""
Test the PresentationDocument __init__ method when initialising the PresentationDocument Class
"""
# GIVEN: A mocked setup method and mocked controller
self.mock_setup.reset()
# WHEN: calling save_titles_and_notes
mocked_get_thumbnail_folder.return_value = 'test'
document.save_titles_and_notes(titles, notes)
# WHEN: Creating an instance of PresentationDocument
PresentationDocument(self.mock_controller, 'Name')
# THEN: No file should have been created
assert mocked_open.call_count == 0, 'No file should be created'
# THEN: PresentationDocument._setup should have been called with the argument 'Name'
self.mock_setup.assert_called_once_with('Name')
def test_presentation_document_setup(self):
"""
Test the PresentationDocument _setup method when initialising the PresentationDocument Class
"""
self._setup_patcher.stop()
def test_get_titles_and_notes(document):
"""
Test PresentationDocument.get_titles_and_notes method
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
# GIVEN: A mocked controller, patched create_paths and get_thumbnail_folder methods
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text',
return_value='uno\ndos\n') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder, \
patch('openlp.plugins.presentations.lib.presentationcontroller.Path.exists') as mocked_exists:
mocked_get_thumbnail_folder.return_value = Path('test')
mocked_exists.return_value = True
# WHEN: Creating an instance of PresentationDocument
PresentationDocument(self.mock_controller, 'Name')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = document.get_titles_and_notes()
# THEN: create_paths should have been called with 'returned/path/'
self.mock_create_paths.assert_called_once_with(Path('returned', 'path/'))
# THEN: it should return two items for the titles and two empty strings for the notes
assert type(result_titles) is list, 'result_titles should be of type list'
assert len(result_titles) == 2, 'There should be two items in the titles'
assert type(result_notes) is list, 'result_notes should be of type list'
assert len(result_notes) == 2, 'There should be two items in the notes'
assert mocked_read_text.call_count == 3, 'Three files should be read'
self._setup_patcher.start()
def test_load_presentation(self):
"""
Test the PresentationDocument.load_presentation method.
"""
def test_get_titles_and_notes_with_file_not_found(document):
"""
Test PresentationDocument.get_titles_and_notes method with file not found
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
mocked_read_text.side_effect = FileNotFoundError()
mocked_get_thumbnail_folder.return_value = Path('test')
# GIVEN: An instance of PresentationDocument
instance = PresentationDocument(self.mock_controller, 'Name')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = document.get_titles_and_notes()
# WHEN: Calling load_presentation()
result = instance.load_presentation()
# THEN: it should return two empty lists
assert isinstance(result_titles, list), 'result_titles should be of type list'
assert len(result_titles) == 0, 'there be no titles'
assert isinstance(result_notes, list), 'result_notes should be a list'
assert len(result_notes) == 0, 'but the list should be empty'
# THEN: load_presentation should return false
assert result is False, "PresentationDocument.load_presentation should return false."
def test_get_titles_and_notes_with_file_error(document):
"""
Test PresentationDocument.get_titles_and_notes method with file errors
"""
# GIVEN: A mocked open, get_thumbnail_folder and exists
with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \
patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
mocked_read_text.side_effect = OSError()
mocked_get_thumbnail_folder.return_value = Path('test')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = document.get_titles_and_notes()
# THEN: it should return two empty lists
assert type(result_titles) is list, 'result_titles should be a list'
def test_initialise_presentation_document(setup):
"""
Test the PresentationDocument __init__ method when initialising the PresentationDocument Class
"""
# GIVEN: A mocked setup method and mocked controller
# WHEN: Creating an instance of PresentationDocument
PresentationDocument(MagicMock(), 'Name')
# THEN: PresentationDocument._setup should have been called with the argument 'Name'
setup.assert_called_once_with('Name')
def test_presentation_document_setup(create_paths, get_thumbnail_folder):
"""
Test the PresentationDocument _setup method when initialising the PresentationDocument Class
"""
# GIVEN: A mocked controller, patched create_paths and get_thumbnail_folder methods
get_thumbnail_folder.return_value = Path('returned/path/')
# WHEN: Creating an instance of PresentationDocument
PresentationDocument(MagicMock(), 'Name')
# THEN: create_paths should have been called with 'returned/path/'
create_paths.assert_called_once_with(Path('returned', 'path/'))
def test_load_presentation(get_thumbnail_folder):
"""
Test the PresentationDocument.load_presentation method.
"""
# GIVEN: An instance of PresentationDocument
instance = PresentationDocument(MagicMock(), 'Name')
# WHEN: Calling load_presentation()
result = instance.load_presentation()
# THEN: load_presentation should return false
assert result is False, "PresentationDocument.load_presentation should return false."