Repository: napari/napari

Issue:
Add tests for popups
## 🧰 Task
<!-- A clear and concise description of the task -->
I realized after reviewing #3766 , that I did not include tests for some of the popup dialogs I worked on (the grid mode popup and the playback settings popup).
These need to be added...  




Discussion:

Resolving patch:
diff --git a/napari/_qt/widgets/qt_viewer_buttons.py b/napari/_qt/widgets/qt_viewer_buttons.py
--- a/napari/_qt/widgets/qt_viewer_buttons.py
+++ b/napari/_qt/widgets/qt_viewer_buttons.py
@@ -183,10 +183,11 @@ def open_perspective_popup(self):
         # make slider connected to perspective parameter
         sld = QSlider(Qt.Orientation.Horizontal, self)
         sld.setRange(0, max(90, int(self.viewer.camera.perspective)))
-        sld.setValue(self.viewer.camera.perspective)
+        sld.setValue(int(self.viewer.camera.perspective))
         sld.valueChanged.connect(
             lambda v: setattr(self.viewer.camera, 'perspective', v)
         )
+        self.perspective_slider = sld
 
         # make layout
         layout = QHBoxLayout()


Test patch:
diff --git a/napari/_qt/widgets/_tests/test_qt_dims.py b/napari/_qt/widgets/_tests/test_qt_dims.py
--- a/napari/_qt/widgets/_tests/test_qt_dims.py
+++ b/napari/_qt/widgets/_tests/test_qt_dims.py
@@ -303,3 +303,13 @@ def test_play_button(qtbot):
     with patch.object(button.popup, 'show_above_mouse') as mock_popup:
         qtbot.mouseClick(button, Qt.RightButton)
         mock_popup.assert_called_once()
