Skip to content

Commit 33040d0

Browse files
committed
Merge pull request robotframework#68 from emanlove/use-selenium-select-class
Use selenium select class
2 parents 074e86e + 1c6fa4d commit 33040d0

File tree

1 file changed

+140
-60
lines changed

1 file changed

+140
-60
lines changed

src/Selenium2Library/keywords/_selectelement.py

Lines changed: 140 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from selenium.webdriver.remote.webelement import WebElement
21
from selenium.webdriver.support.ui import Select
32
from keywordgroup import KeywordGroup
43

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

22-
Fails if there are zero or more than one selection.
23-
2421
Select list keywords work on both lists and combo boxes. Key attributes for
2522
select lists are `id` and `name`. See `introduction` for details about
2623
locating elements.
2724
"""
28-
labels = self.get_selected_list_labels(locator)
29-
if len(labels) != 1:
30-
raise ValueError("Select list with locator '%s' does not have a single selected value")
31-
return labels[0]
25+
select = self._get_select_list(locator)
26+
return select.first_selected_option.get_attribute('label')
3227

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

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

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

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

148140
select = self._get_select_list(locator)
149-
if not self._is_multiselect_list(select):
141+
if not select.is_multiple:
150142
raise RuntimeError("Keyword 'Select all from list' works only for multiselect lists.")
151143

152-
select, options = self._get_select_list_options(select)
153-
for i in range(len(options)):
154-
self._select_option_from_multi_select_list(select, options, i)
144+
for i in range(len(select.options)):
145+
select.select_by_index(i)
155146

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

154+
*items try to select by value then by label.
155+
156+
It's faster to use 'by index/value/label' functions.
157+
163158
Select list keywords work on both lists and combo boxes. Key attributes for
164159
select lists are `id` and `name`. See `introduction` for details about
165160
locating elements.
166161
"""
167162
items_str = items and "option(s) '%s'" % ", ".join(items) or "all options"
168163
self._info("Selecting %s from list '%s'." % (items_str, locator))
169-
items = list(items)
170164

171-
select, options = self._get_select_list_options(locator)
172-
is_multi_select = self._is_multiselect_list(select)
173-
select_func = self._select_option_from_multi_select_list if is_multi_select else self._select_option_from_single_select_list
165+
select = self._get_select_list(locator)
174166

175167
if not items:
176-
for i in range(len(options)):
177-
select_func(select, options, i)
168+
for i in range(len(select.options)):
169+
select.select_by_index(i)
178170
return
179171

180-
option_values = self._get_values_for_options(options)
181-
option_labels = self._get_labels_for_options(options)
182172
for item in items:
183-
option_index = None
184-
try: option_index = option_values.index(item)
173+
try: select.select_by_value(item)
185174
except:
186-
try: option_index = option_labels.index(item)
175+
try: select.select_by_visible_text(item)
187176
except: continue
188-
select_func(select, options, option_index)
177+
178+
def select_from_list_by_index(self, locator, *indexes):
179+
"""Selects `*indexes` from list identified by `locator`
180+
181+
Select list keywords work on both lists and combo boxes. Key attributes for
182+
select lists are `id` and `name`. See `introduction` for details about
183+
locating elements.
184+
"""
185+
if not indexes:
186+
raise ValueError("No index given.")
187+
items_str = "index(es) '%s'" % ", ".join(indexes)
188+
self._info("Selecting %s from list '%s'." % (items_str, locator))
189+
190+
select = self._get_select_list(locator)
191+
for index in indexes:
192+
select.select_by_index(int(index))
193+
194+
def select_from_list_by_value(self, locator, *values):
195+
"""Selects `*values` from list identified by `locator`
196+
197+
Select list keywords work on both lists and combo boxes. Key attributes for
198+
select lists are `id` and `name`. See `introduction` for details about
199+
locating elements.
200+
"""
201+
if not values:
202+
raise ValueError("No value given.")
203+
items_str = "value(s) '%s'" % ", ".join(values)
204+
self._info("Selecting %s from list '%s'." % (items_str, locator))
205+
206+
select = self._get_select_list(locator)
207+
for value in values:
208+
select.select_by_value(value)
209+
210+
def select_from_list_by_label(self, locator, *labels):
211+
"""Selects `*labels` from list identified by `locator`
212+
213+
Select list keywords work on both lists and combo boxes. Key attributes for
214+
select lists are `id` and `name`. See `introduction` for details about
215+
locating elements.
216+
"""
217+
if not labels:
218+
raise ValueError("No value given.")
219+
items_str = "label(s) '%s'" % ", ".join(labels)
220+
self._info("Selecting %s from list '%s'." % (items_str, locator))
221+
222+
select = self._get_select_list(locator)
223+
for label in labels:
224+
select.select_by_visible_text(label)
189225

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

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

