Skip to content

Use selenium select class #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 5, 2012
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 140 additions & 60 deletions src/Selenium2Library/keywords/_selectelement.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import Select
from keywordgroup import KeywordGroup

Expand All @@ -19,16 +18,12 @@ def get_list_items(self, locator):
def get_selected_list_label(self, locator):
"""Returns the visible label of the selected element from the select list identified by `locator`.

Fails if there are zero or more than one selection.

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
labels = self.get_selected_list_labels(locator)
if len(labels) != 1:
raise ValueError("Select list with locator '%s' does not have a single selected value")
return labels[0]
select = self._get_select_list(locator)
return select.first_selected_option.get_attribute('label')

def get_selected_list_labels(self, locator):
"""Returns the visible labels of selected elements (as a list) from the select list identified by `locator`.
Expand All @@ -48,16 +43,13 @@ def get_selected_list_value(self, locator):
"""Returns the value of the selected element from the select list identified by `locator`.

Return value is read from `value` attribute of the selected element.
Fails if there are zero or more than one selection.

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
values = self.get_selected_list_values(locator)
if len(values) != 1:
raise ValueError("Select list with locator '%s' does not have a single selected value")
return values[0]
select = self._get_select_list(locator)
return select.first_selected_option.get_attribute('value')

def get_selected_list_values(self, locator):
"""Returns the values of selected elements (as a list) from the select list identified by `locator`.
Expand Down Expand Up @@ -146,12 +138,11 @@ def select_all_from_list(self, locator):
self._info("Selecting all options from list '%s'." % locator)

select = self._get_select_list(locator)
if not self._is_multiselect_list(select):
if not select.is_multiple:
raise RuntimeError("Keyword 'Select all from list' works only for multiselect lists.")

select, options = self._get_select_list_options(select)
for i in range(len(options)):
self._select_option_from_multi_select_list(select, options, i)
for i in range(len(select.options)):
select.select_by_index(i)

def select_from_list(self, locator, *items):
"""Selects `*items` from list identified by `locator`
Expand All @@ -160,92 +151,190 @@ def select_from_list(self, locator, *items):
value will be selected. If the target list is a multi-selection list,
and `*items` is an empty list, all values of the list will be selected.

*items try to select by value then by label.

It's faster to use 'by index/value/label' functions.

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
items_str = items and "option(s) '%s'" % ", ".join(items) or "all options"
self._info("Selecting %s from list '%s'." % (items_str, locator))
items = list(items)

select, options = self._get_select_list_options(locator)
is_multi_select = self._is_multiselect_list(select)
select_func = self._select_option_from_multi_select_list if is_multi_select else self._select_option_from_single_select_list
select = self._get_select_list(locator)

if not items:
for i in range(len(options)):
select_func(select, options, i)
for i in range(len(select.options)):
select.select_by_index(i)
return

option_values = self._get_values_for_options(options)
option_labels = self._get_labels_for_options(options)
for item in items:
option_index = None
try: option_index = option_values.index(item)
try: select.select_by_value(item)
except:
try: option_index = option_labels.index(item)
try: select.select_by_visible_text(item)
except: continue
select_func(select, options, option_index)

def select_from_list_by_index(self, locator, *indexes):
"""Selects `*indexes` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not indexes:
raise ValueError("No index given.")
items_str = "index(es) '%s'" % ", ".join(indexes)
self._info("Selecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
for index in indexes:
select.select_by_index(int(index))

def select_from_list_by_value(self, locator, *values):
"""Selects `*values` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not values:
raise ValueError("No value given.")
items_str = "value(s) '%s'" % ", ".join(values)
self._info("Selecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
for value in values:
select.select_by_value(value)

def select_from_list_by_label(self, locator, *labels):
"""Selects `*labels` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not labels:
raise ValueError("No value given.")
items_str = "label(s) '%s'" % ", ".join(labels)
self._info("Selecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
for label in labels:
select.select_by_visible_text(label)

def unselect_from_list(self, locator, *items):
"""Unselects given values from select list identified by locator.

As a special case, giving empty list as `*items` will remove all
selections.

*items try to unselect by value AND by label.

It's faster to use 'by index/value/label' functions.

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
items_str = items and "option(s) '%s'" % ", ".join(items) or "all options"
self._info("Unselecting %s from list '%s'." % (items_str, locator))
items = list(items)

select = self._get_select_list(locator)
if not self._is_multiselect_list(select):
if not select.is_multiple:
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")

if not items:
self._unselect_all_options_from_multi_select_list(select)
select.deselect_all()
return

select, options = self._get_select_list_options(select)
option_values = self._get_values_for_options(options)
option_labels = self._get_labels_for_options(options)
for item in items:
option_index = None
try: option_index = option_values.index(item)
except:
try: option_index = option_labels.index(item)
except: continue
self._unselect_option_from_multi_select_list(select, options, option_index)
select.deselect_by_value(item)
select.deselect_by_visible_text(item)

def unselect_from_list_by_index(self, locator, *indexes):
"""Unselects `*indexes` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not indexes:
raise ValueError("No index given.")

items_str = "index(es) '%s'" % ", ".join(indexes)
self._info("Unselecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
if not select.is_multiple:
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")

for index in indexes:
select.deselect_by_index(int(index))

def unselect_from_list_by_value(self, locator, *values):
"""Unselects `*values` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not values:
raise ValueError("No value given.")
items_str = "value(s) '%s'" % ", ".join(values)
self._info("Unselecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
if not select.is_multiple:
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")

for value in values:
select.deselect_by_value(value)

def unselect_from_list_by_label(self, locator, *labels):
"""Unselects `*labels` from list identified by `locator`

Select list keywords work on both lists and combo boxes. Key attributes for
select lists are `id` and `name`. See `introduction` for details about
locating elements.
"""
if not labels:
raise ValueError("No value given.")
items_str = "label(s) '%s'" % ", ".join(labels)
self._info("Unselecting %s from list '%s'." % (items_str, locator))

select = self._get_select_list(locator)
if not select.is_multiple:
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")

for label in labels:
select.deselect_by_visible_text(label)

# Private

def _get_labels_for_options(self, options):
labels = []
for option in options:
labels.append(option.text)
return labels

def _get_select_list(self, locator):
return self._element_find(locator, True, True, 'select')
el = self._element_find(locator, True, True, 'select')
return Select(el)

def _get_select_list_options(self, select_list_or_locator):
if isinstance(select_list_or_locator, WebElement):
if isinstance(select_list_or_locator, Select):
select = select_list_or_locator
else:
select = self._get_select_list(select_list_or_locator)
return select, select.find_elements_by_tag_name('option')
return select, select.options

def _get_select_list_options_selected(self, locator):
select = self._get_select_list(locator)
# TODO: Handle possible exception thrown by all_selected_options
return select, select.all_selected_options

def _get_select_list_options_selected(self, select_list_or_locator):
select, options = self._get_select_list_options(select_list_or_locator)
selected = []
for option in options:
if option.is_selected():
selected.append(option)
return select, selected

def _get_values_for_options(self, options):
values = []
for option in options:
Expand All @@ -258,15 +347,6 @@ def _is_multiselect_list(self, select):
return True
return False

def _select_option_from_multi_select_list(self, select, options, index):
if not options[index].is_selected():
options[index].click()

def _select_option_from_single_select_list(self, select, options, index):
sel = Select(select)
sel.select_by_index(index)


def _unselect_all_options_from_multi_select_list(self, select):
self._current_browser().execute_script("arguments[0].selectedIndex = -1;", select)

Expand Down