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,43 +21,23 @@
"""
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):
"""
Test the ImpressController Class
"""
@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 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())
def tearDown(self):
"""
Stop the patches
"""
self.destroy_settings()
shutil.rmtree(self.temp_folder)
def test_constructor(self):
def test_constructor(settings, mock_plugin):
"""
Test the Constructor from the ImpressController
"""
@ -65,18 +45,19 @@ class TestImpressController(TestCase, TestMixin):
controller = None
# WHEN: The presentation controller object is created
controller = ImpressController(plugin=self.mock_plugin)
controller = ImpressController(plugin=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):
def test_check_available(mocked_log, settings, mock_plugin):
"""
Test `ImpressController.check_available` on Windows
"""
# GIVEN: An instance of :class:`ImpressController`
controller = ImpressController(plugin=self.mock_plugin)
controller = ImpressController(plugin=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), \
@ -87,13 +68,14 @@ class TestImpressController(TestCase, TestMixin):
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):
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=self.mock_plugin)
controller = ImpressController(plugin=mock_plugin)
# WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns an object
mocked_com_object = MagicMock()
@ -106,14 +88,15 @@ class TestImpressController(TestCase, TestMixin):
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):
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=self.mock_plugin)
controller = ImpressController(plugin=mock_plugin)
# WHEN: `check_available` is called on Windows and `uno_available` is True
with patch('openlp.plugins.presentations.lib.impresscontroller.uno_available', True), \
@ -124,13 +107,14 @@ class TestImpressController(TestCase, TestMixin):
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):
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=self.mock_plugin)
controller = ImpressController(plugin=mock_plugin)
controller.get_com_servicemanager = MagicMock(return_value=MagicMock())
# WHEN: start_process() is called
@ -141,17 +125,18 @@ class TestImpressController(TestCase, TestMixin):
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):
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=self.mock_plugin)
controller = ImpressController(plugin=mock_plugin)
# WHEN: start_process() is called
controller.start_process()
@ -163,119 +148,109 @@ class TestImpressController(TestCase, TestMixin):
mocked_process.startDetached.assert_called_once_with('libreoffice')
class TestImpressDocument(TestCase):
"""
Test the ImpressDocument Class
"""
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)
def test_create_titles_and_notes(self):
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
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
doc.save_titles_and_notes = MagicMock()
doc.document = MagicMock()
doc.document.getDrawPages.return_value = MagicMock()
doc.document.getDrawPages().getCount.return_value = 0
# WHEN reading the titles and notes
self.doc.create_titles_and_notes()
doc.create_titles_and_notes()
# THEN save_titles_and_notes should have been called with empty arrays
self.doc.save_titles_and_notes.assert_called_once_with([], [])
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
doc.save_titles_and_notes.reset_mock()
doc.document.getDrawPages().getCount.return_value = 2
# WHEN: a new call to create_titles_and_notes
self.doc.create_titles_and_notes()
doc.create_titles_and_notes()
# 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(['', ''], [' ', ' '])
doc.save_titles_and_notes.assert_called_once_with(['', ''], [' ', ' '])
def test_get_text_from_page_out_of_bound(self):
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
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
doc.document = _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)
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 = self.doc._ImpressDocument__get_text_from_page(0, TextType.Title)
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 = self.doc._ImpressDocument__get_text_from_page(2, TextType.SlideText)
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 self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
assert doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
def test_get_text_from_page_wrong_type(self):
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
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
doc.document = _mock_a_LibreOffice_document(1, 2, 3)
# WHEN: called with TextType 3
result = self.doc._ImpressDocument__get_text_from_page(1, 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 self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
assert doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex'
def test_get_text_from_page_valid_params(self):
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
self.doc.document = self._mock_a_LibreOffice_document(1, 2, 3)
doc.document = _mock_a_LibreOffice_document(1, 2, 3)
# WHEN: __get_text_from_page is called to get the Notes
result = self.doc._ImpressDocument__get_text_from_page(1, TextType.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 = self.doc._ImpressDocument__get_text_from_page(1, TextType.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 = self.doc._ImpressDocument__get_text_from_page(1, TextType.SlideText)
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(self, page_count, note_count, text_count):
def _mock_a_LibreOffice_document(page_count, note_count, text_count):
"""
Helper function, creates a mock libreoffice document.
@ -294,20 +269,21 @@ class TestImpressDocument(TestCase):
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
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[1] == 0:
if args[0] == 0:
page_shape.getShapeType.return_value = 'com.sun.star.presentation.TitleTextShape'
page_shape.getString.return_value = 'Title'
else:

