openlp/tests/openlp_core/lib/test_theme.py

369 lines
15 KiB
Python

# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 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/>. #
##########################################################################
"""
Package to test the openlp.core.lib.theme package.
"""
import pytest
from PyQt5 import QtCore
from pathlib import Path
from unittest.mock import MagicMock, patch
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, TransitionType, TransitionSpeed, Theme
@pytest.fixture
def mock_geometry():
mocked_screen = MagicMock()
mocked_screen.display_geometry = QtCore.QRect(10, 20, 400, 600)
mocked_screenlist = MagicMock()
mocked_screenlist.current = mocked_screen
screenlist_patcher = patch('openlp.core.lib.theme.ScreenList', return_value=mocked_screenlist)
screenlist_patcher.start()
yield
screenlist_patcher.stop()
def test_background_type_to_string():
"""
Test the to_string method of :class:`BackgroundType`
"""
# GIVEN: The BackgroundType members
background_type_solid = BackgroundType.Solid
background_type_gradient = BackgroundType.Gradient
background_type_image = BackgroundType.Image
background_type_transparent = BackgroundType.Transparent
background_type_video = BackgroundType.Video
background_type_stream = BackgroundType.Stream
# WHEN: Calling BackgroundType.to_string
# THEN: The string equivalents should be returned
assert BackgroundType.to_string(background_type_solid) == 'solid'
assert BackgroundType.to_string(background_type_gradient) == 'gradient'
assert BackgroundType.to_string(background_type_image) == 'image'
assert BackgroundType.to_string(background_type_transparent) == 'transparent'
assert BackgroundType.to_string(background_type_video) == 'video'
assert BackgroundType.to_string(background_type_stream) == 'stream'
def test_background_type_from_string():
"""
Test the from_string method of :class:`BackgroundType`
"""
# GIVEN: The BackgroundType strings
background_type_solid = 'solid'
background_type_gradient = 'gradient'
background_type_image = 'image'
background_type_transparent = 'transparent'
background_type_video = 'video'
background_type_stream = 'stream'
# WHEN: Calling BackgroundType.from_string
# THEN: The enum equivalents should be returned
assert BackgroundType.from_string(background_type_solid) == BackgroundType.Solid
assert BackgroundType.from_string(background_type_gradient) == BackgroundType.Gradient
assert BackgroundType.from_string(background_type_image) == BackgroundType.Image
assert BackgroundType.from_string(background_type_transparent) == BackgroundType.Transparent
assert BackgroundType.from_string(background_type_video) == BackgroundType.Video
assert BackgroundType.from_string(background_type_stream) == BackgroundType.Stream
def test_background_gradient_type_to_string():
"""
Test the to_string method of :class:`BackgroundGradientType`
"""
# GIVEN: The BackgroundGradientType member
background_gradient_horizontal = BackgroundGradientType.Horizontal
background_gradient_vertical = BackgroundGradientType.Vertical
background_gradient_circular = BackgroundGradientType.Circular
background_gradient_left_top = BackgroundGradientType.LeftTop
background_gradient_left_bottom = BackgroundGradientType.LeftBottom
# WHEN: Calling BackgroundGradientType.to_string
# THEN: The string equivalents should be returned
assert BackgroundGradientType.to_string(background_gradient_horizontal) == 'horizontal'
assert BackgroundGradientType.to_string(background_gradient_vertical) == 'vertical'
assert BackgroundGradientType.to_string(background_gradient_circular) == 'circular'
assert BackgroundGradientType.to_string(background_gradient_left_top) == 'leftTop'
assert BackgroundGradientType.to_string(background_gradient_left_bottom) == 'leftBottom'
def test_background_gradient_type_from_string():
"""
Test the from_string method of :class:`BackgroundGradientType`
"""
# GIVEN: The BackgroundGradientType strings
background_gradient_horizontal = 'horizontal'
background_gradient_vertical = 'vertical'
background_gradient_circular = 'circular'
background_gradient_left_top = 'leftTop'
background_gradient_left_bottom = 'leftBottom'
# WHEN: Calling BackgroundGradientType.from_string
# THEN: The enum equivalents should be returned
assert BackgroundGradientType.from_string(background_gradient_horizontal) == BackgroundGradientType.Horizontal
assert BackgroundGradientType.from_string(background_gradient_vertical) == BackgroundGradientType.Vertical
assert BackgroundGradientType.from_string(background_gradient_circular) == BackgroundGradientType.Circular
assert BackgroundGradientType.from_string(background_gradient_left_top) == BackgroundGradientType.LeftTop
assert BackgroundGradientType.from_string(background_gradient_left_bottom) == BackgroundGradientType.LeftBottom
def test_transition_type_to_string():
"""
Test the to_string method of :class:`TransitionType`
"""
# GIVEN: The TransitionType member
transition_type_fade = TransitionType.Fade
transition_type_slide = TransitionType.Slide
transition_type_convex = TransitionType.Convex
transition_type_concave = TransitionType.Concave
transition_type_zoom = TransitionType.Zoom
# WHEN: Calling TransitionType.to_string
# THEN: The string equivalents should be returned
assert TransitionType.to_string(transition_type_fade) == 'fade'
assert TransitionType.to_string(transition_type_slide) == 'slide'
assert TransitionType.to_string(transition_type_convex) == 'convex'
assert TransitionType.to_string(transition_type_concave) == 'concave'
assert TransitionType.to_string(transition_type_zoom) == 'zoom'
def test_transition_type_from_string():
"""
Test the from_string method of :class:`TransitionType`
"""
# GIVEN: The TransitionType strings
transition_type_fade = 'fade'
transition_type_slide = 'slide'
transition_type_convex = 'convex'
transition_type_concave = 'concave'
transition_type_zoom = 'zoom'
# WHEN: Calling TransitionType.from_string
# THEN: The enum equivalents should be returned
assert TransitionType.from_string(transition_type_fade) == TransitionType.Fade
assert TransitionType.from_string(transition_type_slide) == TransitionType.Slide
assert TransitionType.from_string(transition_type_convex) == TransitionType.Convex
assert TransitionType.from_string(transition_type_concave) == TransitionType.Concave
assert TransitionType.from_string(transition_type_zoom) == TransitionType.Zoom
def test_transition_speed_to_string():
"""
Test the to_string method of :class:`TransitionSpeed`
"""
# GIVEN: The TransitionSpeed member
transition_speed_normal = TransitionSpeed.Normal
transition_speed_fast = TransitionSpeed.Fast
transition_speed_slow = TransitionSpeed.Slow
# WHEN: Calling TransitionSpeed.to_string
# THEN: The string equivalents should be returned
assert TransitionSpeed.to_string(transition_speed_normal) == 'normal'
assert TransitionSpeed.to_string(transition_speed_fast) == 'fast'
assert TransitionSpeed.to_string(transition_speed_slow) == 'slow'
def test_transition_speed_from_string():
"""
Test the from_string method of :class:`TransitionSpeed`
"""
# GIVEN: The TransitionSpeed strings
transition_speed_normal = 'normal'
transition_speed_fast = 'fast'
transition_speed_slow = 'slow'
# WHEN: Calling TransitionSpeed.from_string
# THEN: The enum equivalents should be returned
assert TransitionSpeed.from_string(transition_speed_normal) == TransitionSpeed.Normal
assert TransitionSpeed.from_string(transition_speed_fast) == TransitionSpeed.Fast
assert TransitionSpeed.from_string(transition_speed_slow) == TransitionSpeed.Slow
def test_new_theme(mock_geometry):
"""
Test the Theme constructor
"""
# GIVEN: The Theme class
# WHEN: A theme object is created
default_theme = Theme()
# THEN: The default values should be correct
check_theme(default_theme)
def test_expand_json(mock_geometry):
"""
Test the expand_json method
"""
# GIVEN: A Theme object and some JSON to "expand"
theme = Theme()
theme_json = {
'background': {
'border_color': '#000000',
'type': 'solid'
},
'display': {
'vertical_align': 0
},
'font': {
'footer': {
'bold': False
},
'main': {
'name': 'Arial'
}
}
}
# WHEN: Theme.expand_json() is run
theme.expand_json(theme_json)
# THEN: The attributes should be set on the object
check_theme(theme)
def test_extend_image_filename(mock_geometry):
"""
Test the extend_image_filename method
"""
# GIVEN: A theme object
theme = Theme()
theme.theme_name = 'MyBeautifulTheme'
theme.background_filename = Path('video.mp4')
theme.background_type = 'video'
path = Path.home()
# WHEN: Theme.extend_image_filename is run
theme.extend_image_filename(path)
# THEN: The filename of the background should be correct
expected_filename = path / 'MyBeautifulTheme' / 'video.mp4'
assert expected_filename == theme.background_filename
assert 'MyBeautifulTheme' == theme.theme_name
def test_save_retrieve(mock_geometry):
"""
Load a dummy theme, save it and reload it
"""
# GIVEN: The default Theme class
# WHEN: A theme object is created
default_theme = Theme()
# THEN: The default values should be correct
save_theme_json = default_theme.export_theme()
lt = Theme()
lt.load_theme(save_theme_json)
check_theme(lt)
def test_set_default_header_footer_overridden(mock_geometry):
"""
Check that when the theme header and footer locations are overridden, the defaults are not set
"""
# GIVEN: A theme with the overrides on
theme = Theme()
theme.set_default_header = MagicMock()
theme.set_default_footer = MagicMock()
theme.font_main_override = True
theme.font_footer_override = True
# WHEN: set_default_header_footer is called
theme.set_default_header_footer()
# THEN: Neither header or footer default fns should have been called
assert theme.set_default_header.call_count == 0
assert theme.set_default_footer.call_count == 0
def test_set_default_footer(mock_geometry):
"""
Test the set_default_footer function sets the footer back to default
(reletive to the screen)
"""
# GIVEN: A screen geometry object and a Theme footer with a strange area
theme = Theme()
theme.font_main_x = 20
theme.font_footer_x = 207
theme.font_footer_y = 25
theme.font_footer_width = 4253
theme.font_footer_height = 5423
# WHEN: set_default_footer is called
theme.set_default_footer()
# THEN: footer should be set, header should not have changed
assert theme.font_main_x == 20, 'header should not have been changed'
assert theme.font_footer_x == 10, 'x pos should be reset to default of 10'
assert theme.font_footer_y == 540, 'y pos should be reset to (screen_size_height * 9 / 10)'
assert theme.font_footer_width == 380, 'width should have been reset to (screen_size_width - 20)'
assert theme.font_footer_height == 60, 'height should have been reset to (screen_size_height / 10)'
def test_set_default_header(mock_geometry):
"""
Test the set_default_header function sets the header back to default
(reletive to the screen)
"""
# GIVEN: A screen geometry object and a Theme header with a strange area
theme = Theme()
theme.font_footer_x = 200
theme.font_main_x = 687
theme.font_main_y = 546
theme.font_main_width = 345
theme.font_main_height = 653
# WHEN: set_default_header is called
theme.set_default_header()
# THEN: footer should be set, header should not have changed
assert theme.font_footer_x == 200, 'footer should not have been changed'
assert theme.font_main_x == 10, 'x pos should be reset to default of 10'
assert theme.font_main_y == 0, 'y pos should be reset to 0'
assert theme.font_main_width == 380, 'width should have been reset to (screen_size_width - 20)'
assert theme.font_main_height == 540, 'height should have been reset to (screen_size_height * 9 / 10)'
def test_set_default_header_footer(mock_geometry):
"""
Test the set_default_header_footer function sets the header and footer back to default
(reletive to the screen)
"""
# GIVEN: A screen geometry object and a Theme header with a strange area
theme = Theme()
theme.font_footer_x = 200
theme.font_main_x = 687
# WHEN: set_default_header is called
theme.set_default_header_footer()
# THEN: footer should be set, header should not have changed
assert theme.font_footer_x == 10, 'footer x pos should be reset to default of 10'
assert theme.font_main_x == 10, 'header x pos should be reset to default of 10'
def check_theme(theme):
assert '#000000' == theme.background_border_color, 'background_border_color should be "#000000"'
assert 'solid' == theme.background_type, 'background_type should be "solid"'
assert 0 == theme.display_vertical_align, 'display_vertical_align should be 0'
assert theme.font_footer_bold is False, 'font_footer_bold should be False'
assert 'Arial' == theme.font_main_name, 'font_main_name should be "Arial"'
assert 53 == len(theme.__dict__), 'The theme should have 53 attributes'