0

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()
1

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.

.

3
  • Thank you so much.for the answer and detailed explanation. This adjustment fixed everything. Here instead of using "a.product-name", I used "li[class*=ajax_block_product]" to find all the products. Feb 10 '20 at 16:05
  • @MaximAshuev please accept the answer by clicking the tick icon near to it.
    – PDHide
    Feb 10 '20 at 16:07
  • @MaximAshuev u should also remember to use i.locator
    – PDHide
    Feb 10 '20 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.