searchbox.send_keys() is unable to write any text on the bar by itself - python-3.x

[from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://youtube.com')
searchbox = driver.find_element("xpath",'//*[#id="search"]')
searchbox.send_keys("Akram Khan")
searchButton = driver.find_element("xpath",'//*[#id="search-icon-legacy"]')
searchButton.click()]
(https://i.stack.imgur.com/egHm1.png)
The function [searchbox.send_keys("Akram Khan")] have to be write the mentioned text("Akram Khan") inside the search box of YouTUbe.

So the problem is that when you first try to get the searchbox element with the current version that you had it was searching for the first occurrence of an element with id='search' which there is an element that is before not connected to the search box (therefore send_keys() to that element doesn't work). You can get the specific element that you want by specifying the tag that it is with your current code by doing (because the input element is what you want to be sending your response to):
searchbox = driver.find_element("xpath",'//input[#id="search"]')

#id='search' is reflecting to list of elements so use unique element like #name='search-query'

Related

Selenium: Stale Element Reference Exception Error

I am trying to loop through all the pages of a website. but I am getting a stale element reference: element is not attached to the page document error. This happens when the script try to click the third page. The script got the error when it runs to page.click(). Any suggestions?
while driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[-1].text=='...':
links=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')
for link in links:
if ((link.text !='...') and (link.text !='ADD DOCUMENTS')):
print('Page Number: '+ link.text)
print('Page Position: '+str(links.index(link)))
position=links.index(link)
page=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[position]
page.click()
time.sleep(5)
driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[-1].click()
You can locate the link element each time again according to the index, not to use elements found initially.
Something like this:
amount = len(driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a'))
for i in range(1,amount+1):
link = driver.find_element_by_xpath("(//*[#id='jsGrid_vgAllCases']//a)["+str(i) +"]")
from now you can continue within your for loop with this link like this:
amount = len(driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a'))
for i in range(1,amount+1):
link = driver.find_element_by_xpath("(//*[#id='jsGrid_vgAllCases']//a)["+str(i) +"]")
if ((link.text !='...') and (link.text !='ADD DOCUMENTS')):
print('Page Number: '+ link.text)
print('Page Position: '+str(links.index(link)))
position=links.index(link)
page=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[position]
page.click()
time.sleep(5)
(I'm not sure about the correctness of all the rest your code, just copy-pasted it)
I'm running into an issue with the Stale Element Exception too. Interesting with Firefox no problem, Chrome && Edge both fail randomly. In general i have two generic find method with retry logic, these find methods would look like:
// Yes C# but should be relevant for any WebDriver...
public static IWebElement( this IWebDriver driver, By locator)
public static IWebElement( this IWebElement element, By locator)
The WebDriver variant seems to work fine for my othe fetches as the search is always "fresh"... But the WebElement search is the one causing grief. Unfortunately the app forces me to need the WebElement version. Why he page/html will be something like:
<node id='Best closest ID Possible'>
<span>
<div>text i want</div>
<div>meh ignore this </div>
<div>More text i want</div>
</span>
<span>
<!-- same pattern ... -->
So the code get the closest element possible by id and child spans i.e. "//*[#id='...']/span" will give all the nodes of interest. This is now where i run into issues, enumerating all element, will do two XPath select i.e. "./div[1]" and "./div[3]" for pulling out the text desired. It is only in fetching the text nodes under the elements where randomly a StaleElement will be thrown. Sometimes the very first XPath fails, sometimes i'll go through a few pages, as the pages being might have 10,000's or more pages, while the structure is the same i'll spot check random pages as they all the same format. At most i've gotten through 20 consecutive pages with Chrome (ver 92.0.4515.107) or Edge (ver 94.0.986), both seem to be the latest as of now.
One solution that should work, get all the the span elements first, i.e. '//*[#id='x']/span' get my list then query from the driver like:
var nodeList = driver.FindElements(By.XPath('//*[#id='x']/span' ));
for( int idx = 0 ; idx < nodeList.Count; idx++)
{
string str1 = driver.FindElements(By.XPath("//*[#id='x']/span[idx+1]/div[1]")).GetAttribute("innerText");
string str2 = driver.FindElements(By.XPath("//*[#id='x']/span[idx+1]/div[3]")).GetAttribute("innerText");
}
```
Think it would work but, YUK! This is kind of simplified and being able to do an XPath from the respective "ID" located node would be preferable..

Selenium Stale Element Reference Errors (Seems Random)?

I know there have been several questions asked regarding stale elements, but I can't seem to resolve these.
My site is private so unfortunately can't share, but seems to always throw the error somewhere within the below for-loop. This loop is meant to get the text of each row in a table (number of rows varies). I've assigned WebDriverWait commands and have a very similar for-loop earlier in my code to do the same thing in another table on the website which works perfectly. I've also tried including the link click command and table, body, and tableText definition inside the loop to redefine at every iteration.
Once the code stops and the error message displays (stale element reference: element is not attached to the page document (Session info: chrome=89.0.4389.128)), if I manually run everything line-by-line, it all seems to work and correctly grabs the text.
Any ideas? Thanks!
link = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "*link address*")))
link.click()
table = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "TableId")))
body = tableSig.find_element(By.CLASS_NAME, "*table body class*")
tableText = body.find_elements(By.TAG_NAME, "tr")
rows = len(tableText)
approvedSigs = [None]*rows
for i in range(1, rows+1):
approvedSigs[i-1] = (tableText[i-1].text)
approvedSigs[i-1] = approvedSigs[i-1].lstrip()
approvedSigs[i-1] = approvedSigs[i-1][9:]
approvedSigs[i-1] = approvedSigs[i-1].replace("\n"," ")

how to use selenium python to open new chat whatsapp (i need to target the second icon New Chat)

I need to target the second icon New Chat but they have the same class name
from selenium import webdriver
driver = webdriver.Chrome('C:/Users/ka-my/AppData/Local/Programs/Python/Python37-32/chromedriver')
driver.get('https://web.whatsapp.com/')
input('Enter anything after scanning QR code')
user1 = driver.find_element_by_class_name('_3j8Pd')
user1.click()
1.i need to target the second icon New Chat
just like Facebook and google the class names are dynamically generated So the best way around that is to look for something constant which is the icon string
new_chat = driver.find_elements_by_xpath('//div[#title="New chat"]') # return a list
if new_chat:
new_chat[0].click()
To get 2nd icon in new chat, you can use this:
# get the 2nd element in the list
second_icon = driver.find_elements_by_xpath("//div[#class='_3j8Pd']")[1]
Or:
# get the 2nd element in the list
second_icon = driver.find_elements_by_xpath("//div[#class='_3j8Pd'][2]")
In first example, we are getting a list of all the div elements, and picking the 2nd item using the [1] index. In second example, we are using element index in XPath [2] to get the second element in the list. List index is 0-based and XPath element index is 1-based, so that is why we see 1 and 2 here.

How to create a list of all visible elements in a class python

I am using python 3.x Selenium WebDriver and I am making a for loop to go all through the elements of the page with limit the length of the elements in the class and then print number of iteration but it gets all visible and hidden elements how to get only visible element in the page.
To get all elements from the class I am using
showMore = driver.find_elements_by_class_name('getPhotos')
You can take the list of all elements (visible and invisible) and filter it down to only those that are visible. There are several ways to do this... here is one.
showMore = driver.find_elements_by_class_name('getPhotos')
onlyVisible = filter(lambda x: x.is_displayed(), showMore)
A better way to cater to your requirement will be to create a List inducing WebDriverWait with expected_conditions as visibility_of_all_elements_located as follows :
showMore = WebDriverWait(driver, 20).until(expected_conditions.visibility_of_all_elements_located((By.CLASS_NAME, "getPhotos")))
Note : visibility_of_all_elements_located refers to an expectation for checking that all elements are present on the HTML DOM of a page and are visible. Visibility means that the elements are not only displayed but also has a height and width that is greater than 0.

Get element Id from a found element

I'm using the Chrome driver and Selenium tools in my CodedUI tests. I can find the element I need using the SearchProperties and a Contains operator however I need the full Id for subsequent searches.
For example I need to find an input element with Id "pm_modal_28".
This is easy enough by doing a search where Id contains "pm_modal".
I then need to parse the value "28" out of the Id that was found so I can search for the next nested element which has an Id of "dp_28".
When I use the Id property of HtmlDiv I get a NotSupportedException. Is there anyway I can get all of the Html attributes from an Element or get the Id from an element after it has been found?
Not sure if this what you are after, once the control is identified, you would have all its properties to play around with.
For example
var control = new HtmlDiv ();
control.SearchProperties.Add("Id", "MyDiv_28");
if (!control.TryFind()) return;
var newControl = new HtmlDiv();
newControl.SearchProperties.Add("Id", control.Id.Split('_')[1]);
newControl.TryFind();
HtmlDiv myDiv = new HtmlDiv(browser);
//Add the search logic u want !
myDiv.SearchProperties.Add("class", "ClassName");
string onewayforID = myDiv.Id;
string anotherWay = myDiv.GetProperty(HtmlDiv.PropertyNames.Id).ToString(); // Or u can simpy pass "Id"
See if that Works !

Resources