+
+    # Check popup updates widget properties (fps, play mode and loop mode)
+    button.fpsspin.clear()
+    qtbot.keyClicks(button.fpsspin, "11")
+    qtbot.keyClick(button.fpsspin, Qt.Key_Enter)
+    assert slider.fps == button.fpsspin.value() == 11
+    button.reverse_check.setChecked(True)
+    assert slider.fps == -button.fpsspin.value() == -11
+    button.mode_combo.setCurrentText('once')
+    assert slider.loop_mode == button.mode_combo.currentText() == 'once'
diff --git a/napari/_qt/widgets/_tests/test_qt_viewer_buttons.py b/napari/_qt/widgets/_tests/test_qt_viewer_buttons.py
new file mode 100644
--- /dev/null
+++ b/napari/_qt/widgets/_tests/test_qt_viewer_buttons.py
@@ -0,0 +1,133 @@
+import pytest
+from qtpy.QtCore import QPoint
+from qtpy.QtWidgets import QApplication
+
+from napari._qt.dialogs.qt_modal import QtPopup
+from napari._qt.widgets.qt_viewer_buttons import QtViewerButtons
+from napari.components.viewer_model import ViewerModel
+
+
+@pytest.fixture
+def qt_viewer_buttons(qtbot):
+    # create viewer model and buttons
+    viewer = ViewerModel()
+    viewer_buttons = QtViewerButtons(viewer)
+    qtbot.addWidget(viewer_buttons)
+
+    yield viewer, viewer_buttons
+
+    # close still open popup widgets
+    for widget in QApplication.topLevelWidgets():
+        if isinstance(widget, QtPopup):
+            widget.close()
+    viewer_buttons.close()
+
+
+def test_roll_dims_button_popup(qt_viewer_buttons, qtbot):
+    """
+    Make sure the QtViewerButtons.rollDimsButton popup works.
+    """
+    # get viewer model and buttons
+    viewer, viewer_buttons = qt_viewer_buttons
+    assert viewer_buttons.rollDimsButton
+
+    # make dims order settings popup
+    viewer_buttons.rollDimsButton.customContextMenuRequested.emit(QPoint())
+
+    # check that the popup widget is available
+    dims_sorter_popup = None
+    for widget in QApplication.topLevelWidgets():
+        if isinstance(widget, QtPopup):
+            dims_sorter_popup = widget
+    assert dims_sorter_popup
+
+
+def test_grid_view_button_popup(qt_viewer_buttons, qtbot):
+    """
+    Make sure the QtViewerButtons.gridViewbutton popup works.
+
+    The popup widget should be able to show/change viewer grid settings.
+    """
+    # get viewer model and buttons
+    viewer, viewer_buttons = qt_viewer_buttons
+    assert viewer_buttons.gridViewButton
+
+    # make grid settings popup
+    viewer_buttons.gridViewButton.customContextMenuRequested.emit(QPoint())
+
+    # check popup widgets were created
+    assert viewer_buttons.grid_stride_box
+    assert viewer_buttons.grid_stride_box.value() == viewer.grid.stride
+    assert viewer_buttons.grid_width_box
+    assert viewer_buttons.grid_width_box.value() == viewer.grid.shape[1]
+    assert viewer_buttons.grid_height_box
+    assert viewer_buttons.grid_height_box.value() == viewer.grid.shape[0]
+
+    # check that widget controls value changes update viewer grid values
+    viewer_buttons.grid_stride_box.setValue(2)
+    assert viewer_buttons.grid_stride_box.value() == viewer.grid.stride
+    viewer_buttons.grid_width_box.setValue(2)
+    assert viewer_buttons.grid_width_box.value() == viewer.grid.shape[1]
+    viewer_buttons.grid_height_box.setValue(2)
+    assert viewer_buttons.grid_height_box.value() == viewer.grid.shape[0]
+
+    # check viewer grid values changes update popup widget controls values
+    viewer.grid.stride = 1
+    viewer.grid.shape = (-1, -1)
+    # popup needs to be relaunched to get widget controls with the new values
+    for widget in QApplication.topLevelWidgets():
+        if isinstance(widget, QtPopup):
+            widget.close()
+    viewer_buttons.gridViewButton.customContextMenuRequested.emit(QPoint())
+    assert viewer_buttons.grid_stride_box.value() == viewer.grid.stride
+    viewer_buttons.grid_width_box.setValue(2)
+    assert viewer_buttons.grid_width_box.value() == viewer.grid.shape[1]
+    assert viewer_buttons.grid_height_box.value() == viewer.grid.shape[0]
+
+
+def test_ndisplay_button_popup(qt_viewer_buttons, qtbot):
+    """
+    Make sure the QtViewerButtons.ndisplayButton popup works.
+    """
+    # get viewer model and buttons
+    viewer, viewer_buttons = qt_viewer_buttons
+    assert viewer_buttons.ndisplayButton
+
+    # toggle ndisplay to be able to trigger popup
+    viewer.dims.ndisplay = 2 + (viewer.dims.ndisplay == 2)
+
+    # make ndisplay perspective setting popup
+    viewer_buttons.ndisplayButton.customContextMenuRequested.emit(QPoint())
+    perspective_popup = None
+    for widget in QApplication.topLevelWidgets():
+        if isinstance(widget, QtPopup):
+            perspective_popup = widget
+    assert perspective_popup
+
+    # check perspective slider change affects viewer camera perspective
+    assert viewer_buttons.perspective_slider
+    viewer_buttons.perspective_slider.setValue(5)
+    assert (
+        viewer.camera.perspective
+        == viewer_buttons.perspective_slider.value()
+        == 5
+    )
+
+    # popup needs to be relaunched to get widget controls with the new values
+    perspective_popup.close()
+    perspective_popup = None
+
+    # check viewer camera perspective value affects perspective popup slider
+    # initial value
+    viewer.camera.perspective = 10
+    viewer_buttons.ndisplayButton.customContextMenuRequested.emit(QPoint())
+    for widget in QApplication.topLevelWidgets():
+        if isinstance(widget, QtPopup):
+            perspective_popup = widget
+    assert perspective_popup
+    assert viewer_buttons.perspective_slider
+    assert (
+        viewer.camera.perspective
+        == viewer_buttons.perspective_slider.value()
+        == 10
+    )