How to loop until element clickable - python

i am using python selenium chrome driver and i am stuck at this.
How can i loop this code until one of the elements is clickable?
Like if its finally clickable it should get clicked and print ("clickable") and if its still not clickable it should print ("Not Clickable")
WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH, "//BUTTON[#type='submit'[text()='Zum Warenkorb hinzufügen']"))).click()
WebDriverWait(driver, 150).until(EC.element_to_be_clickable((By.CLASS_NAME, "c-modal__content")))

I am not sure if your use of uppercase button is correct. Use the same syntax as in html.
One more thing: check your xpath with text():
It should be: //button[#type='submit' and text()='Zum Warenkorb hinzufügen']
Also, the general case for such loop in the case of one element is:
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
wait = WebDriverWait(driver, 15)
while True:
try:
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[#type='submit' and text()='Zum Warenkorb hinzufügen']")))
print("clickable")
element.click()
except TimeoutException:
break

Related

ElementNotInteractableException: element not interactable in Selenium

I am trying to get the review of a certain product but it returns an error.
My code:
import selenium
from selenium import webdriver
chrome_path = r"C:\Users\AV\AppData\Local\Programs\Python\Python39\Scripts\chromedriver.exe"
driver = webdriver.Chrome(chrome_path)
driver.get("https://oldnavy.gapcanada.ca/browse/product.do?pid=647076053&cid=1180630&pcid=26190&vid=1&nav=meganav%3AWomen%3ADeals%3ASale&grid=pds_0_1034_1#pdp-page-content")
driver.execute_script("window.scrollTo(0, 1000)")
import time
from time import sleep
sleep(5)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.promoDrawer__handlebar__icon"))).click()
review = driver.find_elements_by_class_name("pr-rd-description-text")
for post in review:
print(post.text)
driver.find_element_by_xpath('//*[#id="pr-review-display"]/footer/div/div/a').click()
review2 = driver.find_elements_by_class_name("pr-rd-description-text")
for post in review2:
print(post.text)
It returns: selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
Can you please tell me what should I do?
The button is really hard to click.
I guess it could be achieved by adding some more waits and moving with ActionChains class methods.
I could click it with Javascript code with no problems.
What it does:
1 Scrolls to the Next button
2 Clicks it.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome(executable_path='/snap/bin/chromium.chromedriver')
driver.get(
"https://oldnavy.gapcanada.ca/browse/product.do?pid=647076053&cid=1180630&pcid=26190&vid=1&nav=meganav%3AWomen%3ADeals%3ASale&grid=pds_0_1034_1#pdp-page-content")
driver.execute_script("window.scrollTo(0, 1000)")
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.promoDrawer__handlebar__icon"))).click()
wait.until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".pr-rd-description-text")))
review = driver.find_elements_by_css_selector(".pr-rd-description-text")
for post in review:
print(post.text)
# wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".pr-rd-pagination-btn"))).click()
element = driver.find_element_by_css_selector(".pr-rd-pagination-btn")
# actions = ActionChains(driver)
# actions.move_to_element(element).click().perform()
driver.execute_script("arguments[0].scrollIntoView();", element) # Scrolls to the button
driver.execute_script("arguments[0].click();", element) # Clicks it
print("clicked next")
I also rearranged your code, moved imports to the beginning of the file, got rid of unpredictable time.sleep() and used more reliable css locators. However, your locator should also work.
I left the options I tried commented out.
That element is weird. Even when I scroll into view, use actions to click it, or execute javascript to click, it doesn't work. What I would suggest is just grabbing the href attribute from the element and going to that URL, using something like this:
driver.get(driver.find_element_by_xpath('//*[#id="pr-review-display"]/footer/div/div/a').get_attribute('href'))

Popup window on youtube - how to close with selenium

Could you please help me with one issue? I have got a problem with Selenium and popup windows with agreements on youtube.
When first window is jumped - Selenium close this window, but if I want to close second window/frame, selenium doesn't work. Could you please help?
The part of code attached below:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from time import sleep
class YoutubeSearcher:
def __init__(self, search):
self.search = search
def open_url(self) -> None:
driver = webdriver.Chrome()
driver.get('https://www.youtube.com/')
try:
WebDriverWait(driver, 5).until(
EC.element_to_be_clickable((By.XPATH, '/html/body/ytd-app/ytd-popup-container/paper-dialog/yt-upsell-dialog-renderer/div/div[3]/div[1]/yt-button-renderer/a/paper-button/yt-formatted-string'))).click()
except:
print("no alert to accept")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//*[#id="yDmH0d"]/c-wiz/div[2]/div/div/div/div/div[2]/form'))).click()
search = driver.find_element_by_id("search")
search.clear()
search.send_keys(self.search)
submit_button = driver.find_element_by_id("search-icon-legacy")
submit_button.click()
From the code you have share these are my observations :
First popup.
WebDriverWait(driver, 5).until(
EC.element_to_be_clickable((By.XPATH, '/html/body/ytd-app/ytd-popup-container/paper-dialog/yt-upsell-dialog-renderer/div/div[3]/div[1]/yt-button-renderer/a/paper-button/yt-formatted-string'))).click()
Second popup.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="yDmH0d"]/c-wiz/div[2]/div/div/div/div/div[2]/form'))).click()
Suggestion :
Check the xpath once if they are correct or are there multiple locators which are being returned.
Add apprropriate waits : like isVisible,clickable for both the locator popup.
Using basic if else you can make the conditions work (no specific need of try except).
After one popup is closed check if the next popup is visible or not.
This is the code that finally works. A switching frame is needed for the second pop up. It's lame, I know but it works.
Hope it helps. Good luck.
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from time import sleep
driver = webdriver.Chrome('C:\Webdrivers\chromedriver.exe')
driver.maximize_window()
driver.get('https://www.youtube.com')
WebDriverWait(driver, 5).until(
EC.element_to_be_clickable((By.XPATH,
'/html/body/ytd-app/ytd-popup-container/paper-dialog/yt-upsell-dialog-renderer/div/div[3]/div[1]/yt-button-renderer/a/paper-button/yt-formatted-string'))).click()
driver.switch_to.frame(0)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"/html/body/div/c-wiz/div[2]/div/div/div/div/div[2]/form/div/span/span"))).click()

