# -*- 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 . # ########################################################################## """ Package to test the openlp.core.common.actions package. """ import pytest from unittest.mock import MagicMock from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common.actions import ActionList, CategoryActionList from openlp.core.common.registry import Registry MOCK_ACTION1 = MagicMock(**{'text.return_value': 'first'}) MOCK_ACTION2 = MagicMock(**{'text.return_value': 'second'}) @pytest.fixture def action_list(settings): act_list = ActionList.get_instance() yield act_list def test_action_list_contains(): """ Test the __contains__() method """ # GIVEN: The list and 2 actions category_list = CategoryActionList() # WHEN: Add an action category_list.append(MOCK_ACTION1) # THEN: The actions should (not) be in the list. assert MOCK_ACTION1 in category_list assert MOCK_ACTION2 not in category_list def test_action_list_empty_len(): """ Test the __len__ method when the list is empty """ # GIVEN: The list without any actions category_list = CategoryActionList() # WHEN: Do nothing. list_len = len(category_list) # THEN: Check the length. assert list_len == 0, 'The length should be 0.' def test_action_list_len(): """ Test the __len__ method when the list is not empty """ # GIVEN: The list with 2 items in it category_list = CategoryActionList() category_list.append(MOCK_ACTION1) category_list.append(MOCK_ACTION2) # WHEN: The length of the list is calculated list_len = len(category_list) # THEN: It should have 2 items assert list_len == 2, 'The list should have 2 items in it' def test_action_list_append(): """ Test the append() method """ # GIVEN: The list. category_list = CategoryActionList() # WHEN: Append an action. category_list.append(MOCK_ACTION1) category_list.append(MOCK_ACTION2) # THEN: Check if the actions are in the list and check if they have the correct weights. assert MOCK_ACTION1 in category_list assert MOCK_ACTION2 in category_list assert category_list.actions[0] == (0, MOCK_ACTION1) assert category_list.actions[1] == (1, MOCK_ACTION2) def test_action_list_add(): """ Test the add() method """ # GIVEN: The list and weights. action1_weight = 42 action2_weight = 41 category_list = CategoryActionList() # WHEN: Add actions and their weights. category_list.add(MOCK_ACTION1, action1_weight) category_list.add(MOCK_ACTION2, action2_weight) # THEN: Check if they were added and have the specified weights. assert MOCK_ACTION1 in category_list assert MOCK_ACTION2 in category_list assert category_list.actions[0] == (41, MOCK_ACTION2) assert category_list.actions[1] == (42, MOCK_ACTION1) def test_action_list_iterator(): """ Test the __iter__ and __next__ methods """ # GIVEN: The list including two actions category_list = CategoryActionList() category_list.append(MOCK_ACTION1) category_list.append(MOCK_ACTION2) # WHEN: Iterating over the list local_list = [a for a in category_list] # THEN: Make sure they are returned in correct order assert len(category_list) == 2 assert local_list[0] is MOCK_ACTION1 assert local_list[1] is MOCK_ACTION2 def test_action_list_remove(): """ Test the remove() method """ # GIVEN: The list category_list = CategoryActionList() category_list.append(MOCK_ACTION1) # WHEN: Delete an item from the list. category_list.remove(MOCK_ACTION1) # THEN: Now the element should not be in the list anymore. assert MOCK_ACTION1 not in category_list def test_add_action_same_parent(action_list): """ ActionList test - Tests the add_action method. The actions have the same parent, the same shortcuts and both have the QtCore.Qt.WindowShortcut shortcut context set. """ # GIVEN: Two actions with the same shortcuts. parent = QtCore.QObject() action1 = QtWidgets.QAction(parent) action1.setObjectName('action1') action_with_same_shortcuts1 = QtWidgets.QAction(parent) action_with_same_shortcuts1.setObjectName('action_with_same_shortcuts1') # Add default shortcuts to Settings class. default_shortcuts = { 'shortcuts/action1': [QtGui.QKeySequence(QtCore.Qt.Key_A), QtGui.QKeySequence(QtCore.Qt.Key_B)], 'shortcuts/action_with_same_shortcuts1': [QtGui.QKeySequence(QtCore.Qt.Key_B), QtGui.QKeySequence(QtCore.Qt.Key_A)] } Registry().get('settings').extend_default_settings(default_shortcuts) # WHEN: Add the two actions to the action list. action_list.add_action(action1, 'example_category') action_list.add_action(action_with_same_shortcuts1, 'example_category') # Remove the actions again. action_list.remove_action(action1, 'example_category') action_list.remove_action(action_with_same_shortcuts1, 'example_category') # THEN: As both actions have the same shortcuts, they should be removed from one action. assert len(action1.shortcuts()) == 2, 'The action should have two shortcut assigned.' assert len(action_with_same_shortcuts1.shortcuts()) == 0, 'The action should not have a shortcut assigned.' def test_add_action_different_parent(action_list): """ ActionList test - Tests the add_action method. The actions have the different parent, the same shortcuts and both have the QtCore.Qt.WindowShortcut shortcut context set. """ # GIVEN: Two actions with the same shortcuts. parent = QtCore.QObject() action2 = QtWidgets.QAction(parent) action2.setObjectName('action2') second_parent = QtCore.QObject() action_with_same_shortcuts2 = QtWidgets.QAction(second_parent) action_with_same_shortcuts2.setObjectName('action_with_same_shortcuts2') # Add default shortcuts to Settings class. default_shortcuts = { 'shortcuts/action2': [QtGui.QKeySequence(QtCore.Qt.Key_C), QtGui.QKeySequence(QtCore.Qt.Key_D)], 'shortcuts/action_with_same_shortcuts2': [QtGui.QKeySequence(QtCore.Qt.Key_D), QtGui.QKeySequence(QtCore.Qt.Key_C)] } Registry().get('settings').extend_default_settings(default_shortcuts) # WHEN: Add the two actions to the action list. action_list.add_action(action2, 'example_category') action_list.add_action(action_with_same_shortcuts2, 'example_category') # Remove the actions again. action_list.remove_action(action2, 'example_category') action_list.remove_action(action_with_same_shortcuts2, 'example_category') # THEN: As both actions have the same shortcuts, they should be removed from one action. assert len(action2.shortcuts()) == 2, 'The action should have two shortcut assigned.' assert len(action_with_same_shortcuts2.shortcuts()) == 0, 'The action should not have a shortcut assigned.' def test_add_action_different_context(action_list): """ ActionList test - Tests the add_action method. The actions have the different parent, the same shortcuts and both have the QtCore.Qt.WidgetShortcut shortcut context set. """ # GIVEN: Two actions with the same shortcuts. parent = QtCore.QObject() action3 = QtWidgets.QAction(parent) action3.setObjectName('action3') action3.setShortcutContext(QtCore.Qt.WidgetShortcut) second_parent = QtCore.QObject() action_with_same_shortcuts3 = QtWidgets.QAction(second_parent) action_with_same_shortcuts3.setObjectName('action_with_same_shortcuts3') action_with_same_shortcuts3.setShortcutContext(QtCore.Qt.WidgetShortcut) # Add default shortcuts to Settings class. default_shortcuts = { 'shortcuts/action3': [QtGui.QKeySequence(QtCore.Qt.Key_E), QtGui.QKeySequence(QtCore.Qt.Key_F)], 'shortcuts/action_with_same_shortcuts3': [QtGui.QKeySequence(QtCore.Qt.Key_E), QtGui.QKeySequence(QtCore.Qt.Key_F)] } Registry().get('settings').extend_default_settings(default_shortcuts) # WHEN: Add the two actions to the action list. action_list.add_action(action3, 'example_category2') action_list.add_action(action_with_same_shortcuts3, 'example_category2') # Remove the actions again. action_list.remove_action(action3, 'example_category2') action_list.remove_action(action_with_same_shortcuts3, 'example_category2') # THEN: Both action should keep their shortcuts. assert len(action3.shortcuts()) == 2, 'The action should have two shortcut assigned.' assert len(action_with_same_shortcuts3.shortcuts()) == 2, 'The action should have two shortcuts assigned.'