Skip to content

Commit

Permalink
Add tests for FileWidget Context Menu (#916)
Browse files Browse the repository at this point in the history
* Add tests for FileWidget Context Menu
* Update asammdf.spec
  • Loading branch information
tov101 authored Oct 9, 2023
1 parent e6b62de commit c14390e
Show file tree
Hide file tree
Showing 9 changed files with 782 additions and 252 deletions.
9 changes: 4 additions & 5 deletions asammdf.spec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# -*- mode: python -*-
import argparse
from pathlib import Path
import site
import os
import sys
from pathlib import Path

asammdf_path = Path.cwd() / "src" / "asammdf" / "gui" / "asammdfgui.py"
sys.setrecursionlimit(sys.getrecursionlimit() * 5)

asammdf_path = Path.cwd() / "src" / "asammdf" / "gui" / "asammdfgui.py"

block_cipher = None
added_files = []
Expand Down Expand Up @@ -55,7 +55,6 @@ a = Analysis(
noarchive=False,
)


pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
Expand Down
2 changes: 1 addition & 1 deletion src/asammdf/gui/widgets/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ def open_menu(self):
menu.addAction(self.tr("Edit group"))
menu.addAction(self.tr("Group properties"))

action = menu.exec_(self.viewport().mapToGlobal(position))
action = menu.exec(self.viewport().mapToGlobal(position))

if action is None:
return
Expand Down
43 changes: 19 additions & 24 deletions test/asammdf/gui/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ def manual_use(widget):
@staticmethod
def processEvents(timeout=0.001):
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.sendPostedEvents()
if timeout:
time.sleep(timeout)
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.sendPostedEvents()

def setUp(self) -> None:
if os.path.exists(self.test_workspace):
Expand Down Expand Up @@ -171,42 +173,35 @@ def run(self):
)
QtTest.QTest.qWait(10)

def __init__(self, source_widget, destination_widget, source_pos, destination_pos):
# Ensure that previous drop was not in the same place because mouse needs to be moved.
if self._previous_position and self._previous_position == destination_pos:
move_thread = DragAndDrop.MoveThread(widget=source_widget, position=QtCore.QPoint(101, 101))
def __init__(self, src_widget, dst_widget, src_pos, dst_pos):
# Ensure that the previous drop was not in the same place because the mouse needs to be moved.
if self._previous_position and self._previous_position == dst_pos:
move_thread = DragAndDrop.MoveThread(widget=src_widget, position=QtCore.QPoint(101, 101))
move_thread.start()
move_thread.wait()
move_thread.quit()
DragAndDrop._previous_position = destination_pos
DragAndDrop._previous_position = dst_pos

QtCore.QCoreApplication.processEvents()
if hasattr(source_widget, "viewport"):
source_viewport = source_widget.viewport()
if hasattr(src_widget, "viewport"):
source_viewport = src_widget.viewport()
else:
source_viewport = source_widget
# Press on Source Widget
QtTest.QTest.mousePress(
source_viewport,
QtCore.Qt.LeftButton,
QtCore.Qt.KeyboardModifiers(),
source_pos,
)
# Drag few pixels in order to detect startDrag event
# drag_thread = DragAndDrop.MoveThread(widget=source_widget, position=source_pos, step=50)
# drag_thread.start()
source_viewport = src_widget
# Move to Destination Widget
if hasattr(destination_widget, "viewport") and sys.platform == "win32":
destination_viewport = destination_widget.viewport()
if hasattr(dst_widget, "viewport"):
destination_viewport = dst_widget.viewport()
else:
destination_viewport = destination_widget
move_thread = DragAndDrop.MoveThread(widget=destination_viewport, position=destination_pos)
destination_viewport = dst_widget

# Press on Source Widget
QtTest.QTest.mousePress(source_viewport, QtCore.Qt.LeftButton, QtCore.Qt.KeyboardModifiers(), src_pos)

move_thread = DragAndDrop.MoveThread(widget=destination_viewport, position=dst_pos)
move_thread.start()

source_widget.startDrag(QtCore.Qt.MoveAction)
src_widget.startDrag(QtCore.Qt.MoveAction)
QtTest.QTest.qWait(50)

# drag_thread.wait()
move_thread.wait()
move_thread.quit()
QtCore.QCoreApplication.processEvents()
Expand Down
49 changes: 49 additions & 0 deletions test/asammdf/gui/widgets/test_BaseFileWidget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from test.asammdf.gui.test_base import TestBase
from unittest import mock

from PySide6 import QtCore, QtTest, QtWidgets

from asammdf.gui.widgets.file import FileWidget


Expand Down Expand Up @@ -45,6 +47,41 @@ def setUpFileWidget(self, *args, measurement_file, default):
self.widget.showNormal()
self.processEvents()

def create_window(self, window_type, channels_names=tuple(), channels_indexes=tuple()):
channel_tree = self.widget.channels_tree
channel_tree.clearSelection()
for channel in channels_names:
channel = self.find_channel(channel_tree, channel_name=channel)
channel.setCheckState(0, QtCore.Qt.CheckState.Checked)
for channel in channels_indexes:
channel = self.find_channel(channel_tree, channel_index=channel)
channel.setCheckState(0, QtCore.Qt.CheckState.Checked)

