Python selenium: wait until element is clickable - not working - python

I will test a web-app. there is a button available in my table to select all entries.
I've tried:
driver.wait.until(ExpectedCondition.element_to_be_clickable((By.XPATH, "myXpath"))).click()
selenium clicks on the button, but nothing happens. (also with send_Keys(Keys.Return)) the application is developed with GXT, I thing that there is much javascript behind the button. Is there is possibility to wait until a eventloader is ready? waiting before a click solves the problem, but not a solution for automated testing.

Correct syntax for explicit wait in python is :
element = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.ID, "myElement")))
Better that After above you do :
element.click();
So in your case :
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "myXpath")))
element.click();
Better you follow it. Also share your whole code so I can correct it. Your just 1 line code doing little confuse.

I had also that problem... Web apps have views over views and Appium sometimes gets wrong.
This worked for me:
x = webElement.location['x'] + (webElement.size['width']/2)
y = webElement.location['y'] + (webElement.size['height']/2)
print("x: "+x+" - y: "+y)
//I have setted a 200 milli duration for the click...
//I use tap just for Android... If is iOS for me it works better touchAction
driver.tap([(x,y)], 200)
Edit:
I misunderstood your question... Sorry...
Maybe modifying your Xpath to:
(don't know if this will work at a web app)
xpath = "//whatever_goes_here[#clickable='true']"

I know it is probably too late, but for me the solution was to add this line before all the elements clicks:
driver.execute_script('document.getElementsByTagName("html")[0].style.scrollBehavior = "auto"')
Nowadays, sites tend to have a scrholl-behavior set to auto. Drivers do not know that, though they do know when an element is outside the view. So, what happens is a driver tries to click the element. The driver sees that the element is outside the view, so it calls a scroll method and after that immediately clicks the element without waiting for scrolling to finish. And the scrolling does take some time because of its behavior set to auto.

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait=WebDriverWait(driver,5)
a= wait.until(EC.element_to_be_clickable(('id or xpath or class or any thing else ','enabled_trigger')))
a.click()
please note you must have two parentheses in element.to_be_clickable(())

Related

Python Selenium - send_keys not sending any information to element

I am trying out Selenium for the first time so I apologize if there is an obvious mistake or problem with my code.
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://youtube.com')
searchBox = driver.find_element_by_id('search')
searchBox.send_keys('Programming')
searchButton = driver.find_element_by_id('search-icon-legacy')
searchButton.click()
So I tried this and it loads the page fine but, it does not input any characters into the searchBox (I quadruple checked that the id was correct - copied it directly from the inspector).
NOTE:
My internet is really REALLY slow and it takes YouTube approx. 20 seconds to fully load, so I thought that was an issue so I tried;
...
driver.get('https://youtube.com')
driver.implicitly_wait(30)
searchBox = driver.find_element_by_id('search')
...
But this did not work either.
I did use XPATH instead of finding it by element ID at the start and that did not work.
I checked and copied the XPATHs and IDs directly from the inspector and nothing so far has inputted anything into the textbox.
What could be the problem? (1)
and does the webdriver wait for the page to load/find the element before doing anything after it being initialized with the driver.get('websiteAddress')? (2)
NOTE: I double checked that I was selecting the right element as well.
To send keys to the input tag with id = search. We use webdriver waits to allow the element to be usable after driver.get so the page loads correctly.
driver.get('https://youtube.com')
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH, "//input[#id='search']"))).send_keys("Programming")
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
If you don't know the waiting time:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
delay = 40
WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, "//form[#role='form']//input[#id='username']")))
Then it just waits on the element, for as log as delay is, but will continue as soon as the element is found, that the best way to wait on slow connections.
To relate elements more easily you can use ChroPath, it is an extension for google chrome / edge that allows you to see the path of an element, through cssSelector, Abs XPath, Rel XPath and the tag name, so when your code is not working you can try these other ways. Particularly this extension helps me a lot.

Selenium can't locate element after I change desktop