View File

@ -22,31 +22,13 @@
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):
"""
Test the mediaitem methods.
"""
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()
def test_build_file_mask_string(self):
def test_build_file_mask_string(media_item):
"""
Test the build_file_mask_string() method
"""
@ -66,7 +48,7 @@ class TestMediaItem(TestCase, TestMixin):
pdf_controller.supports = ['pdf']
pdf_controller.also_supports = ['xps', 'oxps', 'epub', 'cbz', 'fb2']
# Mock the controllers.
self.media_item.controllers = {
media_item.controllers = {
'Impress': impress_controller,
'Powerpoint': presentation_controller,
'Powerpoint Viewer': presentation_viewer_controller,
@ -76,19 +58,20 @@ class TestMediaItem(TestCase, TestMixin):
# 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()
media_item.build_file_mask_string()
# 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'
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'
def test_clean_up_thumbnails(self):
def test_clean_up_thumbnails(media_item):
"""
Test that the clean_up_thumbnails method works as expected when files exists.
"""
@ -102,7 +85,7 @@ class TestMediaItem(TestCase, TestMixin):
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 = {
media_item.controllers = {
'Enabled': mocked_enabled_controller,
'Disabled': mocked_disabled_controller
}
@ -114,14 +97,15 @@ class TestMediaItem(TestCase, TestMixin):
presentation_file = Path('file.tmp')
# WHEN: calling clean_up_thumbnails
self.media_item.clean_up_thumbnails(presentation_file, True)
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):
def test_clean_up_thumbnails_missing_file(media_item):
"""
Test that the clean_up_thumbnails method works as expected when file is missing.
"""
@ -130,21 +114,22 @@ class TestMediaItem(TestCase, TestMixin):
mocked_doc = MagicMock()
mocked_controller.add_document.return_value = mocked_doc
mocked_controller.supports = ['tmp']
self.media_item.controllers = {
media_item.controllers = {
'Mocked': mocked_controller
}
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)
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(self, *unreferenced_mocks):
def test_search(mock_setup, mock_item, registry):
"""
Test that the search method finds the correct results
"""

View File

@ -21,32 +21,14 @@
"""
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):
"""
Test the Presentation Message Listener.
"""
def setUp(self):
"""
Set up the components need for all tests.
"""
Registry.create()
Registry().register('service_manager', MagicMock())
Registry().register('main_window', MagicMock())
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
@patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup')
def test_start_presentation(self, media_mock):
def test_start_presentation(media_mock, media_item):
"""
Find and chose a controller to play a presentations.
"""
@ -54,15 +36,15 @@ class TestMessageListener(TestCase, TestMixin):
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
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 = MessageListener(media_item)
ml.media_item = media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
@ -73,8 +55,9 @@ class TestMessageListener(TestCase, TestMixin):
# 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):
def test_start_presentation_with_no_player(media_mock, media_item):
"""
Find and chose a controller to play a presentations when the player is not available.
"""
@ -82,7 +65,7 @@ class TestMessageListener(TestCase, TestMixin):
mock_item = MagicMock()
mock_item.processor = 'Powerpoint'
mock_item.get_frame_path.return_value = "test.ppt"
self.media_item.automatic = False
media_item.automatic = False
mocked_controller = MagicMock()
mocked_controller.available = True
mocked_controller.supports = ['ppt']
@ -93,8 +76,8 @@ class TestMessageListener(TestCase, TestMixin):
'Impress': mocked_controller,
'Powerpoint': mocked_controller1
}
ml = MessageListener(self.media_item)
ml.media_item = self.media_item
ml = MessageListener(media_item)
ml.media_item = media_item
ml.controllers = controllers
ml.preview_handler = MagicMock()
ml.timer = MagicMock()
@ -105,8 +88,9 @@ class TestMessageListener(TestCase, TestMixin):
# 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):
def test_start_pdf_presentation(media_mock, media_item):
"""
Test the startup of pdf presentation succeed.
"""
@ -114,9 +98,9 @@ class TestMessageListener(TestCase, TestMixin):
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
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
@ -126,12 +110,7 @@ class TestMessageListener(TestCase, TestMixin):
assert ml.handler is None, 'The handler should be None'
class TestController(TestCase, TestMixin):
"""
Test the Presentation Controller.
"""
def test_add_handler_failure(self):
def test_add_handler_failure():
"""
Test that add_handler does set doc.slidenumber to 0 in case filed loading
"""

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,6 +71,9 @@ def get_screen_resolution():
from win32api import GetSystemMetrics
return GetSystemMetrics(0), GetSystemMetrics(1)
elif is_linux():
if IS_CI:
return 1024, 768
else:
from Xlib.display import Display
resolution = Display().screen().root.get_geometry()
return resolution.width, resolution.height
@ -73,41 +81,7 @@ def get_screen_resolution():
return 1024, 768
class TestPdfController(TestCase, TestMixin):
"""
Test 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
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)
def test_constructor(self):
def test_constructor(settings, mock_plugin):
"""
Test the Constructor from the PdfController
"""
@ -115,13 +89,13 @@ class TestPdfController(TestCase, TestMixin):
controller = None
# WHEN: The presentation controller object is created
controller = PdfController(plugin=self.mock_plugin)
controller = PdfController(plugin=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'
@skipIf(IS_CI, "This is failing on CI, skip until we can figure out what the problem is")
def load_pdf(self, exe_path):
def load_pdf(exe_path, pdf_env):
"""
Test loading a Pdf using the PdfController
"""
@ -129,10 +103,14 @@ class TestPdfController(TestCase, TestMixin):
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
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()
@ -140,7 +118,8 @@ class TestPdfController(TestCase, TestMixin):
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):
def load_pdf_pictures(exe_path, pdf_env):
"""
Test loading a Pdf and check the generated pictures' size
"""
@ -148,16 +127,19 @@ class TestPdfController(TestCase, TestMixin):
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
# 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=self.mock_plugin)
controller.temp_folder = self.temp_folder_path
controller.thumbnail_folder = self.thumbnail_folder_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'))
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'
@ -169,27 +151,30 @@ class TestPdfController(TestCase, TestMixin):
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):
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:
self.load_pdf(exe_path)
self.load_pdf_pictures(exe_path)
load_pdf(exe_path, pdf_env)
load_pdf_pictures(exe_path, pdf_env)
def test_loading_pdf_using_pymupdf(self):
def test_loading_pdf_using_pymupdf():
try:
import fitz # noqa: F401
except ImportError:
pytest.skip('PyMuPDF is not installed')
self.load_pdf(None)
self.load_pdf_pictures(None)
load_pdf(None)
load_pdf_pictures(None)
@patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists')
def test_process_check_binary_mudraw(self, mocked_check_binary_exists):
def test_process_check_binary_mudraw(mocked_check_binary_exists):
"""
Test that the correct output from mudraw is detected
"""
@ -206,8 +191,9 @@ class TestPdfController(TestCase, TestMixin):
# 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):
def test_process_check_binary_new_motool(mocked_check_binary_exists):
"""
Test that the correct output from the new mutool is detected
"""
@ -226,8 +212,9 @@ class TestPdfController(TestCase, TestMixin):
# THEN: mutool should be detected
assert 'mutool' == ret, 'mutool 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):
def test_process_check_binary_old_motool(mocked_check_binary_exists):
"""
Test that the output from the old mutool is not accepted
"""
@ -243,8 +230,9 @@ class TestPdfController(TestCase, TestMixin):
# 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(self, mocked_check_binary_exists):
def test_process_check_binary_gs(mocked_check_binary_exists):
"""
Test that the correct output from gs is detected
"""

