New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic tests for the ScreenshotDialog
widget and fixes
#6057
Conversation
Codecov Report
@@ Coverage Diff @@
## main #6057 +/- ##
==========================================
+ Coverage 91.62% 91.67% +0.04%
==========================================
Files 579 580 +1
Lines 50749 50800 +51
==========================================
+ Hits 46498 46569 +71
+ Misses 4251 4231 -20
|
ScreenshotDialog
widgetScreenshotDialog
widget and fixes
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
0ae5f1f
to
8ee027b
Compare
if base_result: | ||
self.save_function(save_path) | ||
return base_result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait. It looks like I was wrong here. Base on Qt documentation the accept() should return None
(void in c++) https://doc.qt.io/qt-6/qdialog.html#accept
if base_result: | |
self.save_function(save_path) | |
return base_result | |
self.save_function(save_path) | |
return base_result |
If we would like to validate then we should depend on self.result()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh totally right! So the validation should be something like: if self.result() == QDialog.DialogCode.Accepted:
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just if self.result()
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few remarks
monkeypatch.setattr(QMessageBox, "warning", overwrite_message) | ||
|
||
dialog = ScreenshotDialog( | ||
save_function, directory=str(tmp_path), history=get_save_history() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we use get_save_history
here? Why not an empty list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will change it! I think what confused me was that in the ScreenshotDialog
constructor the default value for the history
kwarg is None
def handle_qt_overwrite_message(): | ||
for widget in QApplication.topLevelWidgets(): | ||
if isinstance(widget, QMessageBox): | ||
# test should not enter here! | ||
widget.accept() | ||
nonlocal qt_overwrite_shown | ||
qt_overwrite_shown = True | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe something like this:
https://github.com/4DNucleome/PartSeg/blob/b03118cdcbb109bef5a6905a70fee7bfb1e10db1/package/tests/test_PartSeg/conftest.py#L129-L142
instead of this iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up with this logic since I tried patching the warning
method as in the link but the patch was not being triggered. Maybe patching exec
could work 🤔. My initial guess was that since the warning QMessageBox
is instantiated in Qt code (C++) the monkey patching didn't have any effect on it but I will check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked and seems like even when monkey patching exec
the Qt generated QMessageBox
warning message keeps appearing.
If I do the monkey patch and revert the changes, to first call super().accept
and then the save_function
in the accept
method for the dialog, the test hangs until I manually close the Qt generated QMessageBox
warning:
Maybe I'm missing something in the monkey patch procedure @Czaki ? 🤔
@pytest.mark.parametrize("filename", ["test", "test.png", "test.tif"])
def test_screenshot_save(qtbot, tmp_path, monkeypatch, filename):
"""Check passing different extensions with the filename."""
def save_function(path):
# check incoming path has extension event when a filename without one
# was provided
assert filename in path
assert "." in filename or ".png" in path
# create a file with the given path to check for
# non-native qt overwrite message
with open(path, "w") as mock_img:
mock_img.write("")
def qt_overwrite_qmessagebox_warning(*_, **__):
raise RuntimeError("exec_ call")
monkeypatch.setattr(QMessageBox, "exec_", qt_overwrite_qmessagebox_warning)
monkeypatch.setattr(QMessageBox, "critical", qt_overwrite_qmessagebox_warning)
monkeypatch.setattr(QMessageBox, "information", qt_overwrite_qmessagebox_warning)
monkeypatch.setattr(QMessageBox, "question", qt_overwrite_qmessagebox_warning)
monkeypatch.setattr(QMessageBox, "warning", qt_overwrite_qmessagebox_warning)
# setup dialog
dialog = ScreenshotDialog(
save_function, directory=str(tmp_path), history=[]
)
qtbot.addWidget(dialog)
dialog.setOptions(QFileDialog.DontUseNativeDialog)
dialog.show()
# check dialog and set filename
assert dialog.windowTitle() == 'Save screenshot'
line_edit = dialog.findChild(QLineEdit)
line_edit.setText(filename)
# check that no warning message related with overwriting is shown
dialog.accept()
# check the file was created
save_filename = filename if '.' in filename else f'{filename}.png'
qtbot.waitUntil(lambda: (tmp_path / save_filename).exists())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh. So it looks like Your procedure was better as maybe Qt uses inner references.
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
dafd0c0
to
667aaf3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dalthviz
I think the bug fix makes this for 0.4.19?
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
# Fixes/Closes closes #6078 # Description Adds some tests to the `ScreenshotDialog` as a continuation of the effort started at #5864 to increase Qt widgets code coverage and fixes some errors with the non-native version (the one used when launching napari from and IPython console) ## Notes and questions * The tests call the dialog `show` method and also sets the non-native option so the tests here only cover the case when napari is being launched from an IPython console. The testing of the OS native version of the dialog is more involved. * Checking the code related with the dialogs available I noticed that some of them (files/widgets classes) have the `qt_*` /`Qt` prefix or the `_dialog`/`Dialog` suffix but others don't (for example `screenshot_dialog.py/ScreenshotDialog` vs `qt_about/QtAbout`). Is that something worthy to standardize or maybe there is already some logic behind the naming? --------- Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com> Co-authored-by: Genevieve Buckley <30920819+GenevieveBuckley@users.noreply.github.com> Co-authored-by: Juan Nunez-Iglesias <jni@fastmail.com> Co-authored-by: Peter Sobolewski <76622105+psobolewskiPhD@users.noreply.github.com>
Fixes/Closes
closes #6078
Description
Adds some tests to the
ScreenshotDialog
as a continuation of the effort started at #5864 to increase Qt widgets code coverage and fixes some errors with the non-native version (the one used when launching napari from and IPython console)Notes and questions
show
method and also sets the non-native option so the tests here only cover the case when napari is being launched from an IPython console. The testing of the OS native version of the dialog is more involved.qt_*
/Qt
prefix or the_dialog
/Dialog
suffix but others don't (for examplescreenshot_dialog.py/ScreenshotDialog
vsqt_about/QtAbout
). Is that something worthy to standardize or maybe there is already some logic behind the naming?Type of change
How has this been tested?
as there are small differences between the two Qt bindings.
Final checklist: