Additional unit tests

This commit is contained in:
Rebecca Breu 2023-12-03 22:47:43 +01:00
parent fa9572df96
commit d3f45f2e38
8 changed files with 247 additions and 161 deletions

View file

@ -46,7 +46,7 @@ class BeeGraphicsView(MainControlsMixin,
self.app = app
self.parent = parent
self.settings = BeeSettings()
self.welcome_overlay = widgets.WelcomeOverlay(self)
self.welcome_overlay = widgets.welcome_overlay.WelcomeOverlay(self)
self.setBackgroundBrush(
QtGui.QBrush(QtGui.QColor(*constants.COLORS['Scene:Canvas'])))

View file

@ -16,148 +16,17 @@
import logging
import os.path
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6 import QtCore, QtWidgets
from PyQt6.QtCore import Qt
from beeref import constants
from beeref.config import logfile_name, BeeSettings
from beeref.main_controls import MainControlsMixin
from beeref.widgets import settings # noqa: F401
from beeref.config import logfile_name
from beeref.widgets import settings, welcome_overlay # noqa: F401
logger = logging.getLogger(__name__)
class RecentFilesModel(QtCore.QAbstractListModel):
"""An entry in the 'Recent Files' list."""
def __init__(self, files):
super().__init__()
self.files = files
def rowCount(self, parent):
return len(self.files)
def data(self, index, role):
if role == QtCore.Qt.ItemDataRole.DisplayRole:
return os.path.basename(self.files[index.row()])
if role == QtCore.Qt.ItemDataRole.FontRole:
font = QtGui.QFont()
font.setUnderline(True)
return font
class RecentFilesView(QtWidgets.QListView):
def __init__(self, parent, files=None):
super().__init__(parent)
self.files = files or []
self.clicked.connect(self.on_clicked)
self.setModel(RecentFilesModel(self.files))
self.setMouseTracking(True)
def on_clicked(self, index):
self.parent().parent().open_from_file(self.files[index.row()])
def update_files(self, files):
self.files = files
self.model().files = files
self.reset()
def sizeHint(self):
size = QtCore.QSize()
height = sum(
(self.sizeHintForRow(i) + 2) for i in range(len(self.files)))
width = max(self.sizeHintForColumn(i) for i in range(len(self.files)))
size.setHeight(height)
size.setWidth(width + 2)
return size
def mouseMoveEvent(self, event):
index = self.indexAt(
QtCore.QPoint(int(event.position().x()),
int(event.position().y())))
if index.isValid():
self.setCursor(Qt.CursorShape.PointingHandCursor)
else:
self.setCursor(Qt.CursorShape.ArrowCursor)
super().mouseMoveEvent(event)
class WelcomeOverlay(MainControlsMixin, QtWidgets.QWidget):
"""Some basic info to be displayed when the scene is empty."""
txt = """<p>Paste or drop images here.</p>
<p>Right-click for more options.</p>"""
def __init__(self, parent):
super().__init__(parent)
self.control_target = parent
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
self.init_main_controls(main_window=parent.parent)
# Recent files
self.files_layout = QtWidgets.QVBoxLayout()
self.files_layout.addStretch(50)
self.files_layout.addWidget(
QtWidgets.QLabel('<h3>Recent Files</h3>', self))
self.files_view = RecentFilesView(self)
self.files_layout.addWidget(self.files_view)
self.files_layout.addStretch(50)
# Help text
self.label = QtWidgets.QLabel(self.txt, self)
self.label.setAlignment(Qt.AlignmentFlag.AlignVCenter
| Qt.AlignmentFlag.AlignCenter)
self.layout = QtWidgets.QHBoxLayout()
self.layout.addStretch(50)
self.layout.addWidget(self.label)
self.layout.addStretch(50)
self.setLayout(self.layout)
def show(self):
files = BeeSettings().get_recent_files(existing_only=True)
self.files_view.update_files(files)
if files and self.layout.indexOf(self.files_layout) < 0:
self.layout.insertLayout(0, self.files_layout)
super().show()
def disable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
def enable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)
def mousePressEvent(self, event):
if self.mousePressEventMainControls(event):
return
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.mouseMoveEventMainControls(event):
return
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if self.mouseReleaseEventMainControls(event):
return
super().mouseReleaseEvent(event)
def keyPressEvent(self, event):
if self.keyPressEventMainControls(event):
return
super().keyPressEvent(event)
class BeeProgressDialog(QtWidgets.QProgressDialog):
def __init__(self, label, worker, maximum=0, parent=None):

View file