232+
*items try to unselect by value AND by label.
233+
234+
It's faster to use 'by index/value/label' functions.
235+
196236
Select list keywords work on both lists and combo boxes. Key attributes for
197237
select lists are `id` and `name`. See `introduction` for details about
198238
locating elements.
199239
"""
200240
items_str = items and "option(s) '%s'" % ", ".join(items) or "all options"
201241
self._info("Unselecting %s from list '%s'." % (items_str, locator))
202-
items = list(items)
203242

204243
select = self._get_select_list(locator)
205-
if not self._is_multiselect_list(select):
244+
if not select.is_multiple:
206245
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")
207246

208247
if not items:
209-
self._unselect_all_options_from_multi_select_list(select)
248+
select.deselect_all()
210249
return
211250

212251
select, options = self._get_select_list_options(select)
213-
option_values = self._get_values_for_options(options)
214-
option_labels = self._get_labels_for_options(options)
215252
for item in items:
216-
option_index = None
217-
try: option_index = option_values.index(item)
218-
except:
219-
try: option_index = option_labels.index(item)
220-
except: continue
221-
self._unselect_option_from_multi_select_list(select, options, option_index)
253+
select.deselect_by_value(item)
254+
select.deselect_by_visible_text(item)
255+
256+
def unselect_from_list_by_index(self, locator, *indexes):
257+
"""Unselects `*indexes` from list identified by `locator`
258+
259+
Select list keywords work on both lists and combo boxes. Key attributes for
260+
select lists are `id` and `name`. See `introduction` for details about
261+
locating elements.
262+
"""
263+
if not indexes:
264+
raise ValueError("No index given.")
265+
266+
items_str = "index(es) '%s'" % ", ".join(indexes)
267+
self._info("Unselecting %s from list '%s'." % (items_str, locator))
268+
269+
select = self._get_select_list(locator)
270+
if not select.is_multiple:
271+
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")
272+
273+
for index in indexes:
274+
select.deselect_by_index(int(index))
275+
276+
def unselect_from_list_by_value(self, locator, *values):
277+
"""Unselects `*values` from list identified by `locator`
278+
279+
Select list keywords work on both lists and combo boxes. Key attributes for
280+
select lists are `id` and `name`. See `introduction` for details about
281+
locating elements.
282+
"""
283+
if not values:
284+
raise ValueError("No value given.")
285+
items_str = "value(s) '%s'" % ", ".join(values)
286+
self._info("Unselecting %s from list '%s'." % (items_str, locator))
287+
288+
select = self._get_select_list(locator)
289+
if not select.is_multiple:
290+
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")
291+
292+
for value in values:
293+
select.deselect_by_value(value)
294+
295+
def unselect_from_list_by_label(self, locator, *labels):
296+
"""Unselects `*labels` from list identified by `locator`
297+
298+
Select list keywords work on both lists and combo boxes. Key attributes for
299+
select lists are `id` and `name`. See `introduction` for details about
300+
locating elements.
301+
"""
302+
if not labels:
303+
raise ValueError("No value given.")
304+
items_str = "label(s) '%s'" % ", ".join(labels)
305+
self._info("Unselecting %s from list '%s'." % (items_str, locator))
306+
307+
select = self._get_select_list(locator)
308+
if not select.is_multiple:
309+
raise RuntimeError("Keyword 'Unselect from list' works only for multiselect lists.")
310+
311+
for label in labels:
312+
select.deselect_by_visible_text(label)
222313

223314
# Private
224-
315+
225316
def _get_labels_for_options(self, options):
226317
labels = []
227318
for option in options:
228319
labels.append(option.text)
229320
return labels
230321

231322
def _get_select_list(self, locator):
232-
return self._element_find(locator, True, True, 'select')
323+
el = self._element_find(locator, True, True, 'select')
324+
return Select(el)
233325

234326
def _get_select_list_options(self, select_list_or_locator):
235-
if isinstance(select_list_or_locator, WebElement):
327+
if isinstance(select_list_or_locator, Select):
236328
select = select_list_or_locator
237329
else:
238330
select = self._get_select_list(select_list_or_locator)
239-
return select, select.find_elements_by_tag_name('option')
331+
return select, select.options
332+
333+
def _get_select_list_options_selected(self, locator):
334+
select = self._get_select_list(locator)
335+
# TODO: Handle possible exception thrown by all_selected_options
336+
return select, select.all_selected_options
240337

241-
def _get_select_list_options_selected(self, select_list_or_locator):
242-
select, options = self._get_select_list_options(select_list_or_locator)
243-
selected = []
244-
for option in options:
245-
if option.is_selected():
246-
selected.append(option)
247-
return select, selected
248-
249338
def _get_values_for_options(self, options):
250339
values = []
251340
for option in options:
@@ -258,15 +347,6 @@ def _is_multiselect_list(self, select):
258347
return True
259348
return False
260349

261-
def _select_option_from_multi_select_list(self, select, options, index):
262-
if not options[index].is_selected():
263-
options[index].click()
264-
265-
def _select_option_from_single_select_list(self, select, options, index):
266-
sel = Select(select)
267-
sel.select_by_index(index)
268-
269-
270350
def _unselect_all_options_from_multi_select_list(self, select):
271351
self._current_browser().execute_script("arguments[0].selectedIndex = -1;", select)
272352

0 commit comments

Comments
 (0)