Skip to content

Commit

Permalink
Fix combo box methods .select(), .item_count(), .selected_index() and…
Browse files Browse the repository at this point in the history
… .selected_text() for WinForms and Qt5, add unit tests.
  • Loading branch information
vasily-v-ryabov committed Feb 9, 2019
1 parent 3e7c1bc commit 7f5865f
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 13 deletions.
44 changes: 41 additions & 3 deletions pywinauto/controls/uia_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ def get_expand_state(self):
# workaround for WinForms combo box
children_list = self.children(control_type="List")
if children_list and children_list[0].is_visible():
if self.element_info.framework_id == 'Qt':
# TODO: find the way to get expand_collapse_state
return uia_defs.expand_state_collapsed
return uia_defs.expand_state_expanded
else:
return uia_defs.expand_state_collapsed
Expand Down Expand Up @@ -230,11 +233,29 @@ def select(self, item):
self.expand()
try:
self._select(item)
except IndexError:
except (IndexError, NoPatternInterfaceError):
# Try to access the underlying ListBox explicitly
children_lst = self.children(control_type='List')
if len(children_lst) > 0:
children_lst[0]._select(item)
# do health check and apply workaround for Qt5 combo box if necessary
if isinstance(item, six.string_types):
item = children_lst[0].children(title=item)[0]
if self.selected_text() != item:
# workaround for WinForms combo box
item.invoke()
if self.selected_text() != item:
# workaround for Qt5 combo box
item.click_input()
if self.selected_text() != item:
item.click_input()
elif self.selected_index() != item:
items = children_lst[0].children(control_type='ListItem')
if item < len(items):
items[item].invoke()
else:
raise IndexError('Item number #{} is out of range ' \
'({} items in total)'.format(item, len(items)))
else:
raise IndexError("item '{0}' not found or can't be accessed".format(item))
finally:
Expand Down Expand Up @@ -265,7 +286,11 @@ def selected_text(self):
# TODO: add selected_indices for a combobox with multi-select support
def selected_index(self):
"""Return the selected index"""
return self.selected_item_index()
try:
return self.selected_item_index()
except NoPatternInterfaceError as exc:
# workaround for Qt5 and WinForms
return self.texts().index(self.selected_text())

# -----------------------------------------------------------
def item_count(self):
Expand All @@ -275,7 +300,20 @@ def item_count(self):
The interface is kept mostly for a backward compatibility with
the native ComboBox interface
"""
return self.control_count()
children_list = self.children(control_type="List")
if children_list:
return children_list[0].control_count()
else:
self.expand()
try:
children_list = self.children(control_type="List")
if children_list:
return children_list[0].control_count()
else:
return self.control_count()
finally:
self.collapse()
return self.control_count()


# ====================================================================
Expand Down
55 changes: 45 additions & 10 deletions pywinauto/unittests/test_uiawrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1156,17 +1156,14 @@ def setUp(self):
_set_timings()

# start the application
app = Application(backend='uia')
app = app.start(winfoms_app_grid)
dlg = app.Dialog
self.app = Application(backend='uia').start(winfoms_app_grid)
self.dlg = self.app.Dialog

self.app = app
self.dlg = dlg
self.add_col_button = dlg.AddCol
self.add_row_button = dlg.AddRow
self.row_header_button = dlg.RowHeader
self.col_header_button = dlg.ColHeader
self.list_box = dlg.ListBox
self.add_col_button = self.dlg.AddCol
self.add_row_button = self.dlg.AddRow
self.row_header_button = self.dlg.RowHeader
self.col_header_button = self.dlg.ColHeader
self.list_box = self.dlg.ListBox

def test_list_box_item_selection(self):
"""Test get_item method"""
Expand Down Expand Up @@ -1317,6 +1314,44 @@ def test_texts(self):
self.assertTrue(combo.is_expanded())
combo.collapse()

def test_select(self):
"""Test method .select() for WinForms combo box"""
self.dlg.set_focus()
self.combo_editable.select(u'Letters')
self.assertEqual(self.combo_editable.selected_text(), u'Letters')
self.assertEqual(self.combo_editable.selected_index(), 1)
self.combo_editable.select(2)
self.assertEqual(self.combo_editable.selected_text(), u'Special symbols')
self.assertEqual(self.combo_editable.selected_index(), 2)

self.combo_fixed.select(u'Last Item')
self.assertEqual(self.combo_fixed.selected_text(), u'Last Item')
self.assertEqual(self.combo_fixed.selected_index(), 2)
self.combo_fixed.select(1)
self.assertEqual(self.combo_fixed.selected_text(), u'Item 2')
self.assertEqual(self.combo_fixed.selected_index(), 1)

self.combo_simple.select(u'The Simplest')
self.assertEqual(self.combo_simple.selected_text(), u'The Simplest')
self.assertEqual(self.combo_simple.selected_index(), 2)
self.combo_simple.select(0)
self.assertEqual(self.combo_simple.selected_text(), u'Simple 1')
self.assertEqual(self.combo_simple.selected_index(), 0)

def test_select_errors(self):
"""Test errors in method .select() for WinForms combo box"""
self.dlg.set_focus()
for combo in [self.combo_editable, self.combo_fixed, self.combo_simple]:
self.assertRaises(IndexError, combo.select, u'FFFF')
self.assertRaises(IndexError, combo.select, 50)

def test_item_count(self):
"""Test method .item_count() for WinForms combo box"""
self.dlg.set_focus()
self.assertEqual(self.combo_editable.item_count(), 3)
self.assertEqual(self.combo_fixed.item_count(), 3)
self.assertEqual(self.combo_simple.item_count(), 3)


class ListItemWrapperTests(unittest.TestCase):

Expand Down

0 comments on commit 7f5865f

Please sign in to comment.