@ -0,0 +1,156 @@
# This file is part of BeeRef.
#
# BeeRef 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.
#
# BeeRef 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 BeeRef. If not, see <https://www.gnu.org/licenses/>.
import logging
import os.path
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import Qt
from beeref.config import BeeSettings
from beeref.main_controls import MainControlsMixin
logger = logging.getLogger(__name__)
class RecentFilesModel(QtCore.QAbstractListModel):
"""An entry in the 'Recent Files' list."""
def __init__(self, files):
super().__init__()
self.files = files
def rowCount(self, parent):
return len(self.files)
def data(self, index, role):
if role == QtCore.Qt.ItemDataRole.DisplayRole:
return os.path.basename(self.files[index.row()])
if role == QtCore.Qt.ItemDataRole.FontRole:
font = QtGui.QFont()
font.setUnderline(True)
return font
class RecentFilesView(QtWidgets.QListView):
def __init__(self, parent, files=None):
super().__init__(parent)
self.files = files or []
self.clicked.connect(self.on_clicked)
self.setModel(RecentFilesModel(self.files))
self.setMouseTracking(True)
def on_clicked(self, index):
self.parent().parent().open_from_file(self.files[index.row()])
def update_files(self, files):
self.files = files
self.model().files = files
self.reset()
def sizeHint(self):
size = QtCore.QSize()
height = sum(
(self.sizeHintForRow(i) + 2) for i in range(len(self.files)))
width = max(self.sizeHintForColumn(i) for i in range(len(self.files)))
size.setHeight(height)
size.setWidth(width + 2)
return size
def mouseMoveEvent(self, event):
index = self.indexAt(
QtCore.QPoint(int(event.position().x()),
int(event.position().y())))
if index.isValid():
self.setCursor(Qt.CursorShape.PointingHandCursor)
else:
self.setCursor(Qt.CursorShape.ArrowCursor)
super().mouseMoveEvent(event)
class WelcomeOverlay(MainControlsMixin, QtWidgets.QWidget):
"""Some basic info to be displayed when the scene is empty."""
txt = """<p>Paste or drop images here.</p>
<p>Right-click for more options.</p>"""
def __init__(self, parent):
super().__init__(parent)
self.control_target = parent
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
self.init_main_controls(main_window=parent.parent)
# Recent files
self.files_layout = QtWidgets.QVBoxLayout()
self.files_layout.addStretch(50)
self.files_layout.addWidget(
QtWidgets.QLabel('<h3>Recent Files</h3>', self))
self.files_view = RecentFilesView(self)
self.files_layout.addWidget(self.files_view)
self.files_layout.addStretch(50)
# Help text
self.label = QtWidgets.QLabel(self.txt, self)
self.label.setAlignment(Qt.AlignmentFlag.AlignVCenter
| Qt.AlignmentFlag.AlignCenter)
self.layout = QtWidgets.QHBoxLayout()
self.layout.addStretch(50)
self.layout.addWidget(self.label)
self.layout.addStretch(50)
self.setLayout(self.layout)
def show(self):
files = BeeSettings().get_recent_files(existing_only=True)
self.files_view.update_files(files)
if files and self.layout.indexOf(self.files_layout) < 0:
self.layout.insertLayout(0, self.files_layout)
super().show()
def disable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents)
def enable_mouse_events(self):
self.files_view.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)
self.label.setAttribute(
Qt.WidgetAttribute.WA_TransparentForMouseEvents,
on=False)
def mousePressEvent(self, event):
if self.mousePressEventMainControls(event):
return
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.mouseMoveEventMainControls(event):
return
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if self.mouseReleaseEventMainControls(event):
return
super().mouseReleaseEvent(event)
def keyPressEvent(self, event):
if self.keyPressEventMainControls(event):
return
super().keyPressEvent(event)

View file

@ -336,6 +336,20 @@ def test_key_press_event_enter(exit_mock, key_press_mock, view):
exit_mock.assert_called_once_with()
@patch('PyQt6.QtWidgets.QGraphicsTextItem.keyPressEvent')
@patch('beeref.items.BeeTextItem.exit_edit_mode')
def test_key_press_event_escape(exit_mock, key_press_mock, view):
item = BeeTextItem('foo bar')
view.scene.addItem(item)
view.scene.edit_item = item
event = MagicMock()
event.key.return_value = Qt.Key.Key_Escape
event.modifiers.return_value = Qt.KeyboardModifier.NoModifier
item.keyPressEvent(event)
key_press_mock.assert_not_called()
exit_mock.assert_called_once_with(commit=False)
def test_item_to_clipboard(qapp):
clipboard = QtWidgets.QApplication.clipboard()
item = BeeTextItem('foo bar')

View file