So I have this part of the code:
buttons = browser.driver.find_element_by_id('buttons')
camera_icon = buttons.find_element_by_class_name('style-scope yt-icon-button')
camera_icon.click()
I am trying to click the upload button on youtube, it works perfectly fine when I stay on the browser's desktop(fullscreen). If I start the program and leave the webdriver to work in the background, while I navigate to another desktop, it can't locate 'style-scope yt-icon-button' for some reason.
Any help/tips on this is much appreciated!
It might be timing issue. So make sure you are using appropriate wait mechanism in your script. Introduce implicit and explicit wait conditions.
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".style-scope.yt-icon-button"))
element.click()
Import below package for this
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Moreover, It seems the issue with your locator. there are 2 classes style-scope and yt-icon-button. as far as i know class selector find_element_by_class_name doesn't support compound classes.
camera_icon = buttons.find_element_by_class_name('style-scope yt-icon-button')
should be
camera_icon = buttons.find_element_by_css_selector('.style-scope.yt-icon-button')

Is there a way for selenium to click the like button (without using class)? (refer to picture)

tried a couple of methods with selenium, didn't work for me.
bot.find_element_by_css_selector('[data-testid="like"]').click()
bot.find_element_by_xpath("//a[#aria-label = 'Like']/*[name()='svg']").click()
bot.find_element_by_xpath("//a[#role = 'button']").click()
ss of the inspect segment
//edit//
my attempt to click the like button in this tweet!
https://twitter.com/RichardEudes/status/1196798030529335296
my code is as follows
# link is the url above
for link in stored_links:
bot.get(link)
bot.find_element_by_xpath("//div[#aria-label='Like']/div/div").click()
time.sleep(10)
I would add a WebDriverWait to your code sample as well:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# link is the url above
for link in stored_links:
bot.get(link)
like_button = WebDriverWait(bot, 10).until(
EC.presence_of_element_located((By.XPATH, "//div[#aria-label='Like']/div/div")))
like_button.click()
time.sleep(10)
I used the above code to successfully click the Like button on the tweet provided.
Breaking down this code sample:
from statements at the top -- these are used to include all of the Selenium libraries we need. By is used for locators, specifically By.XPATH here. WebDriverWait and expected_conditions are both used for the explicit wait, where we wait for the like button to be visible before clicking it.
WebDriverWait(bot, 10) declares a new instance of an explicit wait, specifically with a timeout of 10 seconds -- meaning, this method fails if the condition is not met within 10 seconds.
EC.presence_of_element_located is the condition we are waiting on -- in this case, we are waiting on the presence of a certain element. By.XPATH, "//div...div" specifies which element we are waiting on.
The line like_button = WebDriverWait(bot, 10).until(EC.presence_of_element_located((By.XPATH, "//div[#aria-label='Like']/div/div"))) is waiting on the presence of the element located through //div[#aria-label='Like']/div/div. If the element is not found within 10 seconds, a TimeoutException will be thrown.
Lastly, WebDriverWait returns the WebElement which is found after waiting -- so, like_button is the WebElement object we were waiting to exist. That is how we are able to click the button through like_button.click(), because we are using the reference to the WebElement we stored in the previous WebDriverWait step.

Python3 Selenium Button Clicking Issue

I want to click a button as the following picture shows with Selenium
I write my code like that:
try:
browser.find_element_by_xpath("//a[#href='/portal/site/16/801']").click()
except Exception as e:
print(e)
But it always shows error, it cannot locate the element.
Here is the html code of what I want to click.
<a href="/portal/site/16/801" data-blackname="16" title="课程网站">
<img src="/access/img//site/16.png" class="media-icon" onerror="this.src='/resources/images/app-default-icon2.png'">
<h5><i class="icon-ok"></i>课程网站</h5>
​
Could somebody help me fix the problem? Thanks in advance!
Adding a random sleep after using Selenium to send username, password and ENTER. It works
time.sleep(random.randint(3,6))
As supputuri mentioned, Use explicit waits instead of random sleep. If the lower limit is not enough for the button to be clickable then it will surely make the error random.
The explicit wait is used to tell the Web Driver to wait for certain conditions (Expected Conditions). In this case, the button to be clickable. explicit waits by default check every half a second if the condition is fulfilled or not.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//a[#href='/portal/site/16/801']"))).click()
To use this you have to import the followings:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

How to retrieve the Ping Download and Upload time from browser tests?

