adbSOeh
adbSOeh

Reputation: 79

Loop through span items in selenium python

I'm trying to click on each item in a span using Selenium. Is it possible to specify this in a for loop and how could I do this?

This is how I currently click on the first span item:

 _open_actieve_polis = {"by": By.CSS_SELECTOR, "value": "td:nth-child(2)"}

self._click(self._open_actieve_polis)

in the base page this is how i implemented the _click method.

def _find(self, locator):
    return self.driver.find_element(locator["by"], locator["value"])

 def _click(self, locator):
        self._find(locator).click()

these are the other span items I want to click:

tbody > tr:nth-child(2) > td:nth-child(2) > span > a
tbody > tr:nth-child(3) > td:nth-child(2) > span > a
tbody > tr:nth-child(4) > td:nth-child(2) > span > a
tbody > tr:nth-child(5) > td:nth-child(2) > span > a
tbody > tr:nth-child(6) > td:nth-child(2) > span > a

This is what I tried after applying feedback:

This in a method:

for link in self._open_actieve_polis:
        self._click_all(link)
        self.driver.back()

I declared the locator in an attribute:

_open_actieve_polis = ({"by": By.CSS_SELECTOR, "value": "td:nth-child(2)"})

the following in base page:

 def _find_all(self, locator):
        return self.driver.find_elements(locator["by"], locator["value"])

    def _click_all(self, locator):
        self._find_all(locator).click()

is currently resulting in:

     line 18, in _find_all
    return self.driver.find_elements(locator["by"], locator["value"])
TypeError: string indices must be integers

Upvotes: 0

Views: 1188

Answers (2)

Ian Lesperance
Ian Lesperance

Reputation: 5139

Selenium's find_elements() method (as well as its find_elements_by_*() methods, all return a simple list of elements. Lists don't have a click() method.

Instead, you'll need to iterate over the elements, clicking each one in turn.

elements = driver.find_elements(By.CSS, "...")
for element in elements:
    element.click()

Note: Selenium has a find_elements_by_css_selector() method that you can use instead of find_elements():

elements = driver.find_elements_by_css_selector("...")

Upvotes: 0

Andersson
Andersson

Reputation: 52665

You need to implement another method. Something like

def _find_all(self, locator):
    return self.driver.find_elements(locator["by"], locator["value"])

that intend to return you list of elements instead of single element...

With this method you can try to get list of links

self.links = self._find_all({"by": By.CSS_SELECTOR, "value": "tbody > tr > td:nth-child(2) > span > a"})

and loop through it with this

for link in self.links:
    link.click()

or add new method to click each element in list:

def _click_all(self, locator):
    [element.click() for element in self._find_all(locator)]

and call it as

self._click_all({"by": By.CSS_SELECTOR, "value": "tbody > tr > td:nth-child(2) > span > a"})

Note that to get list of links for each table row you should remove tr index from you selector:

tr:nth-child(2) > td:nth-child(2)  -->  tr > td:nth-child(2)

Upvotes: 1

Related Questions