with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog:
mc_WindowSelectionDialog.return_value.result.return_value = True
mc_WindowSelectionDialog.return_value.selected_type.return_value = window_type
# - Press PushButton "Create Window"
QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.LeftButton)
widget_types = self.get_subwindows()
self.assertIn(window_type, widget_types)

@staticmethod
def find_channel(channel_tree, channel_name=None, channel_index=None):
selected_channel = None
if not channel_name and not channel_index:
selected_channel = channel_tree.topLevelItem(0)
elif channel_index:
selected_channel = channel_tree.topLevelItem(channel_index)
elif channel_name:
iterator = QtWidgets.QTreeWidgetItemIterator(channel_tree)
while iterator.value():
item = iterator.value()
if item and item.text(0) == channel_name:
selected_channel = item
break
iterator += 1
return selected_channel

def get_subwindows(self):
widget_types = sorted(
map(
Expand All @@ -53,3 +90,15 @@ def get_subwindows(self):
)
)
return widget_types

def load_display_file(self, display_file):
with mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch(
"asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName"
) as mo_getOpenFileName:
mo_getOpenFileName.return_value = display_file, None
QtTest.QTest.mouseClick(
self.widget.load_channel_list_btn,
QtCore.Qt.MouseButton.LeftButton,
)
# Pre-Evaluate
mo_load_window.assert_called()
81 changes: 54 additions & 27 deletions test/asammdf/gui/widgets/test_BasePlotWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
from PySide6 import QtCore, QtTest, QtWidgets


class QMenuWrap(QtWidgets.QMenu):
return_action = None

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def exec(self, *args, **kwargs):
if not self.return_action:
return super().exec_(*args, **kwargs)
return self.return_action


class TestPlotWidget(TestFileWidget):
class Column:
NAME = 0
Expand All @@ -21,34 +33,23 @@ def add_channel_to_plot(self, plot=None, channel_name=None, channel_index=None):
plot = self.plot

# Select channel
selected_channel = None
channel_tree = self.widget.channels_tree
channel_tree.clearSelection()

if not channel_name and not channel_index:
selected_channel = channel_tree.topLevelItem(0)
channel_name = selected_channel.text(0)
elif channel_index:
selected_channel = channel_tree.topLevelItem(channel_index)
channel_name = selected_channel.text(0)
elif channel_name:
iterator = QtWidgets.QTreeWidgetItemIterator(channel_tree)
while iterator.value():
item = iterator.value()
if item and item.text(0) == channel_name:
item.setSelected(True)
selected_channel = item
iterator += 1
selected_channel = self.find_channel(channel_tree, channel_name, channel_index)
selected_channel.setSelected(True)
if not channel_name:
channel_name = selected_channel.text(self.Column.NAME)

drag_position = channel_tree.visualItemRect(selected_channel).center()
drop_position = plot.channel_selection.viewport().rect().center()

# PreEvaluation
DragAndDrop(
source_widget=channel_tree,
destination_widget=plot.channel_selection,
source_pos=drag_position,
destination_pos=drop_position,
src_widget=channel_tree,
dst_widget=plot.channel_selection,
src_pos=drag_position,
dst_pos=drop_position,
)
self.processEvents(0.05)
plot_channel = None
Expand All @@ -61,11 +62,37 @@ def add_channel_to_plot(self, plot=None, channel_name=None, channel_index=None):

return plot_channel

def create_window(self, window_type):
with mock.patch("asammdf.gui.widgets.file.WindowSelectionDialog") as mc_WindowSelectionDialog:
mc_WindowSelectionDialog.return_value.result.return_value = True
mc_WindowSelectionDialog.return_value.selected_type.return_value = window_type
# - Press PushButton "Create Window"
QtTest.QTest.mouseClick(self.widget.create_window_btn, QtCore.Qt.LeftButton)
widget_types = self.get_subwindows()
self.assertIn(window_type, widget_types)
def context_menu(self, action_text, position=None):
with mock.patch("asammdf.gui.widgets.tree.QtWidgets.QMenu", wraps=QMenuWrap):
mo_action = mock.MagicMock()
mo_action.text.return_value = action_text
QMenuWrap.return_action = mo_action

if not position:
QtTest.QTest.mouseClick(self.plot.channel_selection.viewport(), QtCore.Qt.MouseButton.RightButton)
else:
QtTest.QTest.mouseClick(
self.plot.channel_selection.viewport(),
QtCore.Qt.MouseButton.RightButton,
QtCore.Qt.KeyboardModifiers(),
position,
)
self.processEvents(0.01)

while not mo_action.text.called:
self.processEvents(0.02)

def move_channel_to_group(self, plot=None, src=None, dst=None):
if not plot and self.plot:
plot = self.plot

drag_position = plot.channel_selection.visualItemRect(src).center()
drop_position = plot.channel_selection.visualItemRect(dst).center()

