forked from openlp/openlp
Merge branch 'editform-tests' into 'master'
projector.editform refactoring and tests See merge request openlp/openlp!441
This commit is contained in:
commit
b6135737e3
@ -40,6 +40,7 @@ PJLINK_SUFFIX = CR
|
||||
PJLINK_SVER_MAX_LEN = 32
|
||||
PJLINK_TIMEOUT = 30.0
|
||||
PJLINK_TOKEN_SIZE = 8 # PJLINK 1 <token> : where <token> is 8 characters
|
||||
PJLINK_VALID_PORTS = range(1000, 32768)
|
||||
|
||||
# Error and status codes
|
||||
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
||||
|
@ -26,9 +26,9 @@ import logging
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from openlp.core.common import verify_ip_address
|
||||
from openlp.core.common import verify_ip_address, Singleton
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.projectors.constants import PJLINK_PORT
|
||||
from openlp.core.projectors.constants import PJLINK_PORT, PJLINK_VALID_PORTS
|
||||
from openlp.core.projectors.db import Projector
|
||||
from openlp.core.ui.icons import UiIcons
|
||||
|
||||
@ -38,6 +38,82 @@ log.debug('editform loaded')
|
||||
|
||||
# TODO: Fix db entries for input source(s)
|
||||
|
||||
_translate_group = 'OpenLP.ProjectorEditForm'
|
||||
|
||||
|
||||
class MessageList(metaclass=Singleton):
|
||||
"""
|
||||
Consolidate the messages here. Simplify calls to QMessageBox.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.AddressDuplicate = {'title': translate(_translate_group, 'Duplicate Address'),
|
||||
'text': translate(_translate_group,
|
||||
'IP:port combination are already in the database <br /><br />'
|
||||
'Please Enter a different IP:port combination.')
|
||||
}
|
||||
self.DatabaseError = {'title': translate(_translate_group, 'Database Error'),
|
||||
'text': translate(_translate_group,
|
||||
'There was an error saving projector information.<br /><br />'
|
||||
'See the log for the error')
|
||||
}
|
||||
self.DatabaseID = {'title': translate(_translate_group, 'Database ID Error'),
|
||||
'text': translate(_translate_group,
|
||||
'Mismatch between this entry and the database.<br /><br />'
|
||||
'See the log for possible issues.')
|
||||
}
|
||||
self.DatabaseMultiple = {'title': translate(_translate_group, 'Multiple Records'),
|
||||
'text': translate(_translate_group,
|
||||
'Multiple entries found in the database<br /><br />'
|
||||
'Ensure Name and/or IP/Port data is unique')
|
||||
}
|
||||
self.IPBlank = {'title': translate(_translate_group, 'IP Address Not Set'),
|
||||
'text': translate(_translate_group,
|
||||
'You must enter an IP address.<br /><br />'
|
||||
'Please enter a valid IP address.')
|
||||
}
|
||||
self.IPInvalid = {'title': translate(_translate_group, 'Invalid IP Address'),
|
||||
'text': translate(_translate_group,
|
||||
'IP address is not valid.<br /><br />'
|
||||
'Please enter a valid IP address.')
|
||||
}
|
||||
self.NameBlank = {'title': translate(_translate_group, 'Name Not Set'),
|
||||
'text': translate(_translate_group,
|
||||
'You must enter a name for this entry.<br /><br />'
|
||||
'Please enter a unique name for this entry.')
|
||||
}
|
||||
self.NameDuplicate = {'title': translate(_translate_group, 'Duplicate Name'),
|
||||
'text': translate(_translate_group,
|
||||
'Entries must have unique names.<br /><br />'
|
||||
'Please enter a different name.')
|
||||
}
|
||||
self.ProjectorInvalid = {'title': translate(_translate_group, 'Invalid Projector'),
|
||||
'text': translate(_translate_group,
|
||||
'Projector instance not a valid PJLink or Projector Instance'
|
||||
'<br /><br />See log for issue')
|
||||
}
|
||||
self.PortBlank = {'title': translate(_translate_group, 'Port Not Set'),
|
||||
'text': translate(_translate_group,
|
||||
'You must enter a port number for this entry.<br /><br />'
|
||||
'Please enter a valid port number.')
|
||||
}
|
||||
self.PortInvalid = {'title': translate(_translate_group, 'Invalid Port Number'),
|
||||
'text': translate(_translate_group,
|
||||
'Port numbers below 1000 are reserved for admin use only.<br />'
|
||||
'Port numbers above 32767 are not currently usable.<br /><br />'
|
||||
'Please enter a valid port number between 1000 and 32767 inclusive.'
|
||||
f'<br /><br />Default PJLink port is {PJLINK_PORT}')
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def show_warning(message, form=None):
|
||||
"""
|
||||
Display QMessageBox.warning()
|
||||
"""
|
||||
return QtWidgets.QMessageBox.warning(form, message['title'], message['text'])
|
||||
|
||||
|
||||
Message = MessageList()
|
||||
|
||||
|
||||
class Ui_ProjectorEditForm(object):
|
||||
"""
|
||||
@ -57,58 +133,61 @@ class Ui_ProjectorEditForm(object):
|
||||
self.dialog_layout.setObjectName('dialog_layout')
|
||||
self.dialog_layout.setSpacing(8)
|
||||
self.dialog_layout.setContentsMargins(8, 8, 8, 8)
|
||||
# IP Address
|
||||
self.ip_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.ip_label.setObjectName('projector_edit_ip_label')
|
||||
self.ip_text_edit = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.ip_text_edit.setObjectName('projector_edit_ip_text')
|
||||
self.ip_text_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.ip_text_label.setObjectName('projector_show_ip_text')
|
||||
self.dialog_layout.addWidget(self.ip_label, 0, 0)
|
||||
# For new projector, use edit widget
|
||||
self.dialog_layout.addWidget(self.ip_text_edit, 0, 1)
|
||||
# For edit projector, use show widget
|
||||
self.dialog_layout.addWidget(self.ip_text_label, 0, 1)
|
||||
# Port number
|
||||
self.port_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.port_label.setObjectName('projector_edit_ip_label')
|
||||
self.port_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.port_text.setObjectName('projector_edit_port_text')
|
||||
self.dialog_layout.addWidget(self.port_label, 1, 0)
|
||||
self.dialog_layout.addWidget(self.port_text, 1, 1)
|
||||
# PIN
|
||||
self.pin_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.pin_label.setObjectName('projector_edit_pin_label')
|
||||
self.pin_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.pin_label.setObjectName('projector_edit_pin_text')
|
||||
self.dialog_layout.addWidget(self.pin_label, 2, 0)
|
||||
self.dialog_layout.addWidget(self.pin_text, 2, 1)
|
||||
# Name
|
||||
_row = 0 # If I decide to rearrange the layout again
|
||||
self.name_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.name_label.setObjectName('projector_edit_name_label')
|
||||
self.name_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.name_text.setObjectName('projector_edit_name_text')
|
||||
self.dialog_layout.addWidget(self.name_label, 3, 0)
|
||||
self.dialog_layout.addWidget(self.name_text, 3, 1)
|
||||
self.dialog_layout.addWidget(self.name_label, _row, 0)
|
||||
self.dialog_layout.addWidget(self.name_text, _row, 1)
|
||||
# IP Address
|
||||
_row += 1
|
||||
self.ip_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.ip_label.setObjectName('projector_edit_ip_label')
|
||||
self.ip_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.ip_text.setObjectName('projector_edit_ip_text')
|
||||
self.dialog_layout.addWidget(self.ip_label, _row, 0)
|
||||
self.dialog_layout.addWidget(self.ip_text, _row, 1)
|
||||
# Port number
|
||||
_row += 1
|
||||
self.port_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.port_label.setObjectName('projector_edit_ip_label')
|
||||
self.port_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.port_text.setObjectName('projector_edit_port_text')
|
||||
self.dialog_layout.addWidget(self.port_label, _row, 0)
|
||||
self.dialog_layout.addWidget(self.port_text, _row, 1)
|
||||
# PIN
|
||||
_row += 1
|
||||
self.pin_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.pin_label.setObjectName('projector_edit_pin_label')
|
||||
self.pin_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.pin_label.setObjectName('projector_edit_pin_text')
|
||||
self.dialog_layout.addWidget(self.pin_label, _row, 0)
|
||||
self.dialog_layout.addWidget(self.pin_text, _row, 1)
|
||||
# Location
|
||||
_row += 1
|
||||
self.location_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.location_label.setObjectName('projector_edit_location_label')
|
||||
self.location_text = QtWidgets.QLineEdit(edit_projector_dialog)
|
||||
self.location_text.setObjectName('projector_edit_location_text')
|
||||
self.dialog_layout.addWidget(self.location_label, 4, 0)
|
||||
self.dialog_layout.addWidget(self.location_text, 4, 1)
|
||||
self.dialog_layout.addWidget(self.location_label, _row, 0)
|
||||
self.dialog_layout.addWidget(self.location_text, _row, 1)
|
||||
# Notes
|
||||
_row += 1
|
||||
self.notes_label = QtWidgets.QLabel(edit_projector_dialog)
|
||||
self.notes_label.setObjectName('projector_edit_notes_label')
|
||||
self.notes_text = QtWidgets.QPlainTextEdit(edit_projector_dialog)
|
||||
self.notes_text.setObjectName('projector_edit_notes_text')
|
||||
self.dialog_layout.addWidget(self.notes_label, 5, 0, alignment=QtCore.Qt.AlignTop)
|
||||
self.dialog_layout.addWidget(self.notes_text, 5, 1)
|
||||
self.dialog_layout.addWidget(self.notes_label, _row, 0, alignment=QtCore.Qt.AlignTop)
|
||||
self.dialog_layout.addWidget(self.notes_text, _row, 1)
|
||||
# Time for the buttons
|
||||
self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Help |
|
||||
self.button_box_edit = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Help |
|
||||
QtWidgets.QDialogButtonBox.Save |
|
||||
QtWidgets.QDialogButtonBox.Cancel)
|
||||
self.dialog_layout.addWidget(self.button_box, 8, 0, 1, 2)
|
||||
self.dialog_layout.addWidget(self.button_box_edit, 8, 0, 1, 2)
|
||||
self.button_box_view = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok)
|
||||
self.dialog_layout.addWidget(self.button_box_view, 8, 0, 1, 2)
|
||||
|
||||
def retranslate_ui(self, edit_projector_dialog):
|
||||
if self.new_projector:
|
||||
@ -118,8 +197,7 @@ class Ui_ProjectorEditForm(object):
|
||||
title = translate('OpenLP.ProjectorEditForm', 'Edit Projector')
|
||||
edit_projector_dialog.setWindowTitle(title)
|
||||
self.ip_label.setText(translate('OpenLP.ProjectorEditForm', 'IP Address'))
|
||||
self.ip_text_edit.setText(self.projector.ip)
|
||||
self.ip_text_label.setText(self.projector.ip)
|
||||
self.ip_text.setText(self.projector.ip)
|
||||
self.port_label.setText(translate('OpenLP.ProjectorEditForm', 'Port Number'))
|
||||
self.port_text.setText(str(self.projector.port))
|
||||
self.pin_label.setText(translate('OpenLP.ProjectorEditForm', 'PIN'))
|
||||
@ -138,39 +216,51 @@ class ProjectorEditForm(QtWidgets.QDialog, Ui_ProjectorEditForm):
|
||||
Class to add or edit a projector entry in the database.
|
||||
|
||||
Fields that are editable:
|
||||
ip = Column(String(100)) (Only edit for new projector)
|
||||
name = Column(String(20))
|
||||
ip = Column(String(100))
|
||||
port = Column(String(8))
|
||||
pin = Column(String(20))
|
||||
name = Column(String(20))
|
||||
location = Column(String(30))
|
||||
notes = Column(String(200))
|
||||
"""
|
||||
newProjector = QtCore.pyqtSignal(str)
|
||||
editProjector = QtCore.pyqtSignal(object)
|
||||
updateProjectors = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None, projectordb=None):
|
||||
super(ProjectorEditForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint |
|
||||
QtCore.Qt.WindowCloseButtonHint)
|
||||
self.parent = parent
|
||||
self.projectordb = projectordb
|
||||
self.new_projector = False
|
||||
super(ProjectorEditForm, self).__init__(parent,
|
||||
QtCore.Qt.WindowSystemMenuHint |
|
||||
QtCore.Qt.WindowTitleHint |
|
||||
QtCore.Qt.WindowCloseButtonHint)
|
||||
self.setup_ui(self)
|
||||
self.button_box.accepted.connect(self.accept_me)
|
||||
self.button_box.helpRequested.connect(self.help_me)
|
||||
self.button_box.rejected.connect(self.cancel_me)
|
||||
self.button_box_edit.accepted.connect(self.accept_me)
|
||||
self.button_box_edit.helpRequested.connect(self.help_me)
|
||||
self.button_box_edit.rejected.connect(self.cancel_me)
|
||||
self.button_box_view.accepted.connect(self.cancel_me)
|
||||
|
||||
def exec(self, projector=None):
|
||||
def exec(self, projector=None, edit=True):
|
||||
if projector is None:
|
||||
self.projector = Projector()
|
||||
self.new_projector = True
|
||||
self.ip_text_edit.setVisible(True)
|
||||
self.ip_text_edit.setFocus()
|
||||
self.ip_text_label.setVisible(False)
|
||||
else:
|
||||
if not isinstance(projector, Projector):
|
||||
log.warning('edit_form() Projector type not valid for this form')
|
||||
log.warning(f'editform() projector type is {type(projector)}')
|
||||
return Message.show_warning(Message.ProjectorInvalid)
|
||||
self.projector = projector
|
||||
self.new_projector = False
|
||||
self.ip_text_edit.setVisible(False)
|
||||
self.ip_text_label.setVisible(True)
|
||||
# Since it's already defined, IP address is unchangeable, so focus on port number
|
||||
self.port_text.setFocus()
|
||||
|
||||
self.button_box_edit.setVisible(edit)
|
||||
self.button_box_view.setVisible(not edit)
|
||||
self.name_text.setReadOnly(not edit)
|
||||
self.ip_text.setReadOnly(not edit)
|
||||
self.port_text.setReadOnly(not edit)
|
||||
self.pin_text.setReadOnly(not edit)
|
||||
self.location_text.setReadOnly(not edit)
|
||||
self.notes_text.setReadOnly(not edit)
|
||||
if edit:
|
||||
self.name_text.setFocus()
|
||||
self.retranslate_ui(self)
|
||||
reply = QtWidgets.QDialog.exec(self)
|
||||
return reply
|
||||
@ -178,90 +268,79 @@ class ProjectorEditForm(QtWidgets.QDialog, Ui_ProjectorEditForm):
|
||||
@QtCore.pyqtSlot()
|
||||
def accept_me(self):
|
||||
"""
|
||||
Validate input before accepting input.
|
||||
Validate inputs before accepting.
|
||||
"""
|
||||
log.debug('accept_me() signal received')
|
||||
valid = True
|
||||
if len(self.name_text.text().strip()) < 1:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorEdit', 'Name Not Set'),
|
||||
translate('OpenLP.ProjectorEdit',
|
||||
'You must enter a name for this entry.<br />'
|
||||
'Please enter a new name for this entry.'))
|
||||
valid = False
|
||||
return
|
||||
name = self.name_text.text().strip()
|
||||
record = self.projectordb.get_projector_by_name(name)
|
||||
if record is not None and record.id != self.projector.id:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorEdit', 'Duplicate Name'),
|
||||
translate('OpenLP.ProjectorEdit',
|
||||
'There is already an entry with name "{name}" in '
|
||||
'the database as ID "{record}". <br />'
|
||||
'Please enter a different name.'.format(name=name,
|
||||
record=record.id)))
|
||||
valid = False
|
||||
return
|
||||
|
||||
# Verify name
|
||||
_name = self.name_text.text().strip()
|
||||
|
||||
if len(_name) < 1:
|
||||
return Message.show_warning(message=Message.NameBlank)
|
||||
_record = self.projectordb.get_projector(name=_name)
|
||||
if len(_record) == 0:
|
||||
if self.new_projector:
|
||||
# Only validate a new entry - otherwise it's been previously verified
|
||||
adx = self.ip_text_edit.text()
|
||||
valid = verify_ip_address(adx)
|
||||
if valid:
|
||||
# With a valid IP - check if it's already in database so we don't duplicate
|
||||
ip = self.projectordb.get_projector_by_ip(adx)
|
||||
if ip is None:
|
||||
valid = True
|
||||
self.new_projector = True
|
||||
elif ip.id != self.projector.id:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorWizard', 'Duplicate IP Address'),
|
||||
translate('OpenLP.ProjectorWizard',
|
||||
'IP address "{ip}"<br />is already in the database '
|
||||
'as ID {data}.<br /><br />Please Enter a different '
|
||||
'IP address.'.format(ip=adx, data=ip.id)))
|
||||
return
|
||||
if self.projector.id is not None:
|
||||
log.warning(f'editform(): No record found but projector had id={self.projector.id}')
|
||||
return Message.show_warning(message=Message.DatabaseError)
|
||||
else:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorWizard', 'Invalid IP Address'),
|
||||
translate('OpenLP.ProjectorWizard',
|
||||
'IP address "{ip}"<br>is not a valid IP address.'
|
||||
'<br /><br />Please enter a valid IP address.'.format(ip=adx)))
|
||||
valid = False
|
||||
return
|
||||
port = int(self.port_text.text())
|
||||
if port < 1000 or port > 32767:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorWizard', 'Invalid Port Number'),
|
||||
translate('OpenLP.ProjectorWizard',
|
||||
'Port numbers below 1000 are reserved for admin use only, '
|
||||
'<br />and port numbers above 32767 are not currently usable.'
|
||||
'<br /><br />Please enter a valid port number between '
|
||||
'1000 and 32767.<br /><br />'
|
||||
'Default PJLink port is {port}'.format(port=PJLINK_PORT)))
|
||||
valid = False
|
||||
if valid:
|
||||
if self.new_projector:
|
||||
self.projector.ip = self.ip_text_edit.text()
|
||||
if self.projector.name.strip() == _name:
|
||||
log.warning(f'editform(): No record found when there should be name="{_name}"')
|
||||
return Message.show_warning(message=Message.DatabaseError)
|
||||
elif len(_record) == 1 and self.new_projector:
|
||||
log.warning(f'editform(): Name "{_name}" already in database')
|
||||
return Message.show_warning(message=Message.NameDuplicate)
|
||||
elif len(_record) > 1:
|
||||
log.warning(f'editform(): Multiple records found for name "{_name}"')
|
||||
for item in _record:
|
||||
log.warning(f'editform() Found record={item.id} name="{item.name}"')
|
||||
return Message.show_warning(message=Message.DatabaseMultiple)
|
||||
|
||||
# Verify IP address
|
||||
_ip = self.ip_text.text().strip()
|
||||
if len(_ip) < 1:
|
||||
return Message.show_warning(message=Message.IPBlank)
|
||||
elif not verify_ip_address(_ip):
|
||||
return Message.show_warning(message=Message.IPInvalid)
|
||||
|
||||
# Verify valid port
|
||||
_port = self.port_text.text().strip()
|
||||
if len(_port) < 1:
|
||||
return Message.show_warning(message=Message.PortBlank)
|
||||
elif not _port.isdecimal():
|
||||
return Message.show_warning(message=Message.PortInvalid)
|
||||
elif int(_port) not in PJLINK_VALID_PORTS:
|
||||
return Message.show_warning(message=Message.PortInvalid)
|
||||
_port = int(_port)
|
||||
|
||||
# Verify valid ip:port address
|
||||
check = self.projectordb.get_projector(ip=_ip, port=str(_port))
|
||||
if len(check) == 1:
|
||||
if self.projector.id != check[0].id:
|
||||
log.warning(f'editform(): Address already in database {_ip}:{_port}')
|
||||
return Message.show_warning(message=Message.AddressDuplicate)
|
||||
elif len(check) > 1:
|
||||
log.warning(f'editform(): Multiple records found for {_ip}:{_port}')
|
||||
for chk in check:
|
||||
log.warning(f'editform(): record={chk.id} name="{chk.name}" adx={chk.ip}:{chk.port}')
|
||||
return Message.show_warning(message=Message.DatabaseMultiple)
|
||||
|
||||
self.projector.name = _name
|
||||
self.projector.ip = _ip
|
||||
self.projector.port = _port
|
||||
self.projector.pin = self.pin_text.text()
|
||||
self.projector.port = int(self.port_text.text())
|
||||
self.projector.name = self.name_text.text()
|
||||
self.projector.location = self.location_text.text()
|
||||
self.projector.notes = self.notes_text.toPlainText()
|
||||
# TODO: Update calls when update_projector fixed
|
||||
if self.new_projector:
|
||||
saved = self.projectordb.add_projector(self.projector)
|
||||
_saved = self.projectordb.add_projector(self.projector)
|
||||
else:
|
||||
saved = self.projectordb.update_projector(self.projector)
|
||||
if not saved:
|
||||
QtWidgets.QMessageBox.warning(self,
|
||||
translate('OpenLP.ProjectorEditForm', 'Database Error'),
|
||||
translate('OpenLP.ProjectorEditForm',
|
||||
'There was an error saving projector '
|
||||
'information. See the log for the error'))
|
||||
return saved
|
||||
if self.new_projector:
|
||||
self.newProjector.emit(adx)
|
||||
else:
|
||||
self.editProjector.emit(self.projector)
|
||||
_saved = self.projectordb.update_projector(self.projector)
|
||||
if not _saved:
|
||||
return Message.show_warning(message=Message.DatabaseError)
|
||||
|
||||
self.updateProjectors.emit()
|
||||
self.projector = None
|
||||
self.close()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
|
@ -205,6 +205,11 @@ class UiProjectorManager(object):
|
||||
'&Edit Projector'),
|
||||
icon=UiIcons().edit,
|
||||
triggers=self.on_edit_projector)
|
||||
self.view_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ProjectorManager',
|
||||
'&View Projector'),
|
||||
icon=UiIcons().edit,
|
||||
triggers=self.on_view_projector)
|
||||
self.menu.addSeparator()
|
||||
self.connect_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ProjectorManager',
|
||||
@ -248,6 +253,11 @@ class UiProjectorManager(object):
|
||||
'&Show Projector Screen'),
|
||||
icon=UiIcons().projector,
|
||||
triggers=self.on_show_projector)
|
||||
self.view_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ProjectorManager',
|
||||
'&Show Projector Screen'),
|
||||
icon=UiIcons().projector,
|
||||
triggers=self.on_view_projector)
|
||||
self.menu.addSeparator()
|
||||
self.delete_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ProjectorManager',
|
||||
@ -321,8 +331,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
log.debug('Loading all projectors')
|
||||
self._load_projectors()
|
||||
self.projector_form = ProjectorEditForm(self, projectordb=self.projectordb)
|
||||
self.projector_form.newProjector.connect(self.add_projector_from_wizard)
|
||||
self.projector_form.editProjector.connect(self.edit_projector_from_wizard)
|
||||
self.projector_form.updateProjectors.connect(self._load_projectors)
|
||||
self.projector_list_widget.itemSelectionChanged.connect(self.update_icons)
|
||||
|
||||
def udp_listen_add(self, port=PJLINK_PORT):
|
||||
@ -385,6 +394,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
log.debug(f'({projector_name}) Building menu - visible = {visible}')
|
||||
self.delete_action.setVisible(True)
|
||||
self.edit_action.setVisible(True)
|
||||
self.view_action.setVisible(True)
|
||||
self.connect_action.setVisible(not visible)
|
||||
self.disconnect_action.setVisible(visible)
|
||||
self.status_action.setVisible(visible)
|
||||
@ -687,6 +697,19 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
message += '<b>{key}</b>: {data}<br />'.format(key=key, data=STATUS_MSG[val])
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message)
|
||||
|
||||
def on_view_projector(self, opt=None):
|
||||
"""
|
||||
Calls edit dialog as readonly with selected projector to show information
|
||||
|
||||
:param opt: Needed by PyQt5
|
||||
"""
|
||||
list_item = self.projector_list_widget.item(self.projector_list_widget.currentRow())
|
||||
projector = list_item.data(QtCore.Qt.UserRole)
|
||||
if projector is None:
|
||||
return
|
||||
self.old_projector = projector
|
||||
self.projector_form.exec(projector.db_item, edit=False)
|
||||
|
||||
def _add_projector(self, projector):
|
||||
"""
|
||||
Helper app to build a projector instance
|
||||
@ -771,7 +794,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
|
||||
|
||||
def _load_projectors(self):
|
||||
"""'
|
||||
Load projectors - only call when initializing
|
||||
Load projectors - only call when initializing or after database changes
|
||||
"""
|
||||
log.debug('_load_projectors()')
|
||||
self.projector_list_widget.clear()
|
||||
|
@ -27,8 +27,10 @@ from pathlib import PurePath
|
||||
from unittest.mock import patch
|
||||
|
||||
from openlp.core.projectors.db import Projector, ProjectorDB
|
||||
from openlp.core.projectors.editform import ProjectorEditForm
|
||||
from openlp.core.projectors.manager import ProjectorManager
|
||||
from openlp.core.projectors.pjlink import PJLink
|
||||
|
||||
from tests.helpers.projector import FakePJLink
|
||||
from tests.resources.projector.data import TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
|
||||
|
||||
@ -118,6 +120,28 @@ def projectordb(temp_folder, settings):
|
||||
del proj
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def projector_editform(projectordb):
|
||||
with patch('openlp.core.projectors.editform.QtWidgets.QMessageBox') as mock_msg_box, \
|
||||
patch('openlp.core.projectors.editform.QtWidgets.QDialog') as mock_dialog_box:
|
||||
_form = ProjectorEditForm(projectordb=projectordb)
|
||||
_form.mock_msg_box = mock_msg_box
|
||||
_form.mock_dialog_box = mock_dialog_box
|
||||
yield _form
|
||||
del _form
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def projector_editform_mtdb(projectordb_mtdb):
|
||||
with patch('openlp.core.projectors.editform.QtWidgets.QMessageBox') as mock_msg_box, \
|
||||
patch('openlp.core.projectors.editform.QtWidgets.QDialog') as mock_dialog_box:
|
||||
_form = ProjectorEditForm(projectordb=projectordb_mtdb)
|
||||
_form.mock_msg_box = mock_msg_box
|
||||
_form.mock_dialog_box = mock_dialog_box
|
||||
yield _form
|
||||
del _form
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def pjlink():
|
||||
pj_link = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||
|
535
tests/openlp_core/projectors/editform/test_accept_me.py
Normal file
535
tests/openlp_core/projectors/editform/test_accept_me.py
Normal file
@ -0,0 +1,535 @@
|
||||
# -*- 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/>. #
|
||||
##########################################################################
|
||||
"""
|
||||
Test ProjectorEditForm.accept_me
|
||||
"""
|
||||
import logging
|
||||
|
||||
import openlp.core.projectors.db
|
||||
import openlp.core.projectors.editform
|
||||
|
||||
from unittest.mock import DEFAULT, patch
|
||||
|
||||
from openlp.core.projectors.constants import PJLINK_VALID_PORTS
|
||||
from openlp.core.projectors.db import Projector
|
||||
from tests.resources.projector.data import TEST1_DATA
|
||||
|
||||
_test_module = openlp.core.projectors.editform.__name__
|
||||
_test_module_db = openlp.core.projectors.db.__name__
|
||||
Message = openlp.core.projectors.editform.Message
|
||||
|
||||
|
||||
def test_name_NameBlank(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when name field blank
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received')]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText('')
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.NameBlank['title'],
|
||||
Message.NameBlank['text']
|
||||
)
|
||||
|
||||
|
||||
def test_name_DatabaseError_id(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test with mismatch ID between Projector() and DB
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_id = TEST1_DATA['id']
|
||||
t_name = TEST1_DATA['name']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module, logging.WARNING,
|
||||
f'editform(): No record found but projector had id={t_id}')]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.projector.id = t_id
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseError['title'],
|
||||
Message.DatabaseError['text']
|
||||
)
|
||||
|
||||
|
||||
def test_name_DatabaseError_name(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test with mismatch between name and DB
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module, logging.WARNING,
|
||||
f'editform(): No record found when there should be name="{t_name}"')]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.projector.name = t_name
|
||||
projector_editform_mtdb.new_projector = False
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseError['title'],
|
||||
Message.DatabaseError['text']
|
||||
)
|
||||
|
||||
|
||||
def test_name_NameDuplicate(projector_editform, caplog):
|
||||
"""
|
||||
Test when name duplicate
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
# As long as the new record port number is different, we should be good
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module, logging.WARNING, f'editform(): Name "{t_name}" already in database')
|
||||
]
|
||||
projector_editform.exec()
|
||||
projector_editform.name_text.setText(t_name)
|
||||
projector_editform.projector.name = t_name
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.NameDuplicate['title'],
|
||||
Message.NameDuplicate['text']
|
||||
)
|
||||
|
||||
|
||||
def test_name_DatabaseMultiple(projector_editform, caplog):
|
||||
"""
|
||||
Test when multiple database records have the same name
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
# Save another instance of TEST1_DATA
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
t_proj.id = None
|
||||
projector_editform.projectordb.save_object(t_proj)
|
||||
|
||||
# Test variables
|
||||
t_id1 = TEST1_DATA['id']
|
||||
# There should only be 3 records in the DB, TEST[1,2,3]_DATA
|
||||
# The above save_object() should have created record 4
|
||||
t_id2 = t_proj.id
|
||||
t_name = TEST1_DATA['name']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module, logging.WARNING, f'editform(): Multiple records found for name "{t_name}"'),
|
||||
(_test_module, logging.WARNING, f'editform() Found record={t_id1} name="{t_name}"'),
|
||||
(_test_module, logging.WARNING, f'editform() Found record={t_id2} name="{t_name}"')
|
||||
]
|
||||
projector_editform.exec()
|
||||
projector_editform.name_text.setText(t_name)
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseMultiple['title'],
|
||||
Message.DatabaseMultiple['text']
|
||||
)
|
||||
|
||||
|
||||
def test_ip_IPBlank(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when IP field blank
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name')]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText('')
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.IPBlank['title'],
|
||||
Message.IPBlank['text']
|
||||
)
|
||||
|
||||
|
||||
def test_ip_IPInvalid(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when IP invalid
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = 'a'
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name')]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText(t_ip)
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.IPInvalid['title'],
|
||||
Message.IPInvalid['text']
|
||||
)
|
||||
|
||||
|
||||
def test_port_PortBlank(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when port field blank
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = TEST1_DATA['ip']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText(t_ip)
|
||||
projector_editform_mtdb.port_text.setText('')
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.PortBlank['title'],
|
||||
Message.PortBlank['text']
|
||||
)
|
||||
|
||||
|
||||
def test_port_PortInvalid_not_decimal(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when port not a decimal digit
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = TEST1_DATA['ip']
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText(t_ip)
|
||||
projector_editform_mtdb.port_text.setText('a')
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.PortInvalid['title'],
|
||||
Message.PortInvalid['text']
|
||||
)
|
||||
|
||||
|
||||
def test_port_PortInvalid_low(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when port number less than PJLINK_VALID_PORTS lower value
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = TEST1_DATA['ip']
|
||||
t_port = PJLINK_VALID_PORTS.start - 1
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText(t_ip)
|
||||
projector_editform_mtdb.port_text.setText(str(t_port))
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.PortInvalid['title'],
|
||||
Message.PortInvalid['text']
|
||||
)
|
||||
|
||||
|
||||
def test_port_PortInvalid_high(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test when port number greater than PJLINK_VALID_PORTS higher value
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = TEST1_DATA['ip']
|
||||
t_port = PJLINK_VALID_PORTS.stop + 1
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
]
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_name)
|
||||
projector_editform_mtdb.ip_text.setText(t_ip)
|
||||
projector_editform_mtdb.port_text.setText(str(t_port))
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.PortInvalid['title'],
|
||||
Message.PortInvalid['text']
|
||||
)
|
||||
|
||||
|
||||
def test_adx_AddressDuplicate(projector_editform, caplog):
|
||||
"""
|
||||
Test when IP:Port address duplicate
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_ip = TEST1_DATA['ip']
|
||||
t_port = TEST1_DATA['port']
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by IP Port'),
|
||||
(_test_module, logging.WARNING, f'editform(): Address already in database {t_ip}:{t_port}')
|
||||
]
|
||||
projector_editform.exec()
|
||||
projector_editform.name_text.setText('A Different Name Not In DB')
|
||||
projector_editform.ip_text.setText(t_ip)
|
||||
projector_editform.port_text.setText(str(t_port))
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.AddressDuplicate['title'],
|
||||
Message.AddressDuplicate['text']
|
||||
)
|
||||
|
||||
|
||||
def test_adx_DatabaseMultiple(projector_editform, caplog):
|
||||
"""
|
||||
Test when database has multiple same IP:Port records
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
t_proj.id = None
|
||||
projector_editform.projectordb.save_object(t_proj)
|
||||
t_id1 = TEST1_DATA['id']
|
||||
t_id2 = t_proj.id
|
||||
t_name = TEST1_DATA['name']
|
||||
t_ip = TEST1_DATA['ip']
|
||||
t_port = TEST1_DATA['port']
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'accept_me() signal received'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by Name'),
|
||||
(_test_module_db, logging.DEBUG, 'Filter by IP Port'),
|
||||
(_test_module, logging.WARNING, f'editform(): Multiple records found for {t_ip}:{t_port}'),
|
||||
(_test_module, logging.WARNING, f'editform(): record={t_id1} name="{t_name}" adx={t_ip}:{t_port}'),
|
||||
(_test_module, logging.WARNING, f'editform(): record={t_id2} name="{t_name}" adx={t_ip}:{t_port}')
|
||||
]
|
||||
projector_editform.exec()
|
||||
projector_editform.name_text.setText('A Different Name Not In DB')
|
||||
projector_editform.ip_text.setText(t_ip)
|
||||
projector_editform.port_text.setText(str(t_port))
|
||||
|
||||
# WHEN: Called
|
||||
caplog.clear()
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: Appropriate calls made
|
||||
assert caplog.record_tuples == logs, 'Invalid logs'
|
||||
projector_editform.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseMultiple['title'],
|
||||
Message.DatabaseMultiple['text']
|
||||
)
|
||||
|
||||
|
||||
@patch.multiple(openlp.core.projectors.editform.ProjectorEditForm, updateProjectors=DEFAULT, close=DEFAULT)
|
||||
@patch.object(openlp.core.projectors.db.ProjectorDB, 'add_projector')
|
||||
def test_save_new(mock_add, projector_editform_mtdb, **kwargs):
|
||||
"""
|
||||
Test editform saving new projector instance where db fails to save
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
mock_update = kwargs['updateProjectors']
|
||||
mock_close = kwargs['close']
|
||||
mock_add.return_value = True
|
||||
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
t_proj.id = None
|
||||
projector_editform_mtdb.new_projector = True
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_proj.name)
|
||||
projector_editform_mtdb.ip_text.setText(t_proj.ip)
|
||||
projector_editform_mtdb.port_text.setText(str(t_proj.port))
|
||||
|
||||
# WHEN: Called
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: appropriate message called
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_not_called()
|
||||
mock_update.emit.assert_called_once()
|
||||
mock_close.assert_called_once()
|
||||
|
||||
|
||||
@patch.multiple(openlp.core.projectors.editform.ProjectorEditForm, updateProjectors=DEFAULT, close=DEFAULT)
|
||||
@patch.object(openlp.core.projectors.db.ProjectorDB, 'add_projector')
|
||||
def test_save_new_fail(mock_add, projector_editform_mtdb, caplog, **kwargs):
|
||||
"""
|
||||
Test editform saving new projector instance where db fails to save
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
mock_update = kwargs['updateProjectors']
|
||||
mock_close = kwargs['close']
|
||||
mock_add.return_value = False
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
t_proj.id = None
|
||||
projector_editform_mtdb.new_projector = True
|
||||
projector_editform_mtdb.exec()
|
||||
projector_editform_mtdb.name_text.setText(t_proj.name)
|
||||
projector_editform_mtdb.ip_text.setText(t_proj.ip)
|
||||
projector_editform_mtdb.port_text.setText(str(t_proj.port))
|
||||
|
||||
# WHEN: Called
|
||||
projector_editform_mtdb.accept_me()
|
||||
|
||||
# THEN: appropriate message called
|
||||
mock_add.assert_called_once_with(projector_editform_mtdb.projector)
|
||||
projector_editform_mtdb.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseError['title'],
|
||||
Message.DatabaseError['text']
|
||||
)
|
||||
mock_update.assert_not_called()
|
||||
mock_close.assert_not_called()
|
||||
|
||||
|
||||
@patch.multiple(openlp.core.projectors.editform.ProjectorEditForm, updateProjectors=DEFAULT, close=DEFAULT)
|
||||
@patch.object(openlp.core.projectors.db.ProjectorDB, 'update_projector')
|
||||
def test_save_update(mock_add, projector_editform, **kwargs):
|
||||
"""
|
||||
Test editform update projector instance in database
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
mock_update = kwargs['updateProjectors']
|
||||
mock_close = kwargs['close']
|
||||
mock_add.return_value = True
|
||||
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
projector_editform.new_projector = True
|
||||
projector_editform.exec(projector=t_proj)
|
||||
projector_editform.name_text.setText(t_proj.name)
|
||||
projector_editform.ip_text.setText(t_proj.ip)
|
||||
projector_editform.port_text.setText(str(t_proj.port))
|
||||
|
||||
# WHEN: Called
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: appropriate message called
|
||||
projector_editform.mock_msg_box.warning.assert_not_called()
|
||||
mock_update.emit.assert_called_once()
|
||||
mock_close.assert_called_once()
|
||||
|
||||
|
||||
@patch.multiple(openlp.core.projectors.editform.ProjectorEditForm, updateProjectors=DEFAULT, close=DEFAULT)
|
||||
@patch.object(openlp.core.projectors.db.ProjectorDB, 'update_projector')
|
||||
def test_save_update_fail(mock_add, projector_editform, caplog, **kwargs):
|
||||
"""
|
||||
Test editform updating projector instance where db fails to save
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
mock_update = kwargs['updateProjectors']
|
||||
mock_close = kwargs['close']
|
||||
mock_add.return_value = False
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
t_proj = Projector(**TEST1_DATA)
|
||||
projector_editform.exec(projector=t_proj)
|
||||
projector_editform.name_text.setText(t_proj.name)
|
||||
projector_editform.ip_text.setText(t_proj.ip)
|
||||
projector_editform.port_text.setText(str(t_proj.port))
|
||||
|
||||
# WHEN: Called
|
||||
projector_editform.accept_me()
|
||||
|
||||
# THEN: appropriate message called
|
||||
mock_add.assert_called_once_with(projector_editform.projector)
|
||||
projector_editform.mock_msg_box.warning.assert_called_once_with(None,
|
||||
Message.DatabaseError['title'],
|
||||
Message.DatabaseError['text']
|
||||
)
|
||||
mock_update.assert_not_called()
|
||||
mock_close.assert_not_called()
|
146
tests/openlp_core/projectors/editform/test_misc_editform.py
Normal file
146
tests/openlp_core/projectors/editform/test_misc_editform.py
Normal file
@ -0,0 +1,146 @@
|
||||
# -*- 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/>. #
|
||||
##########################################################################
|
||||
"""
|
||||
Test ProjectorEditForm methods that don't have many paths/options
|
||||
"""
|
||||
|
||||
import logging
|
||||
import openlp.core.projectors.editform
|
||||
import openlp.core.projectors.db
|
||||
|
||||
from unittest.mock import patch
|
||||
from tests.resources.projector.data import TEST1_DATA, TEST2_DATA
|
||||
|
||||
_test_module = openlp.core.projectors.editform.__name__
|
||||
_test_module_db = openlp.core.projectors.db.__name__
|
||||
|
||||
Message = openlp.core.projectors.editform.Message
|
||||
Projector = openlp.core.projectors.db.Projector
|
||||
ProjectorEditForm = openlp.core.projectors.editform.ProjectorEditForm
|
||||
|
||||
|
||||
def test_exec_projector_bad(projector_editform, caplog):
|
||||
"""
|
||||
Test projector edit form with bad projector
|
||||
"""
|
||||
# GIVEN: Mocked setup
|
||||
t_chk_item = str()
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.WARNING, 'edit_form() Projector type not valid for this form'),
|
||||
(_test_module, logging.WARNING, f'editform() projector type is {type(t_chk_item)}')
|
||||
]
|
||||
|
||||
# WHEN: Calling edit form with existing projector instance
|
||||
projector_editform.exec(projector=t_chk_item)
|
||||
|
||||
# THEN: Appropriate calls and log entries
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
assert projector_editform.new_projector is False, 'new_projector should not have changed'
|
||||
projector_editform.mock_dialog_box.exec.assert_not_called()
|
||||
projector_editform.mock_msg_box.warning.assert_called_with(None,
|
||||
Message.ProjectorInvalid['title'],
|
||||
Message.ProjectorInvalid['text']
|
||||
)
|
||||
|
||||
# TODO: Check signals for QDialogButtonBox (projector_editform.button_box_edit/button_box_view)
|
||||
|
||||
|
||||
def test_exec_projector_edit(projector_editform, caplog):
|
||||
"""
|
||||
Test projector edit form with existing projector entry
|
||||
|
||||
:return:
|
||||
"""
|
||||
# GIVEN: Mocked setup
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module_db, logging.DEBUG, 'Filter by ID')]
|
||||
|
||||
t_chk_db = projector_editform.projectordb.get_projector(id=TEST2_DATA['id'])[0]
|
||||
projector_editform.new_projector = False
|
||||
projector_editform.projector = None
|
||||
|
||||
# WHEN: Calling edit form with existing projector instance
|
||||
projector_editform.exec(projector=Projector(**TEST2_DATA))
|
||||
|
||||
# THEN: Should be editing an existing entry
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
assert projector_editform.new_projector is False, 'Projector edit form should be marked as existing entry'
|
||||
assert projector_editform.projector == t_chk_db, 'Entries should match'
|
||||
projector_editform.mock_msg_box.assert_not_called()
|
||||
# TODO: Check signals for QDialogButtonBox (projector_editform.button_box_edit/button_box_view)
|
||||
|
||||
|
||||
def test_exec_projector_new(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test projector edit form with existing projector entry
|
||||
|
||||
:return:
|
||||
"""
|
||||
# GIVEN: Mocked setup
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = []
|
||||
projector_editform_mtdb.new_projector = False
|
||||
projector_editform_mtdb.projector = Projector(**TEST1_DATA)
|
||||
|
||||
# WHEN: Calling edit form with existing projector instance
|
||||
projector_editform_mtdb.exec()
|
||||
t_chk_item = projector_editform_mtdb.projector
|
||||
|
||||
# THEN: Should be editing an existing entry
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
assert projector_editform_mtdb.new_projector is True, 'Projector edit form should be marked as a new entry'
|
||||
assert isinstance(t_chk_item, Projector)
|
||||
assert t_chk_item.id is None, 'ID should have indicated new entry'
|
||||
assert t_chk_item.name is None, 'Name should have indicated new entry'
|
||||
assert t_chk_item.ip is None, 'IP should have indicated new entry'
|
||||
# TODO: Check signals for QDialogButtonBox (projector_editform.button_box_edit/button_box_view)
|
||||
|
||||
|
||||
def test_cancel_me(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
Test cancel_me logs and calls close
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'cancel_me() signal received')]
|
||||
|
||||
with patch.object(projector_editform_mtdb, 'close') as mock_close:
|
||||
# WHEN: Called
|
||||
projector_editform_mtdb.cancel_me()
|
||||
|
||||
# THEN: Appropriate log entries made
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
mock_close.assert_called_once()
|
||||
|
||||
|
||||
def test_help_me(projector_editform_mtdb, caplog):
|
||||
"""
|
||||
TODO: Expand method, then expand test
|
||||
"""
|
||||
# GIVEN: Test setup
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(_test_module, logging.DEBUG, 'help_me() signal received')]
|
||||
|
||||
# WHEN: Called
|
||||
projector_editform_mtdb.help_me()
|
||||
|
||||
# THEN: Appropriate log entries made
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
@ -87,11 +87,9 @@ def test_bootstrap_post_set_up_autostart_false(mock_timer, mocked_edit, projecto
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(test_module, logging.DEBUG, 'Loading all projectors')]
|
||||
|
||||
mock_newProjector = MagicMock()
|
||||
mock_editProjector = MagicMock()
|
||||
mock_updateProjectors = MagicMock()
|
||||
mock_edit = MagicMock()
|
||||
mock_edit.newProjector = mock_newProjector
|
||||
mock_edit.editProjector = mock_editProjector
|
||||
mock_edit.updateProjectors = mock_updateProjectors
|
||||
mocked_edit.return_value = mock_edit
|
||||
|
||||
settings.setValue('projector/connect on start', False)
|
||||
@ -107,8 +105,7 @@ def test_bootstrap_post_set_up_autostart_false(mock_timer, mocked_edit, projecto
|
||||
|
||||
# THEN: verify calls and logs
|
||||
mock_timer.assert_not_called()
|
||||
mock_newProjector.connect.assert_called_once()
|
||||
mock_editProjector.connect.assert_called_once()
|
||||
mock_updateProjectors.connect.assert_called_once()
|
||||
mock_manager['_load_projectors'].assert_called_once(),
|
||||
mock_manager['projector_list_widget'].itemSelectionChanged.connect.assert_called_once()
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
@ -124,11 +121,9 @@ def test_bootstrap_post_set_up_autostart_true(mock_timer, mocked_edit, projector
|
||||
caplog.set_level(logging.DEBUG)
|
||||
logs = [(test_module, logging.DEBUG, 'Delaying 1.5 seconds before loading all projectors')]
|
||||
|
||||
mock_newProjector = MagicMock()
|
||||
mock_editProjector = MagicMock()
|
||||
mock_updateProjectors = MagicMock()
|
||||
mock_edit = MagicMock()
|
||||
mock_edit.newProjector = mock_newProjector
|
||||
mock_edit.editProjector = mock_editProjector
|
||||
mock_edit.updateProjectors = mock_updateProjectors
|
||||
|
||||
settings.setValue('projector/connect on start', True)
|
||||
projector_manager.bootstrap_initialise()
|
||||
@ -146,8 +141,7 @@ def test_bootstrap_post_set_up_autostart_true(mock_timer, mocked_edit, projector
|
||||
mock_timer.assert_called_once()
|
||||
mock_timer.return_value.singleShot.assert_called_once_with(1500, projector_manager._load_projectors)
|
||||
|
||||
mock_newProjector.connect.assert_called_once()
|
||||
mock_editProjector.connect.assert_called_once()
|
||||
mock_updateProjectors.connect.assert_called_once()
|
||||
mock_manager['_load_projectors'].assert_not_called(),
|
||||
mock_manager['projector_list_widget'].itemSelectionChanged.connect.assert_called_once()
|
||||
assert caplog.record_tuples == logs, 'Invalid log entries'
|
||||
|
@ -1,76 +0,0 @@
|
||||
# -*- 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/>. #
|
||||
##########################################################################
|
||||
"""
|
||||
Interface tests to test the openlp.core.projectors.editform.ProjectorEditForm()
|
||||
class and methods.
|
||||
"""
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
|
||||
from openlp.core.projectors.db import Projector, ProjectorDB
|
||||
from openlp.core.projectors.editform import ProjectorEditForm
|
||||
from tests.resources.projector.data import TEST1_DATA, TEST_DB
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def projector_form(settings):
|
||||
with patch('openlp.core.projectors.db.init_url') as mocked_init_url:
|
||||
mocked_init_url.return_value = 'sqlite:///' + TEST_DB
|
||||
projectordb = ProjectorDB()
|
||||
projector_frm = ProjectorEditForm(projectordb=projectordb)
|
||||
yield projector_frm
|
||||
projectordb.session.close()
|
||||
del projector_frm
|
||||
|
||||
|
||||
@patch('openlp.core.projectors.editform.QtWidgets.QDialog.exec')
|
||||
def test_edit_form_add_projector(mocked_exec, projector_form):
|
||||
"""
|
||||
Test projector edit form with no parameters creates a new entry.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
# GIVEN: Mocked setup
|
||||
# WHEN: Calling edit form with no parameters
|
||||
projector_form.exec()
|
||||
item = projector_form.projector
|
||||
|
||||
# THEN: Should be creating a new instance
|
||||
assert projector_form.new_projector, 'Projector edit form should be marked as a new entry'
|
||||
assert (item.ip is None and item.name is None), 'Projector edit form should have a new Projector() instance to edit'
|
||||
|
||||
|
||||
@patch('openlp.core.projectors.editform.QtWidgets.QDialog.exec')
|
||||
def test_edit_form_edit_projector(mocked_exec, projector_form):
|
||||
"""
|
||||
Test projector edit form with existing projector entry
|
||||
|
||||
:return:
|
||||
"""
|
||||
# GIVEN: Mocked setup
|
||||
# WHEN: Calling edit form with existing projector instance
|
||||
projector_form.exec(projector=Projector(**TEST1_DATA))
|
||||
item = projector_form.projector
|
||||
|
||||
# THEN: Should be editing an existing entry
|
||||
assert projector_form.new_projector is False, 'Projector edit form should be marked as existing entry'
|
||||
assert item.ip is TEST1_DATA['ip'] and item.name is TEST1_DATA['name'], \
|
||||
'Projector edit form should have TEST1_DATA() instance to edit'
|
Loading…
Reference in New Issue
Block a user