-
Notifications
You must be signed in to change notification settings - Fork 95
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
[WIP] UITester support for qt TreeEditor #1713
Open
aaronayres35
wants to merge
9
commits into
main
Choose a base branch
from
UITester-TreeEditor
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 7 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
52f0508
add start of TreeEditor support for Qt
aaronayres35 65687cb
we need _interaction_helpers for QAbstractItemModel (these are also i…
aaronayres35 691b342
we need MouseDClick and TreeNode in the api
aaronayres35 eccc2df
lots of clean up of implementation and expose in default_registry
aaronayres35 51a735f
add a test for the TreeEditor_demo
aaronayres35 61c4c43
we are really using a _TreeWidget which subclasses QTreeWidget which …
aaronayres35 5c004c7
update docstring for TreeNode
aaronayres35 6fce173
flake8
aaronayres35 dfc773b
Merge branch 'master' into UITester-TreeEditor
aaronayres35 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
85 changes: 85 additions & 0 deletions
85
traitsui/examples/demo/Standard_Editors/tests/test_TreeEditor_demo.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# (C) Copyright 2004-2021 Enthought, Inc., Austin, TX | ||
# All rights reserved. | ||
# | ||
# This software is provided without warranty under the terms of the BSD | ||
# license included in LICENSE.txt and may be redistributed only under | ||
# the conditions described in the aforementioned license. The license | ||
# is also available online at http://www.enthought.com/licenses/BSD.txt | ||
# | ||
# Thanks for using Enthought open source! | ||
|
||
""" | ||
This example demonstrates how to test interacting with a TreeEditor. | ||
|
||
The GUI being tested is written in the demo under the same name (minus the | ||
preceding 'test') in the outer directory. | ||
""" | ||
|
||
import os | ||
import runpy | ||
import unittest | ||
|
||
from traitsui.testing.api import ( | ||
DisplayedText, | ||
KeyClick, | ||
KeySequence, | ||
MouseClick, | ||
MouseDClick, | ||
TreeNode, | ||
UITester | ||
) | ||
from traitsui.tests._tools import requires_toolkit, ToolkitName | ||
|
||
#: Filename of the demo script | ||
FILENAME = "TreeEditor_demo.py" | ||
|
||
#: Path of the demo script | ||
DEMO_PATH = os.path.join(os.path.dirname(__file__), "..", FILENAME) | ||
|
||
|
||
class TestTreeEditorDemo(unittest.TestCase): | ||
|
||
@requires_toolkit([ToolkitName.qt]) | ||
def test_tree_editor_demo(self): | ||
demo = runpy.run_path(DEMO_PATH)["demo"] | ||
tester = UITester() | ||
with tester.create_ui(demo) as ui: | ||
root_actor = tester.find_by_name(ui, "company") | ||
|
||
# Enthought->Department->Business->(First employee) | ||
node = root_actor.locate(TreeNode((0, 0, 0, 0), 0)) | ||
node.perform(MouseClick()) | ||
|
||
name_actor = node.find_by_name("name") | ||
for _ in range(5): | ||
name_actor.perform(KeyClick("Backspace")) | ||
name_actor.perform(KeySequence("James")) | ||
self.assertEqual( | ||
demo.company.departments[0].employees[0].name, | ||
"James", | ||
) | ||
|
||
# Enthought->Department->Scientific | ||
demo.company.departments[1].name = "Scientific Group" | ||
node = root_actor.locate(TreeNode((0, 0, 1), 0)) | ||
self.assertEqual( | ||
node.inspect(DisplayedText()), "Scientific Group" | ||
) | ||
|
||
# Enthought->Department->Business | ||
node = root_actor.locate(TreeNode((0, 0, 0), 0)) | ||
node.perform(MouseClick()) | ||
node.perform(MouseDClick()) | ||
|
||
name_actor = node.find_by_name("name") | ||
name_actor.perform(KeySequence(" Group")) | ||
self.assertEqual( | ||
demo.company.departments[0].name, | ||
"Business Group", | ||
) | ||
|
||
|
||
# Run the test(s) | ||
unittest.TextTestRunner().run( | ||
unittest.TestLoader().loadTestsFromTestCase(TestTreeEditorDemo) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/tree_editor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# Copyright (c) 2005-2020, Enthought, Inc. | ||
# All rights reserved. | ||
# | ||
# This software is provided without warranty under the terms of the BSD | ||
# license included in LICENSE.txt and may be redistributed only | ||
# under the conditions described in the aforementioned license. The license | ||
# is also available online at http://www.enthought.com/licenses/BSD.txt | ||
# | ||
# Thanks for using Enthought open source! | ||
# | ||
|
||
from traitsui.qt4.tree_editor import SimpleEditor | ||
|
||
|
||
from traitsui.testing.tester.command import ( | ||
MouseClick, MouseDClick, KeyClick, KeySequence | ||
) | ||
from traitsui.testing.tester.locator import TreeNode | ||
from traitsui.testing.tester.query import DisplayedText | ||
from traitsui.testing.tester._ui_tester_registry.qt4 import ( | ||
_interaction_helpers | ||
) | ||
|
||
from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( | ||
BaseSourceWithLocation | ||
) | ||
from traitsui.testing.tester._ui_tester_registry._traitsui_ui import ( | ||
register_traitsui_ui_solvers, | ||
) | ||
|
||
class _SimpleEditorWithTreeNode(BaseSourceWithLocation): | ||
source_class = SimpleEditor | ||
locator_class = TreeNode | ||
handlers = [ | ||
(MouseClick, lambda wrapper, _: wrapper._target._mouse_click( | ||
delay=wrapper.delay)), | ||
(MouseDClick, lambda wrapper, _: wrapper._target._mouse_dclick( | ||
delay=wrapper.delay)), | ||
(KeySequence, | ||
lambda wrapper, action: wrapper._target._key_sequence( | ||
sequence=action.sequence, | ||
delay=wrapper.delay, | ||
)), | ||
(KeyClick, | ||
lambda wrapper, action: wrapper._target._key_press( | ||
key=action.key, | ||
delay=wrapper.delay, | ||
)), | ||
(DisplayedText, | ||
lambda wrapper, _: wrapper._target._get_displayed_text()), | ||
] | ||
|
||
@classmethod | ||
def register(cls, registry): | ||
""" Class method to register interactions on a | ||
_SimpleEditorWithTreeNode for the given registry. | ||
|
||
If there are any conflicts, an error will occur. | ||
|
||
Parameters | ||
---------- | ||
registry : TargetRegistry | ||
The registry being registered to. | ||
""" | ||
super().register(registry) | ||
register_traitsui_ui_solvers( | ||
registry=registry, | ||
target_class=cls, | ||
traitsui_ui_getter=lambda target: target._get_nested_ui() | ||
) | ||
|
||
def _get_model_view_index(self): | ||
tree_widget = self.source._tree | ||
i_column = self.location.column | ||
i_rows = iter(self.location.row) | ||
item = tree_widget.topLevelItem(next(i_rows)) | ||
for i_row in i_rows: | ||
item = item.child(i_row) | ||
q_model_index = tree_widget.indexFromItem(item, i_column) | ||
return dict( | ||
model=tree_widget.model(), | ||
view=tree_widget, | ||
index=q_model_index, | ||
) | ||
|
||
def _mouse_click(self, delay=0): | ||
_interaction_helpers.mouse_click_item_view( | ||
**self._get_model_view_index(), | ||
delay=delay, | ||
) | ||
|
||
def _mouse_dclick(self, delay=0): | ||
_interaction_helpers.mouse_dclick_item_view( | ||
**self._get_model_view_index(), | ||
delay=delay, | ||
) | ||
|
||
def _key_press(self, key, delay=0): | ||
_interaction_helpers.key_press_item_view( | ||
**self._get_model_view_index(), | ||
key=key, | ||
delay=delay, | ||
) | ||
|
||
def _key_sequence(self, sequence, delay=0): | ||
_interaction_helpers.key_sequence_item_view( | ||
**self._get_model_view_index(), | ||
sequence=sequence, | ||
delay=delay, | ||
) | ||
|
||
def _get_displayed_text(self): | ||
return _interaction_helpers.get_display_text_item_view( | ||
**self._get_model_view_index(), | ||
) | ||
|
||
def _get_nested_ui(self): | ||
""" Method to get the nested ui corresponding to the List element at | ||
the given index. | ||
""" | ||
return self.source._editor._node_ui | ||
|
||
|
||
def register(registry): | ||
_SimpleEditorWithTreeNode.register(registry) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This logic and the
TreeNode
object having arow
/column
I need to think about more carefully. I had this code in a branch locally from a long time ago which I believe had originally been pulled from one of Kit's draft PRs.There may be a simple way to do this / at the very least I need to better document the TreeNode class to say what row and column actually specify. In this case (see test_TreeEditor_demo.py) row is a tuple containing the index of the node of interest at subsequent levels of the tree, and column is the index at that last level (?). I have just been using column as 0, ... it may be possible we only need one single tuple to do this TreeNode location.