DragAndDrop(
src_widget=plot.channel_selection,
dst_widget=plot.channel_selection,
src_pos=drag_position,
dst_pos=drop_position,
)
self.processEvents(0.05)
85 changes: 19 additions & 66 deletions test/asammdf/gui/widgets/test_FileWidget_TabChannels.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env python
import pathlib
from test.asammdf.gui.test_base import DragAndDrop
from test.asammdf.gui.widgets.test_BaseFileWidget import TestFileWidget
from unittest import mock

Expand Down Expand Up @@ -374,8 +373,7 @@ def test_PushButton_SaveOfflineWindows(self):
- Press PushButton: "Load offline windows"
- Simulate that valid "dspf" file was selected
- Close all Numeric and Tabular windows
- Add new Plot window
- Drag and drop signal from channels tree to Plot
- Add new Plot window with few channels
- Press PushButton: "Save offline windows"
- Close all windows.
- Press PushButton: "Load offline windows"
Expand All @@ -393,55 +391,19 @@ def test_PushButton_SaveOfflineWindows(self):
# Switch ComboBox to "Internal file structure"
self.widget.channel_view.setCurrentText("Internal file structure")

with mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch(
"asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName"
) as mo_getOpenFileName:
mo_getOpenFileName.return_value = valid_dspf, None
QtTest.QTest.mouseClick(
self.widget.load_channel_list_btn,
QtCore.Qt.MouseButton.LeftButton,
)
# Pre-Evaluate
mo_load_window.assert_called()
self.assertEqual(len(self.widget.mdi_area.subWindowList()), 3)
for window in self.widget.mdi_area.subWindowList():
if window.widget().__class__.__name__ in ("Numeric", "Tabular"):
window.close()
# Load Display File
self.load_display_file(display_file=valid_dspf)
self.assertEqual(len(self.widget.mdi_area.subWindowList()), 3)

# Close all Numeric and Tabular windows
for window in self.widget.mdi_area.subWindowList():
if window.widget().__class__.__name__ in ("Numeric", "Tabular"):
window.close()

# Drag Part
channels_tree = self.widget.channels_tree
mdi_area = self.widget.mdi_area

iterator = QtWidgets.QTreeWidgetItemIterator(channels_tree)
while iterator.value():
item = iterator.value()
# Expand Parent: Channel group 2 (Engine_1)
if item.parent() is None and item.text(0) == "Channel group 2 (Engine_1)":
item.setExpanded(True)
iterator += 1
continue
# Select item: ASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE
if item.text(0) == "ASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE":
item.setSelected(True)

item_rect = channels_tree.visualItemRect(item)
drag_position = item_rect.center()
drop_position = mdi_area.viewport().rect().center() - QtCore.QPoint(200, 200)

with mock.patch("asammdf.gui.widgets.mdi_area.WindowSelectionDialog") as mc_WindowSelectionDialog:
# Setup
mc_WindowSelectionDialog.return_value.result.return_value = True
mc_WindowSelectionDialog.return_value.disable_new_channels.return_value = False
mc_WindowSelectionDialog.return_value.selected_type.return_value = "Plot"

DragAndDrop(
source_widget=channels_tree,
destination_widget=mdi_area,
source_pos=drag_position,
destination_pos=drop_position,
)
break
iterator += 1
# Add a new Plot window with few channels
self.create_window(window_type="Plot", channels_names=["ASAM.M.SCALAR.UBYTE.VTAB_RANGE_NO_DEFAULT_VALUE"])

# Press PushButton: "Save offline windows"
with mock.patch("asammdf.gui.widgets.file.QtWidgets.QFileDialog.getSaveFileName") as mo_getSaveFileName:
Expand All @@ -454,24 +416,15 @@ def test_PushButton_SaveOfflineWindows(self):
self.assertTrue(saved_dspf.exists())

# Event
with mock.patch.object(self.widget, "load_window", wraps=self.widget.load_window) as mo_load_window, mock.patch(
"asammdf.gui.widgets.file.QtWidgets.QFileDialog.getOpenFileName"
) as mo_getOpenFileName:
mo_getOpenFileName.return_value = saved_dspf, None
QtTest.QTest.mouseClick(
self.widget.load_channel_list_btn,
QtCore.Qt.MouseButton.LeftButton,
self.load_display_file(display_file=saved_dspf)
self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2)
widget_types = set(
map(
lambda w: w.widget().__class__.__name__,
self.widget.mdi_area.subWindowList(),
)
# Pre-Evaluate
mo_load_window.assert_called()
self.assertEqual(len(self.widget.mdi_area.subWindowList()), 2)
widget_types = set(
map(
lambda w: w.widget().__class__.__name__,
self.widget.mdi_area.subWindowList(),
)
)
self.assertSetEqual({"Plot"}, widget_types)
)
self.assertSetEqual({"Plot"}, widget_types)

def test_PushButton_SelectAll(self):
"""
Expand Down
Loading

0 comments on commit c14390e

Please sign in to comment.