View File

@ -21,54 +21,27 @@
"""
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):
"""
Test the PowerpointController 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
Registry.create()
Registry().register('settings', Settings())
def tearDown(self):
"""
Stop the patches
"""
self.destroy_settings()
shutil.rmtree(self.temp_folder)
def test_constructor(self):
def test_constructor(settings, mock_plugin):
"""
Test the Constructor from the PowerpointController
"""
@ -76,55 +49,13 @@ class TestPowerpointController(TestCase, TestMixin):
controller = None
# WHEN: The presentation controller object is created
controller = PowerpointController(plugin=self.mock_plugin)
controller = PowerpointController(plugin=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'
class TestPowerpointDocument(TestCase, TestMixin):
"""
Test the PowerpointDocument Class
"""
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__)
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)
def test_show_error_msg(self):
def test_show_error_msg():
"""
Test the PowerpointDocument.show_error_msg() method gets called on com exception
"""
@ -132,7 +63,7 @@ class TestPowerpointDocument(TestCase, TestMixin):
# 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 = PowerpointDocument(MagicMock(), MagicMock())
instance.presentation = MagicMock()
instance.presentation.SlideShowWindow.View.GotoSlide = MagicMock(side_effect=pywintypes.com_error('1'))
instance.index_map[42] = 42
@ -146,53 +77,37 @@ class TestPowerpointDocument(TestCase, TestMixin):
' Restart the presentation if you wish to '
'present it.')
# 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)
# 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(self):
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
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()
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])
self.doc.presentation = pres
doc.presentation = pres
# WHEN reading the titles and notes
self.doc.create_titles_and_notes()
doc.create_titles_and_notes()
# 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'], [' ', ' '])
doc.save_titles_and_notes.assert_called_once_with(['SlideText', 'SlideText'], [' ', ' '])
def test_create_titles_and_notes_with_no_slides(self):
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(self.mock_controller, self.file_name)
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.save_titles_and_notes = MagicMock()
doc._PowerpointDocument__get_text_from_shapes = MagicMock()
pres = MagicMock()
@ -205,7 +120,8 @@ class TestPowerpointDocument(TestCase, TestMixin):
# THEN the save should have been called exactly once with empty titles and notes
doc.save_titles_and_notes.assert_called_once_with([], [])
def test_get_text_from_shapes(self):
def test_get_text_from_shapes():
"""
Test getting text from powerpoint shapes
"""
@ -222,7 +138,8 @@ class TestPowerpointDocument(TestCase, TestMixin):
# THEN: it should return the text
assert result == 'slideText\nslideText\n', 'result should match \'slideText\nslideText\n\''
def test_get_text_from_shapes_with_no_shapes(self):
def test_get_text_from_shapes_with_no_shapes():
"""
Test getting text from powerpoint shapes with no shapes
"""
@ -235,12 +152,14 @@ class TestPowerpointDocument(TestCase, TestMixin):
# THEN: it should not fail but return empty string
assert result == '', 'result should be empty'
def test_goto_slide(self):
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
doc = PowerpointDocument(self.mock_controller, self.mock_presentation)
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
@ -255,12 +174,13 @@ class TestPowerpointDocument(TestCase, TestMixin):
# 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):
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(self.mock_controller, self.mock_presentation)
doc = PowerpointDocument(MagicMock(), MagicMock())
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
doc.presentation.Application.Version = 14.0
@ -275,7 +195,8 @@ class TestPowerpointDocument(TestCase, TestMixin):
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):
def test_unblank_screen(get_thumbnail_folder):
"""
Test that unblank_screen works as expected
"""
@ -284,7 +205,7 @@ class TestPowerpointDocument(TestCase, TestMixin):
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 = PowerpointDocument(MagicMock(), MagicMock())
doc.presentation = MagicMock()
doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3
doc.presentation.Application.Version = 14.0

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,38 +22,51 @@
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):
"""
Test the PresentationController.
"""
def setUp(self):
Registry().create()
Registry().register('settings', Settings())
self.get_thumbnail_folder_patcher = \
patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder',
@pytest.yield_fixture()
def get_thumbnail_folder(settings):
gtf = patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder',
return_value=Path())
self.get_thumbnail_folder_patcher.start()
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'
self.presentation = PresentationController(mocked_plugin)
self.document = PresentationDocument(self.presentation, '')
return PresentationController(mocked_plugin)
def tearDown(self):
self.get_thumbnail_folder_patcher.stop()
def test_constructor(self):
@pytest.fixture()
def document(presentation):
return PresentationDocument(presentation, Path(''))
def test_constructor(presentation):
"""
Test the Constructor
"""
@ -62,10 +75,11 @@ class TestPresentationController(TestCase):
# WHEN: The PresentationController is created
# THEN: The name of the presentation controller should be correct
assert 'PresentationController' == self.presentation.name, \
assert 'PresentationController' == presentation.name, \
'The name of the presentation controller should be correct'
def test_save_titles_and_notes(self):
def test_save_titles_and_notes(document):
"""
Test PresentationDocument.save_titles_and_notes method with two valid lists
"""
@ -77,13 +91,14 @@ class TestPresentationController(TestCase):
# WHEN: calling save_titles_and_notes
mocked_get_thumbnail_folder.return_value = Path('test')
self.document.save_titles_and_notes(titles, notes)
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):
def test_save_titles_and_notes_with_none(document):
"""
Test PresentationDocument.save_titles_and_notes method with no data
"""
@ -94,12 +109,13 @@ class TestPresentationController(TestCase):
# WHEN: calling save_titles_and_notes
mocked_get_thumbnail_folder.return_value = 'test'
self.document.save_titles_and_notes(titles, notes)
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):
def test_get_titles_and_notes(document):
"""
Test PresentationDocument.get_titles_and_notes method
"""
@ -113,7 +129,7 @@ class TestPresentationController(TestCase):
mocked_exists.return_value = True
# WHEN: calling get_titles_and_notes
result_titles, result_notes = self.document.get_titles_and_notes()
result_titles, result_notes = 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'
@ -122,7 +138,8 @@ class TestPresentationController(TestCase):
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):
def test_get_titles_and_notes_with_file_not_found(document):
"""
Test PresentationDocument.get_titles_and_notes method with file not found
"""
@ -133,7 +150,7 @@ class TestPresentationController(TestCase):
mocked_get_thumbnail_folder.return_value = Path('test')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = self.document.get_titles_and_notes()
result_titles, result_notes = document.get_titles_and_notes()
# THEN: it should return two empty lists
assert isinstance(result_titles, list), 'result_titles should be of type list'
@ -141,7 +158,8 @@ class TestPresentationController(TestCase):
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):
def test_get_titles_and_notes_with_file_error(document):
"""
Test PresentationDocument.get_titles_and_notes method with file errors
"""
@ -152,80 +170,45 @@ class TestPresentationController(TestCase):
mocked_get_thumbnail_folder.return_value = Path('test')
# WHEN: calling get_titles_and_notes
result_titles, result_notes = self.document.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'
class TestPresentationDocument(TestCase):
"""
Test the PresentationDocument Class
"""
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')
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()
self.mock_controller = MagicMock()
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_initialise_presentation_document(self):
def test_initialise_presentation_document(setup):
"""
Test the PresentationDocument __init__ method when initialising the PresentationDocument Class
"""
# GIVEN: A mocked setup method and mocked controller
self.mock_setup.reset()
# WHEN: Creating an instance of PresentationDocument
PresentationDocument(self.mock_controller, 'Name')
PresentationDocument(MagicMock(), 'Name')
# THEN: PresentationDocument._setup should have been called with the argument 'Name'
self.mock_setup.assert_called_once_with('Name')
setup.assert_called_once_with('Name')
def test_presentation_document_setup(self):
def test_presentation_document_setup(create_paths, get_thumbnail_folder):
"""
Test the PresentationDocument _setup method when initialising the PresentationDocument Class
"""
self._setup_patcher.stop()
# 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(self.mock_controller, 'Name')
PresentationDocument(MagicMock(), 'Name')
# THEN: create_paths should have been called with 'returned/path/'
self.mock_create_paths.assert_called_once_with(Path('returned', 'path/'))
create_paths.assert_called_once_with(Path('returned', 'path/'))
self._setup_patcher.start()
def test_load_presentation(self):
def test_load_presentation(get_thumbnail_folder):
"""
Test the PresentationDocument.load_presentation method.
"""
# GIVEN: An instance of PresentationDocument
instance = PresentationDocument(self.mock_controller, 'Name')
instance = PresentationDocument(MagicMock(), 'Name')
# WHEN: Calling load_presentation()
result = instance.load_presentation()