I am trying to automate speedtests with different browsers automatically, and the main part of the test is inside a loop. The problem is, sometimes, one element which has been selected before, and the script worked correctly, at the one of the next steps, exactly at the same loop and at the same page, but with different number, without any change in the xpath, selenium cannot select it again. So, I can not repeat my test as much as I want.
Most of the time I have this problem with Edge, and I think one reason can be, the xpath for elements which I found by help of Chrome or Firefox. ( I can not find the xpath in Edge first of all, I searched a lot about it).
I also put the different xpath that I use. Actually I want to get the numeric or string values of ping,download, upload location and server.
Please let me know, how can I solve this issue, I tried different sleep time and two different xpath. the script always gives me error when I am trying to select the element with class_name or css_selector.
firefox:
"/html/body/div[3]/div[2]/div/div/div/div[3]/div[1]/div[3]/div/div[3]/div/div[1]/div[2]/div[1]/div/div[2]/span"
chrome:
"//[#id='container']/div[2]/div/div/div/div[3]/div[1]/div[3]/div/div[3]/div/div[1]/div[2]/div[1]/div/div[2]/span"
chrome:
"//div[#class='result-item result-item-ping updated']/div[2]/span"
Other question is how can I wait for a page to load completely. this method WebDriverWait(driver,some seconds) does not work for me and i have to use time.sleep()
Error:
selenium.common.exceptions.NoSuchElementException: Message: No such element
element = driver.find_element_by_xpath("/html/body/div[3]/div[2]/div/div/div/div[3]/div[1]/div[3]/div/div[3]/div/div[1]/div[2]/div[1]/div/div[2]/span")
To automate the speedtests you can use the following solution:
Code Block:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Edge(executable_path=r'C:\WebDrivers\MicrosoftWebDriver.exe')
driver.get("https://www.speedtest.net/")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.js-start-test.test-mode-multi"))).click()
WebDriverWait(driver, 45).until(EC.url_contains("result"))
print("Ping :"+driver.find_element_by_css_selector("div[title='Reaction Time'] div.result-data.u-align-left>span").get_attribute("innerHTML"))
print("Download: "+driver.find_element_by_css_selector("div[title='Receiving Time'] div.result-data.u-align-left>span").get_attribute("innerHTML"))
print("Upload :"+driver.find_element_by_css_selector("div[title='Sending Time'] div.result-data.u-align-left>span").get_attribute("innerHTML"))
#driver.quit()
Console Output:
Ping :35
Download: 21.53
Upload :3.46
Browser Snapshot:
Use the following CSS locators to identify the values:
Download: *.result-data-large.number.result-data-value.download-speed*
Upload: *.result-data-large.number.result-data-value.upload-speed*
Ping: *.result-data-large.number.result-data-value.ping-speed*
Making use of getText(), you can retrieve their values. Wait for an element in the page to be visible to make sure the page is loaded successfully.
Try with:element = driver.find_element_by_xpath("/html/body/div[3]/div[2]/div/div/div/div[3]/div[1]/div[3]/div/div[3]/div/div[1]/div[2]/div[1]/div/div[2]/")
Maybe also you need to catch exception for: NoSuchElementException cases.
I've tested these CSS selectors and they work in both Chrome and Edge.
span.ping-speed # ping
span.download-speed # download
span.upload-speed # upload
div.server-current > div.result-label # server
If you want to know when the page is done loading, you can wait until the URL changes from https://www.speedtest.net to https://www.speedtest.net/results/<some number>. I would just use WebDriverWait and url_contains("results") , e.g.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 10).until(EC.url_contains("results"))
There are some other approaches in this question.
WebDriverWait driverWait = new WebDriverWait(driver, 30000);
driver.get("https://www.speedtest.net/");
WebElement goLink = driver.findElement(By.cssSelector(".js-start-test.test-mode-multi"));
driverWait.until(ExpectedConditions.elementToBeClickable(goLink));
goLink.click();
By download = By.cssSelector(".result-data-large.number.result-data-value.download-speed");
By upload = By.cssSelector(".result-data-large.number.result-data-value.upload-speed");
By ping = By.cssSelector(".result-data-large.number.result-data-value.ping-speed");
driverWait.until(ExpectedConditions.urlMatches("https://www.speedtest.net/result/[0-9]"));
String downloadSpeed = driver.findElement(download).getText();
String uploadSpeed = driver.findElement(upload).getText();
String pingValue = driver.findElement(ping).getText();
System.out.println("Download: "+downloadSpeed + "\nUpload: "+ uploadSpeed + "\n Ping: "+pingValue);
Output
Download: 78.82
Upload: 45.93
Ping: 23

Categories