pytest-dev / pytest-qt

pytest plugin for Qt (PyQt5/PyQt6 and PySide2/PySide6) application testing
https://pytest-qt.readthedocs.io
MIT License
409 stars 70 forks source link

BUG: Click Away from MenuBar does not Close MenuBar #430

Open adam-grant-hendry opened 2 years ago

adam-grant-hendry commented 2 years ago

System

OS: Windows 10 Python: 3.8.10 Qt: PySide6 pytest-qt: 4.0.2

Problem

After clicking a QMenuBar item, clicking away from the menu does not close it when using qtbot.

MRE

myproj/main.py

from qtpy import QtWidgets

class View(QtWidgets.QMainWindow):
    """The main window."""

    def __init__(self):
        super().__init__()
        self.container = QtWidgets.QFrame()

        self.layout_ = QtWidgets.QVBoxLayout()
        self.layout_.setSpacing(0)
        self.layout_.setContentsMargins(0, 0, 0, 0)

        self.container.setLayout(self.layout_)
        self.setCentralWidget(self.container)

        self._create_actions()
        self._create_menubar()

    def _create_actions(self):
        self.new_action = QtWidgets.QAction(
            '&New Project...',
            self,
        )

    def _create_menubar(self) -> None:
        self.menubar = self.menuBar()
        self.file_menu = self.menubar.addMenu('&File')
        self.file_menu.addAction(self.new_action)

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = View()
    window.showMaximized()
    app.exec_()

tests/test_window.py

import pytest
from myproj.main import View
from pytestqt.qtbot import QtBot
from qtpy import QtCore

@pytest.fixture(name='window', scope='function')
def fixture_app(qtbot):
    window = View()
    window.setMouseTracking(True)
    window.showMaximized()

    yield window

def test_click_outside_menu_closes_menu(window: 'View', qtbot: 'QtBot') -> None:
    """Tests that menu closes when user clicks away from it.

    Args:
        window (view): (fixture) Qt application main window
    """
    menubar = window.menubar
    file_menu = window.file_menu
    new_action = window.new_action

    file_rect = menubar.actionGeometry(file_menu.menuAction())
    new_rect = file_menu.actionGeometry(new_action)

    pause = 1000  # milliseconds

    # Assert - Precondition
    assert not file_menu.isVisible()

    # # Act - Menubar
    qtbot.wait(pause)
    qtbot.mouseMove(menubar, file_rect.center())
    qtbot.wait(pause)
    qtbot.mouseClick(menubar, QtCore.Qt.LeftButton, pos=file_rect.center())
    qtbot.wait(pause)
    qtbot.mouseMove(file_menu, new_rect.center())
    qtbot.wait(pause)
    qtbot.mouseMove(window, window.rect().center())
    qtbot.wait(pause)
    qtbot.mouseClick(window, QtCore.Qt.LeftButton, pos=window.rect().center())
    qtbot.wait(pause)

    # Assert - Precondition
    assert not file_menu.isVisible()

Result

qtbug-104075

adam-grant-hendry commented 2 years ago

FYI, I've opened an issue on the PySide bug tracker here as well: QTBUG-104075

The-Compiler commented 2 years ago

This seems neither an issue in pytest-qt, nor an issue in PySide, but something in Qt.

adam-grant-hendry commented 2 years ago

@The-Compiler Yes, agreed. Could we add a list of pytest-qt features that are not working properly due to Qt bugs to the documentation? So far I've seen 2:

  1. mouseClick not working in PyQt5, but fixed in PyQt6: QTBUG-5232
  2. Clicking away from activated menu does not close it: QTBUG-104075

This would be very helpful to developers using pytest-qt.