@ -39,7 +39,7 @@ def test_init_with_filename(open_file_mock, view, qapp, commandline_args):
del view
@patch('beeref.widgets.WelcomeOverlay.hide')
@patch('beeref.widgets.welcome_overlay.WelcomeOverlay.hide')
def test_on_scene_changed_when_items(hide_mock, view):
item = BeePixmapItem(QtGui.QImage())
view.scene.addItem(item)
@ -51,7 +51,7 @@ def test_on_scene_changed_when_items(hide_mock, view):
assert view.get_scale() == 2
@patch('beeref.widgets.WelcomeOverlay.show')
@patch('beeref.widgets.welcome_overlay.WelcomeOverlay.show')
def test_on_scene_changed_when_no_items(show_mock, view):
view.scale(2, 2)
with patch('beeref.view.BeeGraphicsView.recalc_scene_rect') as r:
@ -600,7 +600,7 @@ def test_on_action_show_titlebar_unchecked(
create_mock.assert_called_once()
@patch('beeref.widgets.WelcomeOverlay.cursor')
@patch('beeref.widgets.welcome_overlay.WelcomeOverlay.cursor')
def test_on_action_move_window_when_welcome_overlay(cursor_mock, view):
cursor_mock.return_value = MagicMock(
pos=MagicMock(return_value=QtCore.QPointF(10.0, 20.0)))

View file

@ -0,0 +1,45 @@
from unittest.mock import patch
from PyQt6 import QtWidgets
from beeref.widgets.settings import (
ImageStorageFormatWidget,
SettingsDialog,
)
def test_image_storage_format_selects_radiobox(settings, view):
settings.setValue('Items/image_storage_format', 'jpg')
widget = ImageStorageFormatWidget()
assert widget.buttons['best'].isChecked() is False
assert widget.buttons['png'].isChecked() is False
assert widget.buttons['jpg'].isChecked() is True
def test_image_storage_format_saves_change(settings, view):
settings.setValue('Items/image_storage_format', 'best')
widget = ImageStorageFormatWidget()
widget.buttons['jpg'].setChecked(True)
assert widget.buttons['best'].isChecked() is False
assert widget.buttons['png'].isChecked() is False
assert widget.buttons['jpg'].isChecked() is True
assert settings.valueOrDefault('Items/image_storage_format', 'jpg')
def test_image_storage_format_on_restore_defaults(settings, view):
widget = ImageStorageFormatWidget()
widget.buttons['jpg'].setChecked(True)
settings.setValue('Items/image_storage_format', 'best')
widget.on_restore_defaults()
assert widget.buttons['best'].isChecked() is True
assert widget.buttons['png'].isChecked() is False
assert widget.buttons['jpg'].isChecked() is False
@patch('PyQt6.QtWidgets.QMessageBox.question',
return_value=QtWidgets.QMessageBox.StandardButton.Yes)
def test_settings_dialog_on_restore_defaults(msg_mock, settings, view):
dialog = SettingsDialog(view)
settings.setValue('Items/image_storage_format', 'jpg')
dialog.on_restore_defaults()
msg_mock.assert_called_once()
assert settings.valueOrDefault('Items/image_storage_format') == 'best'

View file

@ -0,0 +1,25 @@
from unittest.mock import MagicMock
from PyQt6 import QtCore
from beeref.widgets.welcome_overlay import RecentFilesModel
def test_recent_files_model_rowcount(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
assert model.rowCount(None) == 2
def test_recent_files_model_data_diplayrole(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
index = MagicMock()
index.row.return_value = 1
assert model.data(index, QtCore.Qt.ItemDataRole.DisplayRole) == 'bar.png'
def test_recent_files_model_data_fontrole(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
index = MagicMock()
index.row.return_value = 1
font = model.data(index, QtCore.Qt.ItemDataRole.FontRole)
assert font.underline() is True

View file

@ -1,12 +1,9 @@
from unittest.mock import MagicMock
from PyQt6 import QtCore, QtWidgets
from PyQt6.QtCore import Qt
from beeref.config import logfile_name
from beeref.widgets import (
DebugLogDialog,
RecentFilesModel,
SceneToPixmapExporterDialog)
@ -23,26 +20,6 @@ def test_debug_log_dialog(qtbot, settings, view):
assert clipboard.text() == 'my log output'
def test_recent_files_model_rowcount(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
assert model.rowCount(None) == 2
def test_recent_files_model_data_diplayrole(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
index = MagicMock()
index.row.return_value = 1
assert model.data(index, QtCore.Qt.ItemDataRole.DisplayRole) == 'bar.png'
def test_recent_files_model_data_fontrole(view):
model = RecentFilesModel(['foo.png', 'bar.png'])
index = MagicMock()
index.row.return_value = 1
font = model.data(index, QtCore.Qt.ItemDataRole.FontRole)
assert font.underline() is True
def test_scene_to_pixmap_exporter_dialog_sets_defaults(view):
dlg = SceneToPixmapExporterDialog(view, QtCore.QSize(1200, 1600))
assert dlg.width_input.value() == 1200