Selenium Timeout Exception python

So, i was creating a signup machine using selenium. When this page loads to https://mail.protonmail.com/create/new?language=en it is unable to find element by id/xpath of username. On the other side it was able to find password,passwordc elements. I tried to use WebDriverWait function but it is giving timeout error. Tried many things but this thing is still giving me error. If possible then suggest a way to find element of username on the final page or a perfect WebDriverWait code. Below is my code
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time
url = 'https://protonmail.com/'
driver = webdriver.Chrome('C://Users/AAA/Desktop/chromedriver.exe')
driver.get(url)
driver.find_element_by_xpath('//*[#id="bs-example-navbar-collapse-1"]/ul/li[8]/a').click()
time.sleep(2)
driver.find_element_by_xpath('//*[#id="signup-plans"]/div[5]/div[1]/div[1]/div/div[1]/h4').click()
time.sleep(1)
driver.find_element_by_id('freePlan').click()
time.sleep(1)
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "username")))
driver.find_element_by_xpath('//*[#id="username"]').send_keys('santaking44455')
time.sleep(1)
driver.find_element_by_id('password').send_keys('25J8e5b8')
time.sleep(1)
driver.find_element_by_id('passwordc').send_keys('25J8e5b8')```
You can't find it because it's in an iframe tag higher up in the html source. Switch first to the iframe, then you should be able to interact with the element.
iframe=driver.find_element_by_xpath('//*[#title="Registration form"]')
driver.switch_to.frame(iframe)
driver.find_element_by_xpath('//*[#id="username"]').send_keys('santaking44455')

Unable to locate an element because of timeout in selenium python

I'm trying to finding a way to check if a new page/window is opened successfully and has content or not. I know that selenium is not able to check code 200 to see if the page is successfully loaded or not. So what should I do in order to find out if the page is loaded successfully?
while True:
try:
driver.find_element_by_css_selector("#showbtn").click()
print ("Page Loaded Successfully")
break
except:
print ("Page loading failed")
time.sleep(5)
To check for the presence of an element, you can use WebDriverWait with presence_of_element_located like so:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ...))
)
That will wait until the element is either found or the wait time is reached (10 seconds in the example)
To Click on button Induce WebDriverWait() and element_to_be_clickable() and then click on button.
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#showbtn"))).click()
OR to check pageload successfully you can induce javascript executor before interacting the the element.
WebDriverWait(driver, 20).until(lambda drv: drv.execute_script('return document.readyState == "complete"'))
You need to add following libraries.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Updated code:
while True:
try:
WebDriverWait(driver, 20).until(lambda drv: drv.execute_script('return document.readyState == "complete"'))
print("Page Loaded Successfully")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#showbtn"))).click()
break
except:
print ("Page loading failed")
driver.refresh()

How to handle No SuchElementException in python automation,

elem = driver.find_element_by_id("msgButtonAffirm")
if elem.is_displayed():
elem.click()
print("conform popup is avalable and click")
else:
print "Pop-up is not visible"
You can use find_elements_by_id and check if there is anything in the list
elem = driver.find_elements_by_id("msgButtonAffirm")
if elem and elem[0].is_displayed():
elem[0].click()
print("conform popup is avalable and click")
else:
print("Pop-up is not visible")
You can import the exception and work with that as following:
from selenium.common.exceptions import NoSuchElementException
try:
elem = driver.find_element_by_id("msgButtonAffirm")
elem.click()
print("conform popup is avalable and click")
except NoSuchElementException:
print("Pop-up is not visible")
You need to take care of a couple of things:
While clicking on confirmation popups you shouldn't major focus shouldn't be on handling NoSuchElementException
Historically, in majority of the cases confirmation popups resides within modal dialoge boxes so you need to induce WebDriverwait.
The relevant HTML would have helped us to analyze the issue in a better way. However, as per the mentioned points, you need to to induce WebDriverWait for expected_conditions as element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
try:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#msgButtonAffirm"))).click()
print ("Pop-up was clickable and clicked")
except TimeoutException:
print ("Pop-up was not clickable")
Using XPATH:
try:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='msgButtonAffirm']"))).click()
print ("Pop-up was clickable and clicked")
except TimeoutException:
print ("Pop-up was not clickable")
Note : You have to add the following imports :
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Categories