Cannot locate element during the second iteration in the loop selenium python



  • The goal is to add each product to the cart one by one. I have an error on the second iteration.

    selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    driver=webdriver.Chrome()
    driver.implicitly_wait(5)
    driver.maximize_window()
    driver.get("http://automationpractice.com/index.php")
    cart=driver.find_elements_by_css_selector("a.product-name")
    for i in cart:
        ActionChains(driver).move_to_element(i).perform()
        print(i.text)#just to see that loop went to next iteration
        driver.find_element_by_css_selector ("a.ajax_add_to_cart_button").click()
        driver.find_element_by_xpath("//span[@class='continue btn btn-default button exclusive-medium']//span[1]").click()
    


  • What you are trying is:

    1. in first iteration you click the first element and click the add to cart button
    2. in Second iteration you click the second element and tries to click the add to cart button using the same locator as you used in the first iteration

    Problem

    The below locator finds the first element that matches the locator "a.ajax_add_to_cart_button"

    driver.find_element_by_css_selector ("a.ajax_add_to_cart_button")
    
    1. As you are using the same locator for all the iteration, it always finds the first element which is the add button of the first product.
    2. So in your second iteration, you are not trying to click the "add item to cart" button of second product, but the first product itself. As add button of the first product is not visible, selenium throws "not intractable exception"

    Correct code:

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    driver=webdriver.Chrome()
    driver.implicitly_wait(5)
    driver.maximize_window()
    driver.get("http://automationpractice.com/index.php")
    cart=driver.find_elements_by_css_selector("li[class*=ajax_block_product]")
    for i in cart:
    
        ActionChains(driver).move_to_element(i).perform()
        print(i.find_element_by_css_selector("h5").text)#just to see that loop went to next iteration   
        i.find_element_by_css_selector("a.ajax_add_to_cart_button").click()
        i.find_element_by_xpath("//span[@class='continue btn btn-default button exclusive-medium']//span[1]").click()
    

    Code explanation

    Here instead of using "a.product-name", I used "li[class*=ajax_block_product]" to find all the products. This locator finds all the li elements which have class name that contains "ajax_block_product"

    1. The new locator finds the parent element instead of just the description (entire product element "including image, description, and price).

    2. now when you iterate cart, In 'i' you have a parent element with the description, add button, etc as the child elements

    3. So to get text we call i.find_elment("h5"), for add button we call i.find_elment("a.ajax_add_to_cart_button") etc. Here selelnium will not search the entire html to find the a.ajax_add button, but will search only for elements which are under the product we are interested in.

    .



Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2