0

I want to loop through a list of span elements and make Selenium click all span elements available. Currently I'm getting an AttributeError: 'list' object has no attribute 'click'. See code snippets below for more details.

I made have a BasePage as super class where I define most of my selenium methods:

from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait


class BasePage(object):

    def __init__(self, driver):
        self.driver = driver

    def _visit(self, url):
        self.driver.get(url)

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

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

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

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

    def _type(self, locator, input_text):
        self._find(locator).send_keys(input_text)

    def _clear(self, locator):
        self._find(locator).clear()

I have also made a page object where I define all the locators and actions of a page.

from selenium.webdriver.common.by import By

from .base_page import BasePage


class RelatiePage(BasePage):

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

    def __init__(self, driver):
        super(BasePage, self).__init__()
        self.driver = driver


    def relatie_tabs_(self):
        self._click(self._open_actieve_polissen_tab)
        self._click_all(self._open_actieve_polis)
        self.driver.back()

these are the html selectors i want to loop through:

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

the error i'm currently receiving:

line 46, in relatie_tabs_
    self._click_all(self._open_actieve_polis), self.driver.back()

 line 24, in _click_all
    self._find_all(locator).click()

AttributeError: 'list' object has no attribute 'click'
0

1 Answer 1

2

Here is your problem: method self._find_all(self, locator) returns a list of elements, so instead of use it as

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

you should do

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

Also note that if clicking target element triggers page refresh/navigation to new page, you will get StaleElementReferenceException, so _click_all() might be applied to list of elements that performs some actions on static page

Update

from selenium.webdriver.support.ui import WebDriverWait as wait

def _click_all(self, locator):
    counter = len(self._find_all(locator))
    for index in range(counter):
        self._find_all(locator)[index].click()
        self.driver.back()
        wait(self.driver, 10).until(lambda driver: len(self._find_all(locator)) == counter)
Sign up to request clarification or add additional context in comments.

5 Comments

ok so now the test passes. thanks a lot for the assistance. It only clicked the first element though. So my logic isn't correct. After reading your last paragraph. It is making sense to me. My idea of calling the driver.back() method after clicking first element, then going back, clicking the 2nd element etc won't work. How can i implement my idea when a page navigates to new page?
Check updated answer
Currently I'm getting "IndexError: list index out of range"
Try updated answer
wow, thanks a lot. this worked. really appreciate your help. still have loads of python and selenium to learn but happy i could automate the most repetitive tasks at work now. this will save me a lot of time. thanks thanks thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.