1- from selenium.webdriver.remote.webelement import WebElement
21from selenium.webdriver.support.ui import Select
32from 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