beeref/tests/test_items.py
2021-04-01 20:08:19 +02:00

432 lines
17 KiB
Python

from unittest.mock import patch, MagicMock, PropertyMock
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import Qt
from beeref.items import BeePixmapItem
from beeref.scene import BeeGraphicsScene
from .base import BeeTestCase
class BeePixmapItemTestCase(BeeTestCase):
def setUp(self):
self.scene = BeeGraphicsScene(None)
def test_init(self):
item = BeePixmapItem(
QtGui.QImage(self.imgfilename3x3), self.imgfilename3x3)
assert item.save_id is None
assert item.width == 3
assert item.height == 3
assert item.scale() == 1
assert item.flags() == (
QtWidgets.QGraphicsItem.GraphicsItemFlags.ItemIsMovable
| QtWidgets.QGraphicsItem.GraphicsItemFlags.ItemIsSelectable)
assert item.filename == self.imgfilename3x3
def test_set_scale(self):
item = BeePixmapItem(
QtGui.QImage(self.imgfilename3x3), self.imgfilename3x3)
item.prepareGeometryChange = MagicMock()
item.setScale(3)
assert item.scale() == 3
assert item.pos().x() == 0
assert item.pos().y() == 0
item.prepareGeometryChange.assert_called_once()
def test_set_scale_ignores_zero(self):
item = BeePixmapItem(QtGui.QImage())
item.setScale(0)
assert item.scale() == 1
def test_set_scale_ignores_negative(self):
item = BeePixmapItem(QtGui.QImage())
item.setScale(-0.1)
assert item.scale() == 1
def test_set_pos_center(self):
item = BeePixmapItem(QtGui.QImage())
with patch('beeref.items.BeePixmapItem.width',
new_callable=PropertyMock, return_value=200):
with patch('beeref.items.BeePixmapItem.height',
new_callable=PropertyMock, return_value=100):
item.set_pos_center(0, 0)
assert item.pos().x() == -100
assert item.pos().y() == -50
def test_set_zvalue_sets_new_max(self):
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
item.setZValue(1.1)
assert item.zValue() == 1.1
assert self.scene.max_z == 1.1
def test_set_zvalue_keeps_old_max(self):
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
self.scene.max_z = 3.3
item.setZValue(1.1)
assert item.zValue() == 1.1
assert self.scene.max_z == 3.3
def test_bring_to_front(self):
item1 = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item1)
item1.setZValue(3.3)
item2 = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item2)
item2.bring_to_front()
assert item2.zValue() > item1.zValue()
assert item2.zValue() == self.scene.max_z
def test_on_view_scale_change(self):
item = BeePixmapItem(QtGui.QImage())
with patch('beeref.items.BeePixmapItem.prepareGeometryChange') as m:
item.on_view_scale_change()
m.assert_called_once()
class BeePixmapItemWithViewBaseTestCase(BeeTestCase):
def setUp(self):
self.scene = BeeGraphicsScene(None)
self.item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(self.item)
self.view = MagicMock(get_scale=MagicMock(return_value=1))
views_patcher = patch('beeref.scene.BeeGraphicsScene.views',
return_value=[self.view])
views_patcher.start()
self.addCleanup(views_patcher.stop)
width_patcher = patch('beeref.items.BeePixmapItem.width',
new_callable=PropertyMock,
return_value=100)
width_patcher.start()
self.addCleanup(width_patcher.stop)
height_patcher = patch('beeref.items.BeePixmapItem.height',
new_callable=PropertyMock,
return_value=80)
height_patcher.start()
self.addCleanup(height_patcher.stop)
class BeePixmapItemPaintstuffTestCase(BeePixmapItemWithViewBaseTestCase):
def test_fixed_length_for_viewport_when_default_scales(self):
self.view.get_scale = MagicMock(return_value=1)
assert self.item.fixed_length_for_viewport(100) == 100
assert self.item._view_scale == 1
def test_fixed_length_for_viewport_when_viewport_scaled(self):
self.view.get_scale = MagicMock(return_value=2)
assert self.item.fixed_length_for_viewport(100) == 50
assert self.item._view_scale == 2
def test_fixed_length_for_viewport_when_item_scaled(self):
self.view.get_scale = MagicMock(return_value=1)
self.item.setScale(5)
assert self.item.fixed_length_for_viewport(100) == 20
assert self.item._view_scale == 1
def test_fixed_length_for_viewport_when_no_scene(self):
item = BeePixmapItem(QtGui.QImage())
item._view_scale = 0.5
assert item.fixed_length_for_viewport(100) == 200
def test_resize_size_when_scaled(self):
self.view.get_scale = MagicMock(return_value=2)
self.item.setScale(2)
self.item.SELECT_RESIZE_SIZE = 100
assert self.item.select_resize_size == 25
def test_rotate_size_when_scaled(self):
self.view.get_scale = MagicMock(return_value=2)
self.item.setScale(2)
self.item.SELECT_ROTATE_SIZE = 100
assert self.item.select_rotate_size == 25
def test_paint_when_not_selected(self):
painter = MagicMock()
self.item.setSelected(False)
self.item.pixmap = MagicMock(return_value='pixmap')
self.item.paint(painter, None, None)
painter.drawPixmap.assert_called_once_with(0, 0, 'pixmap')
painter.drawRect.assert_not_called()
painter.drawPoint.assert_not_called()
def test_paint_when_selected_single_selection(self):
painter = MagicMock()
self.item.setSelected(True)
self.item.paint(painter, None, None)
painter.drawPixmap.assert_called_once()
painter.drawRect.assert_called_once()
painter.drawPoint.assert_called()
def test_paint_when_selected_multi_selection(self):
item2 = BeePixmapItem(QtGui.QImage())
item2.setSelected(True)
self.scene.addItem(item2)
painter = MagicMock()
self.item.setSelected(True)
self.item.paint(painter, None, None)
painter.drawPixmap.assert_called_once()
painter.drawRect.assert_called_once()
painter.drawPoint.assert_not_called()
def test_corners(self):
assert set(self.item.corners) == set((
(0, 0),
(100, 0),
(0, 80),
(100, 80)))
def test_get_scale_bounds(self):
self.view.get_scale = MagicMock(return_value=1)
self.item.SELECT_RESIZE_SIZE = 10
rect = self.item.get_scale_bounds((100, 100))
assert rect.topLeft().x() == 95
assert rect.topLeft().y() == 95
assert rect.bottomRight().x() == 105
assert rect.bottomRight().y() == 105
def test_bottom_right_rotate_bounds(self):
self.view.get_scale = MagicMock(return_value=1)
self.item.SELECT_RESIZE_SIZE = 10
self.item.SELECT_ROTATE_SIZE = 10
rect = self.item.bottom_right_rotate_bounds
assert rect.topLeft().x() == 105
assert rect.topLeft().y() == 85
assert rect.bottomRight().x() == 115
assert rect.bottomRight().y() == 95
def test_bounding_rect_when_not_selected(self):
self.view.get_scale = MagicMock(return_value=1)
self.item.setSelected(False)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.boundingRect',
return_value=QtCore.QRectF(0, 0, 100, 80)):
rect = self.item.boundingRect()
assert rect.topLeft().x() == 0
assert rect.topLeft().y() == 0
assert rect.bottomRight().x() == 100
assert rect.bottomRight().y() == 80
def test_bounding_rect_when_selected(self):
self.item.SELECT_RESIZE_SIZE = 10
self.item.SELECT_ROTATE_SIZE = 10
self.view.get_scale = MagicMock(return_value=1)
self.item.setSelected(True)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.boundingRect',
return_value=QtCore.QRectF(0, 0, 100, 80)):
rect = self.item.boundingRect()
assert rect.topLeft().x() == -15
assert rect.topLeft().y() == -15
assert rect.bottomRight().x() == 115
assert rect.bottomRight().y() == 95
def test_shape_when_not_selected(self):
self.view.get_scale = MagicMock(return_value=1)
self.item.setSelected(False)
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(0, 0, 100, 80))
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.shape',
return_value=path):
shape = self.item.shape().boundingRect()
assert shape.topLeft().x() == 0
assert shape.topLeft().y() == 0
assert shape.bottomRight().x() == 100
assert shape.bottomRight().y() == 80
def test_shape_when_selected(self):
self.item.SELECT_RESIZE_SIZE = 10
self.item.SELECT_ROTATE_SIZE = 10
self.view.get_scale = MagicMock(return_value=1)
self.item.setSelected(True)
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(0, 0, 100, 80))
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.shape',
return_value=path):
shape = self.item.shape().boundingRect()
assert shape.topLeft().x() == -5
assert shape.topLeft().y() == -5
assert shape.bottomRight().x() == 115
assert shape.bottomRight().y() == 95
class BeePixmapItemScalingTestCase(BeePixmapItemWithViewBaseTestCase):
def test_get_scale_delta_bottomright(self):
self.item.scale_start = QtCore.QPoint(10, 10)
event = MagicMock()
event.scenePos = MagicMock(return_value=QtCore.QPoint(20, 90))
assert self.item.get_scale_delta(event, (100, 80)) == 0.5
def test_get_scale_delta_topleft(self):
self.item.scale_start = QtCore.QPoint(10, 10)
event = MagicMock()
event.scenePos = MagicMock(return_value=QtCore.QPoint(-10, -60))
assert self.item.get_scale_delta(event, (0, 0)) == 0.5
def test_get_scale_anchor_topleft(self):
assert self.item.get_scale_anchor((0, 0)) == (100, 80)
def test_get_scale_anchor_bottomright(self):
assert self.item.get_scale_anchor((100, 80)) == (0, 0)
def test_get_scale_anchor_topright(self):
assert self.item.get_scale_anchor((100, 0)) == (0, 80)
def test_get_scale_anchor_bottomleft(self):
assert self.item.get_scale_anchor((0, 80)) == (100, 0)
def test_get_scale_direction_topleft(self):
assert self.item.get_scale_direction((0, 0)) == (-1, -1)
def test_get_scale_direction_bottomright(self):
assert self.item.get_scale_direction((100, 80)) == (1, 1)
def test_get_scale_direction_topright(self):
assert self.item.get_scale_direction((100, 0)) == (1, -1)
def test_get_scale_direction_bottomleft(self):
assert self.item.get_scale_direction((0, 80)) == (-1, 1)
def test_translate_for_scale_anchor(self):
pos = QtCore.QPoint(50, 70)
self.item.translate_for_scale_anchor(pos, 2, (100, 80))
assert self.item.pos().x() == -150
assert self.item.pos().y() == -90
class BeePixmapItemEventsstuffTestCase(BeePixmapItemWithViewBaseTestCase):
def setUp(self):
super().setUp()
self.event = MagicMock()
self.item.setCursor = MagicMock()
def test_hover_move_event_no_selection(self):
self.event.pos = MagicMock(return_value=QtCore.QPointF(0, 0))
self.item.hoverMoveEvent(self.event)
self.item.setCursor.assert_not_called()
def test_hover_move_event_topleft_scale(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(0, 0))
self.item.hoverMoveEvent(self.event)
self.item.setCursor.assert_called_once_with(
Qt.CursorShape.SizeFDiagCursor)
def test_hover_move_event_bottomright_scale(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(100, 80))
self.item.hoverMoveEvent(self.event)
self.item.setCursor.assert_called_once_with(
Qt.CursorShape.SizeFDiagCursor)
def test_hover_move_event_topright_scale(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(100, 0))
self.item.hoverMoveEvent(self.event)
self.item.setCursor.assert_called_once_with(
Qt.CursorShape.SizeBDiagCursor)
def test_hover_move_event_not_in_handles(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(50, 50))
self.item.hoverMoveEvent(self.event)
self.item.setCursor.assert_called_once_with(
Qt.CursorShape.ArrowCursor)
def test_hover_enter_event_when_selected(self):
self.item.setSelected(True)
self.item.hoverEnterEvent(self.event)
self.item.setCursor.assert_not_called()
def test_hover_enter_event_when_not_selected(self):
self.item.setSelected(False)
self.item.hoverEnterEvent(self.event)
self.item.setCursor.assert_called_once_with(
Qt.CursorShape.ArrowCursor)
def test_mouse_press_event_topleft_scale(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(2, 2))
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(66, 99))
self.event.button = MagicMock(
return_value=Qt.MouseButtons.LeftButton)
self.item.mousePressEvent(self.event)
assert self.item.scale_active_corner == (0, 0)
assert self.item.scale_start == QtCore.QPointF(66, 99)
assert self.item.scale_orig_factor == 1
assert self.item.scale_orig_pos == QtCore.QPointF(0, 0)
def test_mouse_press_event_bottomright_scale(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(99, 79))
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(66, 99))
self.event.button = MagicMock(
return_value=Qt.MouseButtons.LeftButton)
self.item.mousePressEvent(self.event)
assert self.item.scale_active_corner == (100, 80)
assert self.item.scale_start == QtCore.QPointF(66, 99)
assert self.item.scale_orig_factor == 1
assert self.item.scale_orig_pos == QtCore.QPointF(0, 0)
def test_mouse_press_event_not_selected(self):
self.item.setSelected(False)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
self.item.mousePressEvent(self.event)
m.assert_called_once_with(self.event)
assert self.item.scale_active_corner is None
def test_mouse_press_not_in_handles(self):
self.item.setSelected(True)
self.event.pos = MagicMock(return_value=QtCore.QPointF(50, 40))
self.event.button = MagicMock(
return_value=Qt.MouseButtons.LeftButton)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
self.item.mousePressEvent(self.event)
m.assert_called_once_with(self.event)
assert self.item.scale_active_corner is None
def test_mouse_move_event_when_no_action(self):
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
self.item.mouseMoveEvent(self.event)
m.assert_called_once_with(self.event)
def test_move_event_when_scale_action(self):
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90))
self.item.scale_active_corner = (100, 80)
self.item.scale_start = QtCore.QPointF(10, 10)
self.item.scale_orig_factor = 1
self.item.scale_orig_pos = QtCore.QPointF(0, 0)
self.item.mouseMoveEvent(self.event)
assert self.item.scale() == 1.5
def test_mouse_release_event_when_no_action(self):
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem'
'.mouseReleaseEvent') as m:
self.item.mouseReleaseEvent(self.event)
m.assert_called_once_with(self.event)
def test_mouse_release_event_when_scale_action(self):
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90))
self.item.scale_active_corner = (100, 80)
self.item.scale_start = QtCore.QPointF(10, 10)
self.item.scale_orig_factor = 1
self.item.scale_orig_pos = QtCore.QPointF(0, 0)
self.scene.undo_stack = MagicMock()
self.scene.undo_stack.push = MagicMock()
self.item.mouseReleaseEvent(self.event)
self.scene.undo_stack.push.assert_called_once()
args = self.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
assert cmd.items == [self.item]
assert cmd.delta == 0.5
assert cmd.anchor == (0, 0)
assert cmd.ignore_first_redo is True
assert self.item.scale_active_corner is None