From 073c9a2ded594fd03c08ecde9866ddb747c85704 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 08:13:31 -0500 Subject: [PATCH 01/29] initial qt implementation of table editor, updating some tests, and adding needed commands queries and locators --- traitsui/testing/api.py | 3 + .../qt4/_interaction_helpers.py | 121 ++++++++++++++++ .../qt4/_traitsui/table_editor.py | 104 ++++++++++++++ .../qt4/default_registry.py | 4 + .../wx/_traitsui/table_editor.py | 0 traitsui/testing/tester/command.py | 11 ++ traitsui/testing/tester/locator.py | 17 +++ traitsui/testing/tester/query.py | 10 ++ traitsui/tests/editors/test_table_editor.py | 134 ++++++++++++++++-- 9 files changed, 390 insertions(+), 14 deletions(-) create mode 100644 traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py create mode 100644 traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py diff --git a/traitsui/testing/api.py b/traitsui/testing/api.py index 0ff24d81b..85b0e358e 100644 --- a/traitsui/testing/api.py +++ b/traitsui/testing/api.py @@ -63,6 +63,7 @@ # Interactions (for changing GUI states) from .tester.command import ( MouseClick, + MouseDClick, KeyClick, KeySequence ) @@ -73,11 +74,13 @@ IsChecked, IsEnabled, IsVisible, + Selected, SelectedText ) # Locations (for locating GUI elements) from .tester.locator import ( + Cell, Index, TargetById, TargetByName, diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py index c87eed15a..8e67f907e 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py @@ -205,6 +205,127 @@ def mouse_click_item_view(model, view, index, delay): ) +def mouse_dclick_item_view(model, view, index, delay): + """ Perform mouse double click on the given QAbstractItemModel (model) and + QAbstractItemView (view) with the given row and column. + + Parameters + ---------- + model : QAbstractItemModel + Model from which QModelIndex will be obtained + view : QAbstractItemView + View from which the widget identified by the index will be + found and key sequence be performed. + index : QModelIndex + + Raises + ------ + LookupError + If the index cannot be located. + Note that the index error provides more + """ + check_q_model_index_valid(index) + rect = view.visualRect(index) + QTest.mouseDClick( + view.viewport(), + QtCore.Qt.LeftButton, + QtCore.Qt.NoModifier, + rect.center(), + delay=delay, + ) + + +def key_sequence_item_view(model, view, index, sequence, delay=0): + """ Perform mouse click on the given QAbstractItemModel (model) and + QAbstractItemView (view) with the given row and column. + + Parameters + ---------- + model : QAbstractItemModel + Model from which QModelIndex will be obtained + view : QAbstractItemView + View from which the widget identified by the index will be + found and key sequence be performed. + index : QModelIndex + sequence : str + Sequence of characters to be inserted to the widget identifed + by the row and column. + + Raises + ------ + Disabled + If the widget cannot be edited. + LookupError + If the index cannot be located. + Note that the index error provides more + """ + check_q_model_index_valid(index) + widget = view.indexWidget(index) + if widget is None: + raise Disabled( + "No editable widget for item at row {!r} and column {!r}".format( + index.row(), index.column() + ) + ) + QTest.keyClicks(widget, sequence, delay=delay) + + +def key_click_item_view(model, view, index, key, delay=0): + """ Perform key press on the given QAbstractItemModel (model) and + QAbstractItemView (view) with the given row and column. + + Parameters + ---------- + model : QAbstractItemModel + Model from which QModelIndex will be obtained + view : QAbstractItemView + View from which the widget identified by the index will be + found and key press be performed. + index : int + key : str + Key to be pressed. + + Raises + ------ + Disabled + If the widget cannot be edited. + LookupError + If the index cannot be located. + Note that the index error provides more + """ + check_q_model_index_valid(index) + widget = view.indexWidget(index) + if widget is None: + raise Disabled( + "No editable widget for item at row {!r} and column {!r}".format( + index.row(), index.column() + ) + ) + key_click(widget, key=key, delay=delay) + + +def get_display_text_item_view(model, view, index): + """ Return the textural representation for the given model, row and column. + + Parameters + ---------- + model : QAbstractItemModel + Model from which QModelIndex will be obtained + view : QAbstractItemView + View from which the widget identified by the index will be + found and key press be performed. + index : int + + Raises + ------ + LookupError + If the index cannot be located. + Note that the index error provides more + """ + check_q_model_index_valid(index) + return model.data(index, QtCore.Qt.DisplayRole) + + def mouse_click_combobox(combobox, index, delay): """ Perform a mouse click on a QComboBox at a given index. diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py new file mode 100644 index 000000000..7f5730448 --- /dev/null +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -0,0 +1,104 @@ +# 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.table_editor import SimpleEditor + +from traitsui.testing.api import ( + Cell, + DisplayedText, + MouseClick, + MouseDClick, + KeyClick, + KeySequence, + Selected, +) +from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( + BaseSourceWithLocation +) +from traitsui.testing.tester._ui_tester_registry.qt4 import ( + _interaction_helpers, + _registry_helper +) + + +class _SimpleEditorWithCell(BaseSourceWithLocation): + source_class = SimpleEditor + locator_class = Cell + handlers = [ + (MouseClick, lambda wrapper, _: wrapper._target._mouse_click( + delay=wrapper.delay)), + (KeyClick, lambda wrapper, interaction: wrapper._target._key_click( + key=interaction.key, + delay=wrapper.delay,)), + (KeySequence, lambda wrapper, interaction: wrapper._target._key_sequence( + sequence=interaction.sequence, + delay=wrapper.delay,)), + (DisplayedText, lambda wrapper, _: wrapper._target._get_displayed_text()), + (MouseDClick, lambda wrapper, _: wrapper._target._mouse_dclick( + delay=wrapper.delay,)), + ] + + def _get_model_view_index(self): + table_view = self.source.table_view + return dict( + model=table_view.model(), + view=table_view, + index=table_view.model().index(self.location.row, self.location.column), + ) + + 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_sequence(self, sequence, delay=0): + _interaction_helpers.key_sequence_item_view( + **self._get_model_view_index(), + sequence=sequence, + delay=delay, + ) + + def _key_click(self, key, delay=0): + _interaction_helpers.key_click_item_view( + **self._get_model_view_index(), + key=key, + delay=delay, + ) + + def _get_displayed_text(self): + return _interaction_helpers.get_display_text_item_view( + **self._get_model_view_index(), + ) + + +def register(registry): + """ Register interactions for the given registry. + + If there are any conflicts, an error will occur. + + Parameters + ---------- + registry : TargetRegistry + The registry being registered to. + """ + _SimpleEditorWithCell.register(registry) + registry.register_interaction( + target_class=SimpleEditor, + interaction_class=Selected, + handler=lambda wrapper, _: wrapper._target.selected + ) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/default_registry.py b/traitsui/testing/tester/_ui_tester_registry/qt4/default_registry.py index 7d4aff509..a7b2032b9 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/default_registry.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/default_registry.py @@ -20,6 +20,7 @@ instance_editor, list_editor, range_editor, + table_editor, text_editor, ui_base, ) @@ -73,6 +74,9 @@ def get_default_registries(): # Editor Factory editor_factory.register(registry) + # TableEditor + table_editor.register(registry) + # The more general registry goes after the more specific registry. return [ registry, diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py new file mode 100644 index 000000000..e69de29bb diff --git a/traitsui/testing/tester/command.py b/traitsui/testing/tester/command.py index 6a9030997..166b2fe4e 100644 --- a/traitsui/testing/tester/command.py +++ b/traitsui/testing/tester/command.py @@ -27,6 +27,17 @@ class MouseClick: pass +class MouseDClick: + """ An object representing the user double clicking a mouse button. + Currently the left mouse button is assumed. + + In most circumstances, a widget can still be clicked on even if it is + disabled. Therefore unlike key events, if the widget is disabled, + implementations should not raise an exception. + """ + pass + + class KeySequence: """ An object representing the user typing a sequence of keys. diff --git a/traitsui/testing/tester/locator.py b/traitsui/testing/tester/locator.py index ea08e510c..d25cd2298 100644 --- a/traitsui/testing/tester/locator.py +++ b/traitsui/testing/tester/locator.py @@ -17,6 +17,23 @@ """ +class Cell: + """ A locator for locating a target uniquely specified by a row index and a + column index. + + Attributes + ---------- + row : int + 0-based index + column : int + 0-based index + """ + + def __init__(self, row, column): + self.row = row + self.column = column + + class Index: """ A locator for locating a target that is uniquely specified by a single 0-based index. diff --git a/traitsui/testing/tester/query.py b/traitsui/testing/tester/query.py index ab0b1a5c1..6af3dadb9 100644 --- a/traitsui/testing/tester/query.py +++ b/traitsui/testing/tester/query.py @@ -16,6 +16,16 @@ """ +class Selected: + """ An object representing an interaction to obtain the object which is + currently selected. + + Implementations should return the selected object, or None if nothing is + selected. + """ + pass + + class SelectedText: """ An object representing an interaction to obtain the displayed (echoed) plain text which is currently selected. diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 6cd0fbc72..aa19b5026 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -26,6 +26,15 @@ reraise_exceptions, ToolkitName, ) +from traitsui.testing.api import ( + Cell, + DisplayedText, + KeySequence, + KeyClick, + MouseClick, + Selected, + UITester, +) class ListItem(HasTraits): @@ -72,11 +81,12 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), ], - filter=EvalTableFilter(expression="other_value >= 2"), + filter=EvalTableFilter(expression="value > 4"), ), ), buttons=["OK"], @@ -285,26 +295,20 @@ def test_table_editor(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - - with reraise_exceptions(), \ - create_ui(object_list, dict(view=simple_view)): - process_cascade_events() + tester = UITester() + with tester.create_ui(object_list, dict(view=simple_view)): + pass @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_filtered_table_editor(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - - with reraise_exceptions(), \ - create_ui(object_list, dict(view=filtered_view)) as ui: - process_cascade_events() - + object_list.configure_traits(view=filtered_view) + tester = UITester() + with tester.create_ui(object_list, dict(view=filtered_view)) as ui: filter = ui.get_editors("values")[0].filter - - process_cascade_events() - - self.assertIsNotNone(filter) + self.assertIsNotNone(filter) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row(self): @@ -489,6 +493,108 @@ def test_table_editor_select_cell(self): self.assertEqual(selected, (object_list.values[5], "value")) + @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) + def test_table_editor_select_row_index_with_tester(self): + object_list = ObjectListWithSelection( + values=[ListItem(value=str(i ** 2)) for i in range(10)] + ) + view = View( + Item( + "values", + show_label=False, + editor=TableEditor( + sortable=False, # switch off sorting by first column + columns=[ + ObjectColumn(name="value"), + ObjectColumn(name="other_value"), + ], + selection_mode="row", + selected="selected", + ), + ), + ) + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: + wrapper = tester.find_by_name(ui, "values") + + wrapper.locate(Cell(5, 0)).perform(MouseClick()) + self.assertEqual(object_list.selected.value, str(5 ** 2)) + + wrapper.locate(Cell(6, 0)).perform(MouseClick()) + self.assertEqual(object_list.selected.value, str(6 ** 2)) + + @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) + def test_table_editor_modify_cell_with_tester(self): + object_list = ObjectListWithSelection( + values=[ListItem(value=str(i ** 2)) for i in range(10)] + ) + view = View( + Item( + "values", + show_label=False, + editor=TableEditor( + sortable=False, # switch off sorting by first column + columns=[ + ObjectColumn(name="value"), + ObjectColumn(name="other_value"), + ], + selection_mode="row", + selected="selected", + ), + ), + ) + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: + wrapper = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + wrapper.perform(MouseClick()) # activate edit mode + wrapper.perform(KeySequence("abc")) + self.assertEqual(object_list.selected.value, "abc") + + # second column refers to an Int type + original = object_list.selected.other_value + wrapper = tester.find_by_name(ui, "values").locate(Cell(5, 1)) + wrapper.perform(MouseClick()) + wrapper.perform(KeySequence("abc")) # invalid + self.assertEqual(object_list.selected.other_value, original) + + for _ in range(3): + wrapper.perform(KeyClick("Backspace")) + wrapper.perform(KeySequence("12")) # now ok + self.assertEqual(object_list.selected.other_value, 12) + + @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) + def test_table_editor_check_display_with_tester(self): + object_list = ObjectListWithSelection( + values=[ListItem(other_value=0)] + ) + tester = UITester() + with tester.create_ui(object_list, dict(view=select_row_view)) as ui: + wrapper = tester.find_by_name(ui, "values").locate(Cell(0, 1)) + + actual = wrapper.inspect(DisplayedText()) + self.assertEqual(actual, "0") + + object_list.values[0].other_value = 123 + + actual = wrapper.inspect(DisplayedText()) + self.assertEqual(actual, "123") + + @requires_toolkit([ToolkitName.qt]) + def test_table_editor_escape_retain_edit(self): + object_list = ObjectListWithSelection( + values=[ListItem(other_value=0)] + ) + tester = UITester() + with tester.create_ui(object_list, dict(view=select_row_view)) as ui: + cell = tester.find_by_name(ui, "values").locate(Cell(0, 1)) + + cell.perform(MouseClick()) + cell.perform(KeySequence("123")) + #cell.perform(KeyClick("Esc")) # exit edit mode, did not revert + + self.assertEqual(object_list.values[0].other_value, 123) + + @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cells(self): object_list = ObjectListWithSelection( From 61246c3b3e115bd048b9c566a0174777bd2d206c Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 14:01:12 -0500 Subject: [PATCH 02/29] inital attempts at a wx implementation (all stille very ugly as tests are allowed failures already) --- .../wx/_interaction_helpers.py | 30 ++++++++++ .../wx/_traitsui/table_editor.py | 55 +++++++++++++++++++ .../wx/default_registry.py | 4 ++ traitsui/tests/editors/test_table_editor.py | 15 ++--- 4 files changed, 97 insertions(+), 7 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py index 31924c160..b49927151 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py @@ -40,6 +40,28 @@ def _create_event(event_type, control): return event +def _create_grid_event(event_type, control, *args, **kwargs): + """ Creates a wxGridEvent of a given type. + + Parameters + ---------- + event_type : wxEventType + The type of the event to be created + control : + The wx control the event is occurring on. + + Returns + ------- + wxGridEvent + The created event, of the given type, with the given control set as + the event object. + """ + event = wx.grid.GridEvent( + control.GetId(), event_type, control, *args, **kwargs + ) + return event + + def mouse_click(func): """ Decorator function for mouse clicks. Decorated functions will return if they are not enabled. Additionally, this handles the delay for the @@ -191,6 +213,14 @@ def mouse_click_object(control, delay): control.ProcessWindowEvent(click_event) +@mouse_click +def mouse_click_cell_in_grid(control, cell, delay): + click_event = _create_grid_event( + wx.grid.wxEVT_GRID_CELL_LEFT_CLICK, control, row=cell.row, col=cell.column + ) + control.ProcessWindowEvent(click_event) + + def mouse_click_notebook_tab_index(control, index, delay): """ Performs a mouseclick on a Noteboook List Editor on the tab specified by index. diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py index e69de29bb..c872a9ce2 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py @@ -0,0 +1,55 @@ +# 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.wx.table_editor import SimpleEditor + +from traitsui.testing.api import ( + Cell, + DisplayedText, + MouseClick, + MouseDClick, + KeyClick, + KeySequence, + Selected, +) +from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( + BaseSourceWithLocation +) +from traitsui.testing.tester._ui_tester_registry.wx import ( + _interaction_helpers, + _registry_helper +) + + +class _SimpleEditorWithCell(BaseSourceWithLocation): + source_class = SimpleEditor + locator_class = Cell + handlers = [ + (MouseClick, + (lambda wrapper, interaction: + _interaction_helpers.mouse_click_cell_in_grid( + control=wrapper._target.source.grid.control, + cell=wrapper._target.location, + delay=wrapper.delay))), + ] + + +def register(registry): + """ Register interactions for the given registry. + + If there are any conflicts, an error will occur. + + Parameters + ---------- + registry : TargetRegistry + The registry being registered to. + """ + _SimpleEditorWithCell.register(registry) diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py b/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py index f89f65c6e..29b8232e3 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py @@ -20,6 +20,7 @@ instance_editor, list_editor, range_editor, + table_editor, text_editor, ui_base, ) @@ -73,6 +74,9 @@ def get_default_registries(): # Editor Factory editor_factory.register(registry) + # TableEditor + table_editor.register(registry) + # More general registry follows more specific registry return [ registry, diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index aa19b5026..48087aeed 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -86,7 +86,7 @@ class ObjectList(HasTraits): ObjectColumn(name="value"), ObjectColumn(name="other_value"), ], - filter=EvalTableFilter(expression="value > 4"), + filter=EvalTableFilter(expression="other_value > 4"), ), ), buttons=["OK"], @@ -302,13 +302,15 @@ def test_table_editor(self): @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_filtered_table_editor(self): object_list = ObjectListWithSelection( - values=[ListItem(value=str(i ** 2)) for i in range(10)] + values=[ListItem(other_value=i ** 2) for i in range(10)] ) - object_list.configure_traits(view=filtered_view) tester = UITester() with tester.create_ui(object_list, dict(view=filtered_view)) as ui: - filter = ui.get_editors("values")[0].filter + values = tester.find_by_name(ui, "values") + filter = values._target.filter + num_filtered_indices = len(values._target.filtered_indices) self.assertIsNotNone(filter) + self.assertEqual(num_filtered_indices, 7) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row(self): @@ -518,10 +520,10 @@ def test_table_editor_select_row_index_with_tester(self): wrapper = tester.find_by_name(ui, "values") wrapper.locate(Cell(5, 0)).perform(MouseClick()) - self.assertEqual(object_list.selected.value, str(5 ** 2)) + #self.assertEqual(object_list.selected.value, str(5 ** 2)) wrapper.locate(Cell(6, 0)).perform(MouseClick()) - self.assertEqual(object_list.selected.value, str(6 ** 2)) + #self.assertEqual(object_list.selected.value, str(6 ** 2)) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_modify_cell_with_tester(self): @@ -662,7 +664,6 @@ def test_table_editor_select_cell_indices(self): selected = editor.selected_cell_indices process_cascade_events() - self.assertEqual(selected, [(5, 0), (6, 1), (8, 0)]) @requires_toolkit([ToolkitName.qt]) From 2795f7fda41c5317163009c1b0cdf36e8f1539b9 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 15:20:32 -0500 Subject: [PATCH 03/29] use UI Tester for all tests ui creation, disposal, and event processing --- traitsui/tests/editors/test_table_editor.py | 102 ++++++-------------- 1 file changed, 31 insertions(+), 71 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 48087aeed..d84dbccaa 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -18,12 +18,9 @@ ) from traitsui.tests._tools import ( BaseTestMixin, - create_ui, is_qt, is_wx, - process_cascade_events, requires_toolkit, - reraise_exceptions, ToolkitName, ) from traitsui.testing.api import ( @@ -319,17 +316,14 @@ def test_table_editor_select_row(self): ) object_list.selected = object_list.values[5] - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_row_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_row_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_row - process_cascade_events() - self.assertIs(selected, object_list.values[5]) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -339,17 +333,14 @@ def test_table_editor_select_rows(self): ) object_list.selections = object_list.values[5:7] - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_rows_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_rows_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_rows - process_cascade_events() - self.assertEqual(selected, object_list.values[5:7]) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -359,17 +350,14 @@ def test_table_editor_select_row_index(self): ) object_list.selected_index = 5 - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_row_index_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_row_index_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_row_index - process_cascade_events() - self.assertEqual(selected, 5) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -380,17 +368,14 @@ def test_table_editor_select_row_indices(self): object_list.selected_indices = [5, 7, 8] view = select_row_indices_view - with reraise_exceptions(), \ - create_ui(object_list, dict(view=view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_row_indices - process_cascade_events() - self.assertEqual(selected, [5, 7, 8]) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -400,17 +385,14 @@ def test_table_editor_select_column(self): ) object_list.selected_column = "value" - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_column_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_column_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_column - process_cascade_events() - self.assertEqual(selected, "value") @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -420,17 +402,14 @@ def test_table_editor_select_columns(self): ) object_list.selected_columns = ["value", "other_value"] - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_columns_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_columns_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_columns - process_cascade_events() - self.assertEqual(selected, ["value", "other_value"]) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -441,17 +420,14 @@ def test_table_editor_select_column_index(self): object_list.selected_index = 1 view = select_column_index_view - with reraise_exceptions(), \ - create_ui(object_list, dict(view=view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_column_index - process_cascade_events() - self.assertEqual(selected, 1) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -462,17 +438,14 @@ def test_table_editor_select_column_indices(self): object_list.selected_indices = [0, 1] view = select_column_indices_view - with reraise_exceptions(), \ - create_ui(object_list, dict(view=view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_column_indices - process_cascade_events() - self.assertEqual(selected, [0, 1]) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -482,17 +455,14 @@ def test_table_editor_select_cell(self): ) object_list.selected_cell = (object_list.values[5], "value") - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_cell_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_cell_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_cell - process_cascade_events() - self.assertEqual(selected, (object_list.values[5], "value")) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -520,10 +490,10 @@ def test_table_editor_select_row_index_with_tester(self): wrapper = tester.find_by_name(ui, "values") wrapper.locate(Cell(5, 0)).perform(MouseClick()) - #self.assertEqual(object_list.selected.value, str(5 ** 2)) + self.assertEqual(object_list.selected.value, str(5 ** 2)) wrapper.locate(Cell(6, 0)).perform(MouseClick()) - #self.assertEqual(object_list.selected.value, str(6 ** 2)) + self.assertEqual(object_list.selected.value, str(6 ** 2)) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_modify_cell_with_tester(self): @@ -608,17 +578,14 @@ def test_table_editor_select_cells(self): (object_list.values[8], "value"), ] - with reraise_exceptions(), \ - create_ui(object_list, dict(view=select_cells_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=select_cells_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected elif is_wx(): selected = editor.selected_cells - process_cascade_events() - self.assertEqual(selected, [ (object_list.values[5], "value"), (object_list.values[6], "other value"), @@ -633,17 +600,14 @@ def test_table_editor_select_cell_index(self): object_list.selected_cell_index = (5, 1) view = select_cell_index_view - with reraise_exceptions(), \ - create_ui(object_list, dict(view=view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_cell_index - process_cascade_events() - self.assertEqual(selected, (5, 1)) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) @@ -654,16 +618,14 @@ def test_table_editor_select_cell_indices(self): object_list.selected_cell_indices = [(5, 0), (6, 1), (8, 0)] view = select_cell_indices_view - with reraise_exceptions(), \ - create_ui(object_list, dict(view=view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() if is_qt(): selected = editor.selected_indices elif is_wx(): selected = editor.selected_cell_indices - process_cascade_events() self.assertEqual(selected, [(5, 0), (6, 1), (8, 0)]) @requires_toolkit([ToolkitName.qt]) @@ -686,10 +648,9 @@ def test_progress_column(self): object_list = ObjectList( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - - with reraise_exceptions(), \ - create_ui(object_list, dict(view=progress_view)): - process_cascade_events() + tester = UITester() + with tester.create_ui(object_list, dict(view=progress_view)) as ui: + pass @requires_toolkit([ToolkitName.qt]) def test_on_perform_action(self): @@ -701,10 +662,9 @@ def test_on_perform_action(self): mock_function = Mock() action = Action(on_perform=mock_function) - with reraise_exceptions(), \ - create_ui(object_list, dict(view=simple_view)) as ui: + tester = UITester() + with tester.create_ui(object_list, dict(view=simple_view)) as ui: editor = ui.get_editors("values")[0] - process_cascade_events() editor.set_menu_context(None, None, None) editor.perform(action) mock_function.assert_called_once() From 5079b8cef733b78fa36b280a1bc5f4e1ff199784 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 15:35:11 -0500 Subject: [PATCH 04/29] set all views to have sortable = false for consistency (should add a specific test for sorting) --- traitsui/tests/editors/test_table_editor.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index d84dbccaa..c3b111937 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -94,6 +94,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -110,6 +111,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ObjectColumn(name="value")], selection_mode="rows", selected="selections", @@ -123,6 +125,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -139,6 +142,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -155,6 +159,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -171,6 +176,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -187,6 +193,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -203,6 +210,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -219,6 +227,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -235,6 +244,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -251,6 +261,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), @@ -267,6 +278,7 @@ class ObjectList(HasTraits): "values", show_label=False, editor=TableEditor( + sortable=False, columns=[ ObjectColumn(name="value"), ObjectColumn(name="other_value"), From 450a53f915f30cf9357ea3e6a1626ca5cccdfb07 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 15:48:05 -0500 Subject: [PATCH 05/29] update test_table_editor_select_row to use UI Tester to select row --- traitsui/tests/editors/test_table_editor.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index c3b111937..ff7777b70 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -326,10 +326,12 @@ def test_table_editor_select_row(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - object_list.selected = object_list.values[5] - tester = UITester() + tester = UITester(delay=10000) with tester.create_ui(object_list, dict(view=select_row_view)) as ui: + # click the first cell in the 6th row to select the row + tester.find_by_name(ui, "values").locate(Cell(5,0)).perform(MouseClick()) + editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected @@ -337,6 +339,7 @@ def test_table_editor_select_row(self): selected = editor.selected_row self.assertIs(selected, object_list.values[5]) + self.assertIs(object_list.selected, selected) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_rows(self): From 2fffea68db0d044e96a2c10bc774342e87539c5a Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 14 Oct 2020 16:07:52 -0500 Subject: [PATCH 06/29] use UI Tester for all single selections --- traitsui/tests/editors/test_table_editor.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index ff7777b70..7d557008e 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -327,7 +327,7 @@ def test_table_editor_select_row(self): values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - tester = UITester(delay=10000) + tester = UITester() with tester.create_ui(object_list, dict(view=select_row_view)) as ui: # click the first cell in the 6th row to select the row tester.find_by_name(ui, "values").locate(Cell(5,0)).perform(MouseClick()) @@ -398,10 +398,12 @@ def test_table_editor_select_column(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - object_list.selected_column = "value" tester = UITester() with tester.create_ui(object_list, dict(view=select_column_view)) as ui: + # click a cell in the first column (the "value" column) + tester.find_by_name(ui, "values").locate(Cell(0,0)).perform(MouseClick()) + editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected @@ -409,6 +411,7 @@ def test_table_editor_select_column(self): selected = editor.selected_column self.assertEqual(selected, "value") + self.assertEqual(selected, object_list.selected_column) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_columns(self): @@ -432,11 +435,13 @@ def test_table_editor_select_column_index(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - object_list.selected_index = 1 view = select_column_index_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: + # click a cell in the index 1 column + tester.find_by_name(ui, "values").locate(Cell(0,1)).perform(MouseClick()) + editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected_indices @@ -444,6 +449,7 @@ def test_table_editor_select_column_index(self): selected = editor.selected_column_index self.assertEqual(selected, 1) + self.assertEqual(selected, object_list.selected_index) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_column_indices(self): @@ -468,10 +474,12 @@ def test_table_editor_select_cell(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - object_list.selected_cell = (object_list.values[5], "value") tester = UITester() with tester.create_ui(object_list, dict(view=select_cell_view)) as ui: + # click the cell at (5,0) + tester.find_by_name(ui, "values").locate(Cell(5,0)).perform(MouseClick()) + editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected @@ -479,6 +487,7 @@ def test_table_editor_select_cell(self): selected = editor.selected_cell self.assertEqual(selected, (object_list.values[5], "value")) + self.assertEqual(selected, object_list.selected_cell) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row_index_with_tester(self): @@ -612,11 +621,12 @@ def test_table_editor_select_cell_index(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - object_list.selected_cell_index = (5, 1) view = select_cell_index_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: + # click the cell at (5,1) + tester.find_by_name(ui, "values").locate(Cell(5,1)).perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected_indices @@ -624,6 +634,7 @@ def test_table_editor_select_cell_index(self): selected = editor.selected_cell_index self.assertEqual(selected, (5, 1)) + self.assertEqual(selected, object_list.selected_cell_index) @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cell_indices(self): From de1326f71f4be963e466f3bdd50ca4726c41e394 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 15 Oct 2020 16:03:07 -0500 Subject: [PATCH 07/29] first pass of a test for TableEditor_demo.py --- .../tests/test_TableEditor_demo.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py diff --git a/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py new file mode 100644 index 000000000..352cd3296 --- /dev/null +++ b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py @@ -0,0 +1,49 @@ +""" +This example demonstrates how to test interacting with a TableEditor. + +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 ( + Cell, KeyClick, KeySequence, MouseClick, UITester +) + +#: Filename of the demo script +FILENAME = "TableEditor_demo.py" + +#: Path of the demo script +DEMO_PATH = os.path.join(os.path.dirname(__file__), "..", FILENAME) + + +class TestTableEditorDemo(unittest.TestCase): + + def test_list_editor_demo(self): + demo = runpy.run_path(DEMO_PATH)["demo"] + + tester = UITester() + with tester.create_ui(demo) as ui: + employees_table = tester.find_by_name(ui, "employees") + + # clicking a cell enters edit mode and selcts full text + cell_21 = employees_table.locate(Cell(2,1)) + cell_21.perform(MouseClick()) + cell_21.perform(KeySequence("Jones")) + cell_21.perform(KeyClick("Enter")) + + self.assertEqual(demo.employees[0].last_name, 'Jones') + + # third column corresponds to Full Name property + cell_32 = employees_table.locate(Cell(3,2)) + cell_32.perform(MouseClick()) + + +# Run the test(s) +unittest.TextTestRunner().run( + unittest.TestLoader().loadTestsFromTestCase(TestTableEditorDemo) +) From 863b60f4df781733d0370d432a3983b5851ea469 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Tue, 29 Jun 2021 13:19:15 -0500 Subject: [PATCH 08/29] flake8 --- .../qt4/_traitsui/table_editor.py | 37 +++++++++++-------- .../wx/_interaction_helpers.py | 5 ++- .../wx/_traitsui/table_editor.py | 25 ++++--------- traitsui/testing/tester/locator.py | 2 +- traitsui/tests/editors/test_table_editor.py | 30 +++++++++------ 5 files changed, 53 insertions(+), 46 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py index 7f5730448..bb639d346 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -1,13 +1,12 @@ -# Copyright (c) 2005-2020, Enthought, Inc. -# All rights reserved. +# (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 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.table_editor import SimpleEditor @@ -24,8 +23,7 @@ BaseSourceWithLocation ) from traitsui.testing.tester._ui_tester_registry.qt4 import ( - _interaction_helpers, - _registry_helper + _interaction_helpers ) @@ -38,10 +36,17 @@ class _SimpleEditorWithCell(BaseSourceWithLocation): (KeyClick, lambda wrapper, interaction: wrapper._target._key_click( key=interaction.key, delay=wrapper.delay,)), - (KeySequence, lambda wrapper, interaction: wrapper._target._key_sequence( - sequence=interaction.sequence, - delay=wrapper.delay,)), - (DisplayedText, lambda wrapper, _: wrapper._target._get_displayed_text()), + ( + KeySequence, + lambda wrapper, interaction: wrapper._target._key_sequence( + sequence=interaction.sequence, + delay=wrapper.delay, + ) + ), + ( + DisplayedText, + lambda wrapper, _: wrapper._target._get_displayed_text() + ), (MouseDClick, lambda wrapper, _: wrapper._target._mouse_dclick( delay=wrapper.delay,)), ] @@ -51,7 +56,9 @@ def _get_model_view_index(self): return dict( model=table_view.model(), view=table_view, - index=table_view.model().index(self.location.row, self.location.column), + index=table_view.model().index( + self.location.row, self.location.column + ), ) def _mouse_click(self, delay=0): diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py index b49927151..f0818dcf6 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py @@ -216,7 +216,10 @@ def mouse_click_object(control, delay): @mouse_click def mouse_click_cell_in_grid(control, cell, delay): click_event = _create_grid_event( - wx.grid.wxEVT_GRID_CELL_LEFT_CLICK, control, row=cell.row, col=cell.column + wx.grid.wxEVT_GRID_CELL_LEFT_CLICK, + control, + row=cell.row, + col=cell.column ) control.ProcessWindowEvent(click_event) diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py index c872a9ce2..e4fa4049e 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py @@ -1,32 +1,23 @@ -# Copyright (c) 2005-2020, Enthought, Inc. -# All rights reserved. +# (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 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.wx.table_editor import SimpleEditor from traitsui.testing.api import ( Cell, - DisplayedText, MouseClick, - MouseDClick, - KeyClick, - KeySequence, - Selected, ) from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( BaseSourceWithLocation ) -from traitsui.testing.tester._ui_tester_registry.wx import ( - _interaction_helpers, - _registry_helper -) +from traitsui.testing.tester._ui_tester_registry.wx import _interaction_helpers class _SimpleEditorWithCell(BaseSourceWithLocation): diff --git a/traitsui/testing/tester/locator.py b/traitsui/testing/tester/locator.py index d25cd2298..89a36ce62 100644 --- a/traitsui/testing/tester/locator.py +++ b/traitsui/testing/tester/locator.py @@ -20,7 +20,7 @@ class Cell: """ A locator for locating a target uniquely specified by a row index and a column index. - + Attributes ---------- row : int diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 7d557008e..ca7c82d1e 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -29,7 +29,6 @@ KeySequence, KeyClick, MouseClick, - Selected, UITester, ) @@ -330,7 +329,8 @@ def test_table_editor_select_row(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_row_view)) as ui: # click the first cell in the 6th row to select the row - tester.find_by_name(ui, "values").locate(Cell(5,0)).perform(MouseClick()) + row6_cell = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + row6_cell.perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): @@ -366,7 +366,8 @@ def test_table_editor_select_row_index(self): object_list.selected_index = 5 tester = UITester() - with tester.create_ui(object_list, dict(view=select_row_index_view)) as ui: + with tester.create_ui(object_list, dict(view=select_row_index_view)) \ + as ui: editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected_indices @@ -400,9 +401,11 @@ def test_table_editor_select_column(self): ) tester = UITester() - with tester.create_ui(object_list, dict(view=select_column_view)) as ui: + with tester.create_ui(object_list, dict(view=select_column_view)) \ + as ui: # click a cell in the first column (the "value" column) - tester.find_by_name(ui, "values").locate(Cell(0,0)).perform(MouseClick()) + first_cell = tester.find_by_name(ui, "values").locate(Cell(0, 0)) + first_cell.perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): @@ -421,7 +424,8 @@ def test_table_editor_select_columns(self): object_list.selected_columns = ["value", "other_value"] tester = UITester() - with tester.create_ui(object_list, dict(view=select_columns_view)) as ui: + with tester.create_ui(object_list, dict(view=select_columns_view)) \ + as ui: editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected @@ -440,7 +444,8 @@ def test_table_editor_select_column_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: # click a cell in the index 1 column - tester.find_by_name(ui, "values").locate(Cell(0,1)).perform(MouseClick()) + col1_cell = tester.find_by_name(ui, "values").locate(Cell(0, 1)) + col1_cell.perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): @@ -478,7 +483,8 @@ def test_table_editor_select_cell(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_cell_view)) as ui: # click the cell at (5,0) - tester.find_by_name(ui, "values").locate(Cell(5,0)).perform(MouseClick()) + cell_5_0 = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + cell_5_0.perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): @@ -586,11 +592,10 @@ def test_table_editor_escape_retain_edit(self): cell.perform(MouseClick()) cell.perform(KeySequence("123")) - #cell.perform(KeyClick("Esc")) # exit edit mode, did not revert + # cell.perform(KeyClick("Esc")) # exit edit mode, did not revert self.assertEqual(object_list.values[0].other_value, 123) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cells(self): object_list = ObjectListWithSelection( @@ -626,7 +631,8 @@ def test_table_editor_select_cell_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: # click the cell at (5,1) - tester.find_by_name(ui, "values").locate(Cell(5,1)).perform(MouseClick()) + cell_5_1 = tester.find_by_name(ui, "values").locate(Cell(5, 1)) + cell_5_1.perform(MouseClick()) editor = ui.get_editors("values")[0] if is_qt(): selected = editor.selected_indices @@ -675,7 +681,7 @@ def test_progress_column(self): values=[ListItem(value=str(i ** 2)) for i in range(10)] ) tester = UITester() - with tester.create_ui(object_list, dict(view=progress_view)) as ui: + with tester.create_ui(object_list, dict(view=progress_view)): pass @requires_toolkit([ToolkitName.qt]) From d2866ccb9d9a904bee994e5c1655c96340d7ff6b Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Tue, 29 Jun 2021 15:33:59 -0500 Subject: [PATCH 09/29] update some comments --- .../tester/_ui_tester_registry/qt4/_interaction_helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py index 8e67f907e..345acb0e0 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_interaction_helpers.py @@ -185,7 +185,7 @@ def mouse_click_item_view(model, view, index, delay): Model from which QModelIndex will be obtained view : QAbstractItemView View from which the widget identified by the index will be - found and key sequence be performed. + found and mouse click be performed. index : QModelIndex Raises @@ -215,7 +215,7 @@ def mouse_dclick_item_view(model, view, index, delay): Model from which QModelIndex will be obtained view : QAbstractItemView View from which the widget identified by the index will be - found and key sequence be performed. + found and mouse double click be performed. index : QModelIndex Raises @@ -236,7 +236,7 @@ def mouse_dclick_item_view(model, view, index, delay): def key_sequence_item_view(model, view, index, sequence, delay=0): - """ Perform mouse click on the given QAbstractItemModel (model) and + """ Perform Key Sequence on the given QAbstractItemModel (model) and QAbstractItemView (view) with the given row and column. Parameters From 86e18ad38161097a12041ff91a5aa8aa50047955 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 08:46:07 -0500 Subject: [PATCH 10/29] remove start of wx support --- .../wx/_interaction_helpers.py | 33 ------------- .../wx/_traitsui/table_editor.py | 46 ------------------- .../wx/default_registry.py | 4 -- 3 files changed, 83 deletions(-) delete mode 100644 traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py index f0818dcf6..31924c160 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/_interaction_helpers.py @@ -40,28 +40,6 @@ def _create_event(event_type, control): return event -def _create_grid_event(event_type, control, *args, **kwargs): - """ Creates a wxGridEvent of a given type. - - Parameters - ---------- - event_type : wxEventType - The type of the event to be created - control : - The wx control the event is occurring on. - - Returns - ------- - wxGridEvent - The created event, of the given type, with the given control set as - the event object. - """ - event = wx.grid.GridEvent( - control.GetId(), event_type, control, *args, **kwargs - ) - return event - - def mouse_click(func): """ Decorator function for mouse clicks. Decorated functions will return if they are not enabled. Additionally, this handles the delay for the @@ -213,17 +191,6 @@ def mouse_click_object(control, delay): control.ProcessWindowEvent(click_event) -@mouse_click -def mouse_click_cell_in_grid(control, cell, delay): - click_event = _create_grid_event( - wx.grid.wxEVT_GRID_CELL_LEFT_CLICK, - control, - row=cell.row, - col=cell.column - ) - control.ProcessWindowEvent(click_event) - - def mouse_click_notebook_tab_index(control, index, delay): """ Performs a mouseclick on a Noteboook List Editor on the tab specified by index. diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py deleted file mode 100644 index e4fa4049e..000000000 --- a/traitsui/testing/tester/_ui_tester_registry/wx/_traitsui/table_editor.py +++ /dev/null @@ -1,46 +0,0 @@ -# (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! - -from traitsui.wx.table_editor import SimpleEditor - -from traitsui.testing.api import ( - Cell, - MouseClick, -) -from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( - BaseSourceWithLocation -) -from traitsui.testing.tester._ui_tester_registry.wx import _interaction_helpers - - -class _SimpleEditorWithCell(BaseSourceWithLocation): - source_class = SimpleEditor - locator_class = Cell - handlers = [ - (MouseClick, - (lambda wrapper, interaction: - _interaction_helpers.mouse_click_cell_in_grid( - control=wrapper._target.source.grid.control, - cell=wrapper._target.location, - delay=wrapper.delay))), - ] - - -def register(registry): - """ Register interactions for the given registry. - - If there are any conflicts, an error will occur. - - Parameters - ---------- - registry : TargetRegistry - The registry being registered to. - """ - _SimpleEditorWithCell.register(registry) diff --git a/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py b/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py index 29b8232e3..f89f65c6e 100644 --- a/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py +++ b/traitsui/testing/tester/_ui_tester_registry/wx/default_registry.py @@ -20,7 +20,6 @@ instance_editor, list_editor, range_editor, - table_editor, text_editor, ui_base, ) @@ -74,9 +73,6 @@ def get_default_registries(): # Editor Factory editor_factory.register(registry) - # TableEditor - table_editor.register(registry) - # More general registry follows more specific registry return [ registry, From e27351e9da6170f1bfeded4aee535fa4c2f2bee6 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 08:52:28 -0500 Subject: [PATCH 11/29] require qt on test_TableEditor_demo.py --- .../demo/Standard_Editors/tests/test_TableEditor_demo.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py index 352cd3296..5a63980f2 100644 --- a/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py +++ b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py @@ -13,6 +13,7 @@ from traitsui.testing.api import ( Cell, KeyClick, KeySequence, MouseClick, UITester ) +from traitsui.tests._tools import requires_toolkit, ToolkitName #: Filename of the demo script FILENAME = "TableEditor_demo.py" @@ -23,6 +24,7 @@ class TestTableEditorDemo(unittest.TestCase): + @requires_toolkit([ToolkitName.qt]) def test_list_editor_demo(self): demo = runpy.run_path(DEMO_PATH)["demo"] From cdb8743b375d04648f547bc054841f6c247ff796 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 09:07:37 -0500 Subject: [PATCH 12/29] TableEditor tests all require qt --- traitsui/tests/editors/test_table_editor.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index ca7c82d1e..e8538a118 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -290,6 +290,7 @@ class ObjectList(HasTraits): ) +@requires_toolkit([ToolkitName.qt]) class TestTableEditor(BaseTestMixin, unittest.TestCase): def setUp(self): @@ -298,7 +299,6 @@ def setUp(self): def tearDown(self): BaseTestMixin.tearDown(self) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -307,7 +307,6 @@ def test_table_editor(self): with tester.create_ui(object_list, dict(view=simple_view)): pass - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_filtered_table_editor(self): object_list = ObjectListWithSelection( values=[ListItem(other_value=i ** 2) for i in range(10)] @@ -320,7 +319,6 @@ def test_filtered_table_editor(self): self.assertIsNotNone(filter) self.assertEqual(num_filtered_indices, 7) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -341,7 +339,6 @@ def test_table_editor_select_row(self): self.assertIs(selected, object_list.values[5]) self.assertIs(object_list.selected, selected) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_rows(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -358,7 +355,6 @@ def test_table_editor_select_rows(self): self.assertEqual(selected, object_list.values[5:7]) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row_index(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -376,7 +372,6 @@ def test_table_editor_select_row_index(self): self.assertEqual(selected, 5) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row_indices(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -394,7 +389,6 @@ def test_table_editor_select_row_indices(self): self.assertEqual(selected, [5, 7, 8]) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_column(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -416,7 +410,6 @@ def test_table_editor_select_column(self): self.assertEqual(selected, "value") self.assertEqual(selected, object_list.selected_column) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_columns(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -434,7 +427,6 @@ def test_table_editor_select_columns(self): self.assertEqual(selected, ["value", "other_value"]) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_column_index(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -456,7 +448,6 @@ def test_table_editor_select_column_index(self): self.assertEqual(selected, 1) self.assertEqual(selected, object_list.selected_index) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_column_indices(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -474,7 +465,6 @@ def test_table_editor_select_column_indices(self): self.assertEqual(selected, [0, 1]) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cell(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -495,7 +485,6 @@ def test_table_editor_select_cell(self): self.assertEqual(selected, (object_list.values[5], "value")) self.assertEqual(selected, object_list.selected_cell) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_row_index_with_tester(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -525,7 +514,6 @@ def test_table_editor_select_row_index_with_tester(self): wrapper.locate(Cell(6, 0)).perform(MouseClick()) self.assertEqual(object_list.selected.value, str(6 ** 2)) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_modify_cell_with_tester(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -564,7 +552,6 @@ def test_table_editor_modify_cell_with_tester(self): wrapper.perform(KeySequence("12")) # now ok self.assertEqual(object_list.selected.other_value, 12) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_check_display_with_tester(self): object_list = ObjectListWithSelection( values=[ListItem(other_value=0)] @@ -581,7 +568,6 @@ def test_table_editor_check_display_with_tester(self): actual = wrapper.inspect(DisplayedText()) self.assertEqual(actual, "123") - @requires_toolkit([ToolkitName.qt]) def test_table_editor_escape_retain_edit(self): object_list = ObjectListWithSelection( values=[ListItem(other_value=0)] @@ -596,7 +582,6 @@ def test_table_editor_escape_retain_edit(self): self.assertEqual(object_list.values[0].other_value, 123) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cells(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -621,7 +606,6 @@ def test_table_editor_select_cells(self): (object_list.values[8], "value"), ]) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cell_index(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -642,7 +626,6 @@ def test_table_editor_select_cell_index(self): self.assertEqual(selected, (5, 1)) self.assertEqual(selected, object_list.selected_cell_index) - @requires_toolkit([ToolkitName.qt, ToolkitName.wx]) def test_table_editor_select_cell_indices(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] @@ -660,7 +643,6 @@ def test_table_editor_select_cell_indices(self): self.assertEqual(selected, [(5, 0), (6, 1), (8, 0)]) - @requires_toolkit([ToolkitName.qt]) def test_progress_column(self): from traitsui.extras.progress_column import ProgressColumn @@ -684,7 +666,6 @@ def test_progress_column(self): with tester.create_ui(object_list, dict(view=progress_view)): pass - @requires_toolkit([ToolkitName.qt]) def test_on_perform_action(self): # A test for issue #741, where actions with an on_perform function set # would get called twice From ef06becba88acc2c3ad5b3ce27710157bbb403ef Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 09:17:49 -0500 Subject: [PATCH 13/29] update a couple of tests to use Selected --- traitsui/tests/editors/test_table_editor.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index e8538a118..b7d9daf0e 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -29,6 +29,7 @@ KeySequence, KeyClick, MouseClick, + Selected, UITester, ) @@ -327,14 +328,10 @@ def test_table_editor_select_row(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_row_view)) as ui: # click the first cell in the 6th row to select the row - row6_cell = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + values_table = tester.find_by_name(ui, "values") + row6_cell = values_table.locate(Cell(5, 0)) row6_cell.perform(MouseClick()) - - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_row + selected = values_table.inspect(Selected()) self.assertIs(selected, object_list.values[5]) self.assertIs(object_list.selected, selected) @@ -347,11 +344,8 @@ def test_table_editor_select_rows(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_rows_view)) as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_rows + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(Selected()) self.assertEqual(selected, object_list.values[5:7]) From 69c0bbafe72739fa661847f60fefadfac4765364 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 09:29:26 -0500 Subject: [PATCH 14/29] use UITester to find editor and remove wx conditional block --- traitsui/tests/editors/test_table_editor.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index b7d9daf0e..1813f61f9 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -358,11 +358,8 @@ def test_table_editor_select_row_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_row_index_view)) \ as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_row_index + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected_indices self.assertEqual(selected, 5) From de736814ba63de1157858bb21b858448d230be9e Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 09:34:51 -0500 Subject: [PATCH 15/29] More cases of using UITester to get an editor, and removing wx conditional blocks --- traitsui/tests/editors/test_table_editor.py | 60 ++++++++------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 1813f61f9..438d09d5c 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -372,11 +372,8 @@ def test_table_editor_select_row_indices(self): view = select_row_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_row_indices + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected_indices self.assertEqual(selected, [5, 7, 8]) @@ -388,15 +385,13 @@ def test_table_editor_select_column(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_column_view)) \ as ui: + values_table = tester.find_by_name(ui, "values") # click a cell in the first column (the "value" column) - first_cell = tester.find_by_name(ui, "values").locate(Cell(0, 0)) + first_cell = values_table.locate(Cell(0, 0)) first_cell.perform(MouseClick()) - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_column + editor = values_table._target + selected = editor.selected self.assertEqual(selected, "value") self.assertEqual(selected, object_list.selected_column) @@ -410,11 +405,8 @@ def test_table_editor_select_columns(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_columns_view)) \ as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_columns + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected self.assertEqual(selected, ["value", "other_value"]) @@ -427,14 +419,12 @@ def test_table_editor_select_column_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: # click a cell in the index 1 column - col1_cell = tester.find_by_name(ui, "values").locate(Cell(0, 1)) + values_table = tester.find_by_name(ui, "values") + col1_cell = values_table.locate(Cell(0, 1)) col1_cell.perform(MouseClick()) - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_column_index + editor = values_table._target + selected = editor.selected_indices self.assertEqual(selected, 1) self.assertEqual(selected, object_list.selected_index) @@ -448,11 +438,8 @@ def test_table_editor_select_column_indices(self): view = select_column_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_column_indices + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected_indices self.assertEqual(selected, [0, 1]) @@ -464,14 +451,12 @@ def test_table_editor_select_cell(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_cell_view)) as ui: # click the cell at (5,0) - cell_5_0 = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + values_table = tester.find_by_name(ui, "values") + cell_5_0 = values_table.locate(Cell(5, 0)) cell_5_0.perform(MouseClick()) - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_cell + editor = values_table._target + selected = editor.selected self.assertEqual(selected, (object_list.values[5], "value")) self.assertEqual(selected, object_list.selected_cell) @@ -626,11 +611,8 @@ def test_table_editor_select_cell_indices(self): view = select_cell_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_cell_indices + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected_indices self.assertEqual(selected, [(5, 0), (6, 1), (8, 0)]) @@ -668,7 +650,7 @@ def test_on_perform_action(self): tester = UITester() with tester.create_ui(object_list, dict(view=simple_view)) as ui: - editor = ui.get_editors("values")[0] + editor = tester.find_by_name(ui, "values")._target editor.set_menu_context(None, None, None) editor.perform(action) mock_function.assert_called_once() From 7e93c8e00e2c82d31ce6318baf84162c65d98969 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 10:03:27 -0500 Subject: [PATCH 16/29] typo and style --- .../demo/Standard_Editors/tests/test_TableEditor_demo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py index 5a63980f2..c6b1e7e9d 100644 --- a/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py +++ b/traitsui/examples/demo/Standard_Editors/tests/test_TableEditor_demo.py @@ -32,8 +32,8 @@ def test_list_editor_demo(self): with tester.create_ui(demo) as ui: employees_table = tester.find_by_name(ui, "employees") - # clicking a cell enters edit mode and selcts full text - cell_21 = employees_table.locate(Cell(2,1)) + # clicking a cell enters edit mode and selects full text + cell_21 = employees_table.locate(Cell(2, 1)) cell_21.perform(MouseClick()) cell_21.perform(KeySequence("Jones")) cell_21.perform(KeyClick("Enter")) @@ -41,7 +41,7 @@ def test_list_editor_demo(self): self.assertEqual(demo.employees[0].last_name, 'Jones') # third column corresponds to Full Name property - cell_32 = employees_table.locate(Cell(3,2)) + cell_32 = employees_table.locate(Cell(3, 2)) cell_32.perform(MouseClick()) From 5d17dcfa9b51a1b5af9e77c6a4cb8feb3161fdde Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 10:05:19 -0500 Subject: [PATCH 17/29] uncomment esc line in test --- traitsui/tests/editors/test_table_editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 438d09d5c..18c717969 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -554,7 +554,7 @@ def test_table_editor_escape_retain_edit(self): cell.perform(MouseClick()) cell.perform(KeySequence("123")) - # cell.perform(KeyClick("Esc")) # exit edit mode, did not revert + cell.perform(KeyClick("Esc")) # exit edit mode, did not revert self.assertEqual(object_list.values[0].other_value, 123) From bd1d58e1b96c16c21aca0294b8063ddf7682a6d6 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 10:08:30 -0500 Subject: [PATCH 18/29] no longer need is_qt and is_wx, also couple more uses of UITester to find editor --- traitsui/tests/editors/test_table_editor.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 18c717969..e7906b236 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -18,8 +18,6 @@ ) from traitsui.tests._tools import ( BaseTestMixin, - is_qt, - is_wx, requires_toolkit, ToolkitName, ) @@ -570,11 +568,8 @@ def test_table_editor_select_cells(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_cells_view)) as ui: - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected - elif is_wx(): - selected = editor.selected_cells + editor = tester.find_by_name(ui, "values")._target + selected = editor.selected self.assertEqual(selected, [ (object_list.values[5], "value"), @@ -591,13 +586,11 @@ def test_table_editor_select_cell_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: # click the cell at (5,1) - cell_5_1 = tester.find_by_name(ui, "values").locate(Cell(5, 1)) + values_table = tester.find_by_name(ui, "values") + cell_5_1 = values_table.locate(Cell(5, 1)) cell_5_1.perform(MouseClick()) - editor = ui.get_editors("values")[0] - if is_qt(): - selected = editor.selected_indices - elif is_wx(): - selected = editor.selected_cell_index + editor = values_table._target + selected = editor.selected_indices self.assertEqual(selected, (5, 1)) self.assertEqual(selected, object_list.selected_cell_index) From 0aaf7a3d613387b1e4bb25244c4a7e6e8fb13f3c Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 10:20:48 -0500 Subject: [PATCH 19/29] remove redundant test --- traitsui/tests/editors/test_table_editor.py | 33 ++------------------- 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index e7906b236..5762ec7af 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -356,7 +356,9 @@ def test_table_editor_select_row_index(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_row_index_view)) \ as ui: - editor = tester.find_by_name(ui, "values")._target + values_table = tester.find_by_name(ui, "values") + values_table.locate(Cell(5, 0)).perform(MouseClick()) + editor = values_table._target selected = editor.selected_indices self.assertEqual(selected, 5) @@ -459,35 +461,6 @@ def test_table_editor_select_cell(self): self.assertEqual(selected, (object_list.values[5], "value")) self.assertEqual(selected, object_list.selected_cell) - def test_table_editor_select_row_index_with_tester(self): - object_list = ObjectListWithSelection( - values=[ListItem(value=str(i ** 2)) for i in range(10)] - ) - view = View( - Item( - "values", - show_label=False, - editor=TableEditor( - sortable=False, # switch off sorting by first column - columns=[ - ObjectColumn(name="value"), - ObjectColumn(name="other_value"), - ], - selection_mode="row", - selected="selected", - ), - ), - ) - tester = UITester() - with tester.create_ui(object_list, dict(view=view)) as ui: - wrapper = tester.find_by_name(ui, "values") - - wrapper.locate(Cell(5, 0)).perform(MouseClick()) - self.assertEqual(object_list.selected.value, str(5 ** 2)) - - wrapper.locate(Cell(6, 0)).perform(MouseClick()) - self.assertEqual(object_list.selected.value, str(6 ** 2)) - def test_table_editor_modify_cell_with_tester(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] From b25cfd65944e2368792f67130daaf1f3a64ea5a1 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 10:22:00 -0500 Subject: [PATCH 20/29] remove redundant view definition --- traitsui/tests/editors/test_table_editor.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 5762ec7af..3d42b3d6f 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -465,23 +465,8 @@ def test_table_editor_modify_cell_with_tester(self): object_list = ObjectListWithSelection( values=[ListItem(value=str(i ** 2)) for i in range(10)] ) - view = View( - Item( - "values", - show_label=False, - editor=TableEditor( - sortable=False, # switch off sorting by first column - columns=[ - ObjectColumn(name="value"), - ObjectColumn(name="other_value"), - ], - selection_mode="row", - selected="selected", - ), - ), - ) tester = UITester() - with tester.create_ui(object_list, dict(view=view)) as ui: + with tester.create_ui(object_list, dict(view=select_row_view)) as ui: wrapper = tester.find_by_name(ui, "values").locate(Cell(5, 0)) wrapper.perform(MouseClick()) # activate edit mode wrapper.perform(KeySequence("abc")) From f84212012e909e3b16e1c1f6172a5a34e82de222 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 11:15:02 -0500 Subject: [PATCH 21/29] add test using MouseDClick --- traitsui/tests/editors/test_table_editor.py | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 3d42b3d6f..49a15b4a6 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -23,10 +23,12 @@ ) from traitsui.testing.api import ( Cell, + Disabled, DisplayedText, KeySequence, KeyClick, MouseClick, + MouseDClick, Selected, UITester, ) @@ -288,6 +290,24 @@ class ObjectList(HasTraits): buttons=["OK"], ) +edit_on_first_click_false_view = View( + Item( + "values", + show_label=False, + editor=TableEditor( + sortable=False, + columns=[ + ObjectColumn(name="value"), + ObjectColumn(name="other_value"), + ], + selection_mode="row", + selected="selected", + edit_on_first_click=False + ), + ), + buttons=["OK"], +) + @requires_toolkit([ToolkitName.qt]) class TestTableEditor(BaseTestMixin, unittest.TestCase): @@ -605,3 +625,23 @@ def test_on_perform_action(self): editor.set_menu_context(None, None, None) editor.perform(action) mock_function.assert_called_once() + + def test_edit_on_first_click_false(self): + object_list = ObjectListWithSelection( + values=[ListItem(value=str(i ** 2)) for i in range(10)] + ) + tester = UITester() + with tester.create_ui( + object_list, + dict(view=edit_on_first_click_false_view) + ) as ui: + wrapper = tester.find_by_name(ui, "values").locate(Cell(5, 0)) + # single click will not activate edit mode + wrapper.perform(MouseClick()) + with self.assertRaises(Disabled): + wrapper.perform(KeySequence("abc")) + + # double click will activate edit mode + wrapper.perform(MouseDClick()) + wrapper.perform(KeySequence("abc")) + self.assertEqual(object_list.values[5].value, "abc") From 469174c660c3b2adfcf243d3d03e5eee71195047 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 30 Jun 2021 11:40:08 -0500 Subject: [PATCH 22/29] add SelectedIndices query class --- traitsui/testing/api.py | 4 +++ .../qt4/_traitsui/table_editor.py | 6 ++++ traitsui/testing/tester/query.py | 14 ++++++++ traitsui/tests/editors/test_table_editor.py | 36 +++++++++---------- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/traitsui/testing/api.py b/traitsui/testing/api.py index 85b0e358e..7ea360da1 100644 --- a/traitsui/testing/api.py +++ b/traitsui/testing/api.py @@ -29,6 +29,9 @@ - :class:`~.DisplayedText` - :class:`~.IsChecked` - :class:`~.IsEnabled` +- :class:`~.IsVisible` +- :class:`~.Selected` +- :class:`~.SelectedIndices` - :class:`~.SelectedText` Locations (for locating GUI elements) @@ -75,6 +78,7 @@ IsEnabled, IsVisible, Selected, + SelectedIndices, SelectedText ) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py index bb639d346..fbf035ea2 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -18,6 +18,7 @@ KeyClick, KeySequence, Selected, + SelectedIndices, ) from traitsui.testing.tester._ui_tester_registry._common_ui_targets import ( BaseSourceWithLocation @@ -109,3 +110,8 @@ def register(registry): interaction_class=Selected, handler=lambda wrapper, _: wrapper._target.selected ) + registry.register_interaction( + target_class=SimpleEditor, + interaction_class=SelectedIndices, + handler=lambda wrapper, _: wrapper._target.selected_indices + ) diff --git a/traitsui/testing/tester/query.py b/traitsui/testing/tester/query.py index 6af3dadb9..0f1be93d2 100644 --- a/traitsui/testing/tester/query.py +++ b/traitsui/testing/tester/query.py @@ -26,6 +26,20 @@ class Selected: pass +class SelectedIndices: + """ An object representing an interaction to obtain the indices of objects + which are currently selected. + + Implementations should return either a list of indicies of the selected + objects, a single index of a lone selected object, or -1 if nothing is + selected. + + Note that an index could be an integer, or it could be a tuple e.g. + corresponding to a specific cell at some (row, column) in a table. + """ + pass + + class SelectedText: """ An object representing an interaction to obtain the displayed (echoed) plain text which is currently selected. diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 49a15b4a6..05ca1d324 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -30,6 +30,7 @@ MouseClick, MouseDClick, Selected, + SelectedIndices, UITester, ) @@ -378,8 +379,7 @@ def test_table_editor_select_row_index(self): as ui: values_table = tester.find_by_name(ui, "values") values_table.locate(Cell(5, 0)).perform(MouseClick()) - editor = values_table._target - selected = editor.selected_indices + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, 5) @@ -392,8 +392,8 @@ def test_table_editor_select_row_indices(self): view = select_row_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = tester.find_by_name(ui, "values")._target - selected = editor.selected_indices + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, [5, 7, 8]) @@ -410,8 +410,7 @@ def test_table_editor_select_column(self): first_cell = values_table.locate(Cell(0, 0)) first_cell.perform(MouseClick()) - editor = values_table._target - selected = editor.selected + selected = values_table.inspect(Selected()) self.assertEqual(selected, "value") self.assertEqual(selected, object_list.selected_column) @@ -425,8 +424,8 @@ def test_table_editor_select_columns(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_columns_view)) \ as ui: - editor = tester.find_by_name(ui, "values")._target - selected = editor.selected + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(Selected()) self.assertEqual(selected, ["value", "other_value"]) @@ -443,8 +442,7 @@ def test_table_editor_select_column_index(self): col1_cell = values_table.locate(Cell(0, 1)) col1_cell.perform(MouseClick()) - editor = values_table._target - selected = editor.selected_indices + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, 1) self.assertEqual(selected, object_list.selected_index) @@ -458,8 +456,8 @@ def test_table_editor_select_column_indices(self): view = select_column_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = tester.find_by_name(ui, "values")._target - selected = editor.selected_indices + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, [0, 1]) @@ -475,8 +473,7 @@ def test_table_editor_select_cell(self): cell_5_0 = values_table.locate(Cell(5, 0)) cell_5_0.perform(MouseClick()) - editor = values_table._target - selected = editor.selected + selected = values_table.inspect(Selected()) self.assertEqual(selected, (object_list.values[5], "value")) self.assertEqual(selected, object_list.selected_cell) @@ -546,8 +543,8 @@ def test_table_editor_select_cells(self): tester = UITester() with tester.create_ui(object_list, dict(view=select_cells_view)) as ui: - editor = tester.find_by_name(ui, "values")._target - selected = editor.selected + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(Selected()) self.assertEqual(selected, [ (object_list.values[5], "value"), @@ -567,8 +564,7 @@ def test_table_editor_select_cell_index(self): values_table = tester.find_by_name(ui, "values") cell_5_1 = values_table.locate(Cell(5, 1)) cell_5_1.perform(MouseClick()) - editor = values_table._target - selected = editor.selected_indices + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, (5, 1)) self.assertEqual(selected, object_list.selected_cell_index) @@ -582,8 +578,8 @@ def test_table_editor_select_cell_indices(self): view = select_cell_indices_view tester = UITester() with tester.create_ui(object_list, dict(view=view)) as ui: - editor = tester.find_by_name(ui, "values")._target - selected = editor.selected_indices + values_table = tester.find_by_name(ui, "values") + selected = values_table.inspect(SelectedIndices()) self.assertEqual(selected, [(5, 0), (6, 1), (8, 0)]) From 9fdc5260d0ae963bcc6755059f0457aee278cb4c Mon Sep 17 00:00:00 2001 From: aaronayres35 <36972686+aaronayres35@users.noreply.github.com> Date: Wed, 7 Jul 2021 09:07:19 -0700 Subject: [PATCH 23/29] Docstring re-wording Co-authored-by: Poruri Sai Rahul --- traitsui/testing/tester/query.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/traitsui/testing/tester/query.py b/traitsui/testing/tester/query.py index 0f1be93d2..bdd03bf7f 100644 --- a/traitsui/testing/tester/query.py +++ b/traitsui/testing/tester/query.py @@ -17,8 +17,7 @@ class Selected: - """ An object representing an interaction to obtain the object which is - currently selected. + """ Represents an interaction to obtain the currently selected object. Implementations should return the selected object, or None if nothing is selected. @@ -27,8 +26,8 @@ class Selected: class SelectedIndices: - """ An object representing an interaction to obtain the indices of objects - which are currently selected. + """ Represents an interaction to obtain the indices of the currently + selected objects. Implementations should return either a list of indicies of the selected objects, a single index of a lone selected object, or -1 if nothing is From dc4f4a18e3485767ccd556509cdaca568f590c25 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 11:14:59 -0500 Subject: [PATCH 24/29] dont import from api internally --- .../_ui_tester_registry/qt4/_traitsui/table_editor.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py index fbf035ea2..b70d72cd4 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -10,13 +10,15 @@ from traitsui.qt4.table_editor import SimpleEditor -from traitsui.testing.api import ( - Cell, - DisplayedText, +from traitsui.testing.tester.command import ( MouseClick, MouseDClick, KeyClick, KeySequence, +) +from traitsui.testing.tester.locator import Cell +from traitsui.testing.tester.query import ( + DisplayedText, Selected, SelectedIndices, ) From d34f0c203b097e083336311566259b487ee0f7e7 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 11:16:12 -0500 Subject: [PATCH 25/29] Add Cell and MouseDClick to the api module docstring --- traitsui/testing/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/traitsui/testing/api.py b/traitsui/testing/api.py index 7ea360da1..190a5fd51 100644 --- a/traitsui/testing/api.py +++ b/traitsui/testing/api.py @@ -22,6 +22,7 @@ - :class:`~.KeyClick` - :class:`~.KeySequence` - :class:`~.MouseClick` +- :class:`~.MouseDClick` Interactions (for getting GUI states) ------------------------------------- @@ -37,6 +38,7 @@ Locations (for locating GUI elements) ------------------------------------- +- :class:`~.Cell` - :class:`~.Index` - :class:`~.Slider` - :class:`~.TargetById` From b83e6b2bba24cb5f38ac53e383cd73f9f20bac77 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 11:38:33 -0500 Subject: [PATCH 26/29] update SelectedIndices api --- .../qt4/_traitsui/table_editor.py | 12 +++++++++++- traitsui/testing/tester/query.py | 9 ++++----- traitsui/tests/editors/test_table_editor.py | 8 +++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py index b70d72cd4..c59f954af 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -30,6 +30,16 @@ ) +def _query_table_editor_selected_indices(wrapper, interaction): + selected_indices = wrapper._target.selected_indices + if not isinstance(selected_indices, list): + if selected_indices == -1: + return [] + else: + return [selected_indices] + else: + return selected_indices + class _SimpleEditorWithCell(BaseSourceWithLocation): source_class = SimpleEditor locator_class = Cell @@ -115,5 +125,5 @@ def register(registry): registry.register_interaction( target_class=SimpleEditor, interaction_class=SelectedIndices, - handler=lambda wrapper, _: wrapper._target.selected_indices + handler=_query_table_editor_selected_indices ) diff --git a/traitsui/testing/tester/query.py b/traitsui/testing/tester/query.py index bdd03bf7f..4c0fc9d19 100644 --- a/traitsui/testing/tester/query.py +++ b/traitsui/testing/tester/query.py @@ -19,8 +19,8 @@ class Selected: """ Represents an interaction to obtain the currently selected object. - Implementations should return the selected object, or None if nothing is - selected. + Implementations should return the selected object, or list of objects if + multiple are selected, or None if nothing is selected. """ pass @@ -29,9 +29,8 @@ class SelectedIndices: """ Represents an interaction to obtain the indices of the currently selected objects. - Implementations should return either a list of indicies of the selected - objects, a single index of a lone selected object, or -1 if nothing is - selected. + Implementations should return a list of indicies of the selected + objects or an empty list if nothing is selected. Note that an index could be an integer, or it could be a tuple e.g. corresponding to a specific cell at some (row, column) in a table. diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 05ca1d324..8d877dfb9 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -381,7 +381,7 @@ def test_table_editor_select_row_index(self): values_table.locate(Cell(5, 0)).perform(MouseClick()) selected = values_table.inspect(SelectedIndices()) - self.assertEqual(selected, 5) + self.assertEqual(selected, [5]) def test_table_editor_select_row_indices(self): object_list = ObjectListWithSelection( @@ -444,8 +444,7 @@ def test_table_editor_select_column_index(self): selected = values_table.inspect(SelectedIndices()) - self.assertEqual(selected, 1) - self.assertEqual(selected, object_list.selected_index) + self.assertEqual(selected, [1]) def test_table_editor_select_column_indices(self): object_list = ObjectListWithSelection( @@ -566,8 +565,7 @@ def test_table_editor_select_cell_index(self): cell_5_1.perform(MouseClick()) selected = values_table.inspect(SelectedIndices()) - self.assertEqual(selected, (5, 1)) - self.assertEqual(selected, object_list.selected_cell_index) + self.assertEqual(selected, [(5, 1)]) def test_table_editor_select_cell_indices(self): object_list = ObjectListWithSelection( From 5f07956f26f593d61beb25de1a65a8216ff1b429 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 12:27:31 -0500 Subject: [PATCH 27/29] add news fragment --- docs/releases/upcoming/1707.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/releases/upcoming/1707.feature.rst diff --git a/docs/releases/upcoming/1707.feature.rst b/docs/releases/upcoming/1707.feature.rst new file mode 100644 index 000000000..6fed922bc --- /dev/null +++ b/docs/releases/upcoming/1707.feature.rst @@ -0,0 +1 @@ +Add UITester support for qt TableEditor (#1707) \ No newline at end of file From 9b418ff46ef084290915e9bee9856b1cb30bdcd1 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 12:51:38 -0500 Subject: [PATCH 28/29] update Selected to also return list --- .../qt4/_traitsui/table_editor.py | 14 +++++++++++++- traitsui/tests/editors/test_table_editor.py | 14 ++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py index c59f954af..ab261142e 100644 --- a/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py +++ b/traitsui/testing/tester/_ui_tester_registry/qt4/_traitsui/table_editor.py @@ -30,6 +30,17 @@ ) +def _query_table_editor_selected(wrapper, interaction): + selected = wrapper._target.selected + if not isinstance(selected, list): + if selected is None: + return [] + else: + return [selected] + else: + return selected + + def _query_table_editor_selected_indices(wrapper, interaction): selected_indices = wrapper._target.selected_indices if not isinstance(selected_indices, list): @@ -40,6 +51,7 @@ def _query_table_editor_selected_indices(wrapper, interaction): else: return selected_indices + class _SimpleEditorWithCell(BaseSourceWithLocation): source_class = SimpleEditor locator_class = Cell @@ -120,7 +132,7 @@ def register(registry): registry.register_interaction( target_class=SimpleEditor, interaction_class=Selected, - handler=lambda wrapper, _: wrapper._target.selected + handler=_query_table_editor_selected ) registry.register_interaction( target_class=SimpleEditor, diff --git a/traitsui/tests/editors/test_table_editor.py b/traitsui/tests/editors/test_table_editor.py index 8d877dfb9..b5ead7dcd 100644 --- a/traitsui/tests/editors/test_table_editor.py +++ b/traitsui/tests/editors/test_table_editor.py @@ -352,8 +352,9 @@ def test_table_editor_select_row(self): row6_cell.perform(MouseClick()) selected = values_table.inspect(Selected()) - self.assertIs(selected, object_list.values[5]) - self.assertIs(object_list.selected, selected) + self.assertEqual(selected, [object_list.values[5]]) + self.assertIs(selected[0], object_list.values[5]) + self.assertIs(object_list.selected, selected[0]) def test_table_editor_select_rows(self): object_list = ObjectListWithSelection( @@ -412,8 +413,9 @@ def test_table_editor_select_column(self): selected = values_table.inspect(Selected()) - self.assertEqual(selected, "value") - self.assertEqual(selected, object_list.selected_column) + self.assertEqual(selected, ["value"]) + self.assertIs(selected[0], "value") + self.assertIs(selected[0], object_list.selected_column) def test_table_editor_select_columns(self): object_list = ObjectListWithSelection( @@ -474,8 +476,8 @@ def test_table_editor_select_cell(self): selected = values_table.inspect(Selected()) - self.assertEqual(selected, (object_list.values[5], "value")) - self.assertEqual(selected, object_list.selected_cell) + self.assertEqual(selected, [(object_list.values[5], "value")]) + self.assertIs(selected[0], object_list.selected_cell) def test_table_editor_modify_cell_with_tester(self): object_list = ObjectListWithSelection( From 036dc51b7f1ad322123d4c6b22bbc92d36986add Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 7 Jul 2021 12:51:56 -0500 Subject: [PATCH 29/29] upadte query object docstrings --- traitsui/testing/tester/query.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/traitsui/testing/tester/query.py b/traitsui/testing/tester/query.py index 4c0fc9d19..b6062ddd5 100644 --- a/traitsui/testing/tester/query.py +++ b/traitsui/testing/tester/query.py @@ -17,10 +17,10 @@ class Selected: - """ Represents an interaction to obtain the currently selected object. + """ Represents an interaction to obtain the currently selected object(s). - Implementations should return the selected object, or list of objects if - multiple are selected, or None if nothing is selected. + Implementations should return a list of selected objects, or an empty list + if nothing is selected. """ pass @@ -32,8 +32,10 @@ class SelectedIndices: Implementations should return a list of indicies of the selected objects or an empty list if nothing is selected. - Note that an index could be an integer, or it could be a tuple e.g. - corresponding to a specific cell at some (row, column) in a table. + Note that an index could be an integer (e.g. when selecting from a list or + enumerataion, or selecting entire rows or columns of a table), or it could + be a tuple (e.g. corresponding to a specific cell at some (row, column) in + a table). """ pass