enthought / pyface

pyface: traits-capable windowing framework
Other
105 stars 55 forks source link

ModalDialogTester does not reproduce proper behavior on close #1122

Closed sallenEnth closed 1 year ago

sallenEnth commented 2 years ago

When I close a ConfirmationDialog that does not have a CANCEL button it returns NO but when writing a test using ModalDialogTester I need to assert that it returned CANCEL otherwise the test does not pass. Here is a small code to reproduce the issue:

from pyface.api import CANCEL, NO, ConfirmationDialog
from pyface.ui.qt4.util.modal_dialog_tester import ModalDialogTester

dialog = ConfirmationDialog(cancel=False)
tester = ModalDialogTester(dialog.open)
tester.open_and_run(when_opened=lambda x: x.close())
assert (tester.result == CANCEL)

confirm = dialog.open()  # After opening, click X to close the dialog
assert (confirm == NO)
corranwebster commented 1 year ago

I think that this is expected, if slightly surprising behaviour. The ModalDialogTester.close() method works by using a slot on the dialog widget, and that slot is either accept or reject depending on the value of the accept parameter (it is False by default). These signals are independent of what buttons are or are not present: it doesn't interact via clicking on buttons or anything similar.

One possible approach is to explicitly select the button you want:

tester.open_and_run(when_opened=lambda x: x.click_button(NO))

although there have been issues with this on some Qt versions on Linux (see #282).

An alternative is to search for the button with the NO role, something like:

def click_no(tester):
    with tester.capture_error():
        widget = tester.get_dialog_widget()
        for button in widget.buttons():
            if widget.buttonRole(button) == QMessageBox.NoRole:
                button.click()
                return

tester.open_and_run(when_opened=click_no)
corranwebster commented 1 year ago

I'm going to close this issue for now - if this doesn't solve the issue, please re-open.