Using python selenium to click an element not visible - python

I am using python selenium on browser to fill in some form. I was trying to select an element in the drop-down list,
0
but if I try to find it by text using this script:
browser.find_element_by_link_text("0").click()
it result an error:
"unknown error: Element is not clickable at point (498, 612). Other element would receive the click: ..."
and if try to find it by class name:
browser.find_element_by_class_name("dropdown-toggle").click()
it result in another error: "element not visible"
is there any way I can click onto that drop-down list? Thanks very much.

I had a similar problem. You can execute a script to change the visibility of that element once you find it and then click it.
driver.execute_script("arguments[0].style.visibility = 'visible';",myElement)
myElement.click()

Try to find it by Xpath searching for partial class and text at the same time:
browser.find_element_by_xpath(//a[contains(#class, 'dropdown-toggle select') and contains(text(), '0')]).click();

you should get the element by xpath and then press it.
browser.find_element_by_xpath(xpath).
read here how to get the xpath: http://www.wikihow.com/Find-XPath-Using-Firebug

Thanks for the feedback, I've found the problem which was due to the new script being loaded by javascript as triggered by some clicks. I've created the following code to capture the exception and retrying until the element is ready:
while True:
try:
time.sleep(1)
browser.find_element_by_xpath("//div[#class='tckt']/a").click()
print("found")
break
except ElementNotVisibleException:
print("notvisible")
except WebDriverException:
print("clickduplicate")
I read it on articles says this happened a lot on radio button for Chrome webdriver, hope this helps.

Firstly click the parent element by finding it, using it's xpath->find the element you want to click within the parent element like the way you did. i.e
browser.find_element_by_link_text("0").click()
Hope this 2 steps will work for you. Otherwise please post the url with the code you've tried-It'll be easy to find out the issue.

Related

Error when switching to iframe with Python Selenium

Currently I'm attemping to switch from my default content, to the only iframe in the website. I don't know if it's how the site is coded, but I can't access via DOM any element.
This is the HTML structure of the site:
XPATH of site is //*[#id="iframeBody"] (When I paste this in the element inspector, I get the correct iframe). So, if I try to switch using frame_to_be_available_and_switch_to_it, this is the output:
try:
WebDriverWait(self.driver, 10).until(ec.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id='iframeBody' and #name='body']")))
except Exception as e:
print(e)
>>> Message: javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
>>>(Session info: chrome=79.0.3945.88)
I also tried creating an iframe element variable, finding it via ID and XPATH and then I've used switch_to(element). Getting the same result. When I print this variable, the element is actually found:
# Also tried finding with id
element = self.driver.find_element_by_xpath('//iframe[#id='iframeBody')
print(element)
<selenium.webdriver.remote.webelement.WebElement (session="9184691b1fdcccc15dd36bbcb914ac8b", element="1ef77729-8a6e-4d3c-98bd-c95878437585")>
But when I try to switch to this iframe, I get the same result as above.
For some reason, this site is not letting me use the DOM data, actually, when I try to click a button I need to use action chains, because I get the same error.
Anybody can help me?
Did you put enough time before switching ?
also, you could directly switch as well:
driver.switch_to.default_content()
driver.switch_to.frame(driver.find_element_by_id("iframeBody"))

How to get full X-path of element instance using selenium python

I wanted to get full X-path of element instance using selenium python ?
Input:
element_inst = driver.find_element_by_link_text('Next')
I wanted to get full X-path of element_inst
Sample Output:
/html/body/div[1]/div[6]/div[1]/div[1]/div[1]/content-viewer/div/div/div/div[2]/div[2]/div/activity-viewer/div/div/phase-map-directive/div/div/div/ul/li[3]/div/span[1]
is there any way to print full X-path of element?
Option -1
I found below link which may help you:
https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/5520
Option 2-
You can use Sikuli and record code for below steps and use clipboard data as xpath in your code
Right Click and click on inspect
On selected element just right click
Copy-> Xpath
Hope this helps

Selenium selects multiple elements with shadow dom

I am working with the chrome://extensions page and I met some problems when trying to access a specific element using selenium. I am trying to get the extension id of an extension that I installed. The work flow is as follows:
1. I go to the chrome://extensions page by using driver.get()
2. I get the "developer mode" toggle by using selenium element selector, and click the toggle so that extension id gets shown on the page.
3. I want to use multiple elements selector to select all "extensions-item" element on the page, find the specific extension that I installed, and retrieve the id. But I am stuck at this part because I am able to select one element but not multiple elements for some reason.
I have the following script:
def expand_shadow_element(driver, element):
shadow_root = driver.execute_script(
'return arguments[0].shadowRoot', element)
return shadow_root
def get_extension_id(driver):
root1 = driver.find_element_by_tag_name("extensions-manager")
shadow1 = expand_shadow_element(driver, root1)
shadow2 = shadow1.find_element_by_css_selector("cr-view-manager")
root3 = shadow2.find_element_by_id("items-list")
shadow3 = expand_shadow_element(driver, root3)
i = shadow3.find_element_by_tag_name("extensions-item") # This works fine, but it can only retrieve the first "extensions-item". What if I want the second one?
print("finding single element successful")
items = shadow3.find_elements_by_tag_name("extensions-item") # This line throws an error
for item in items:
shadow4 = expand_shadow_element(driver, item)
if shadow4.find_element_by_id("name").text != "Chrome Automation Extension":
return "Success"
raise "Error"
The error message is as follows:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"extensions-item"}
(Session info: chrome=78.0.3904.97)
Besides, I used find_element_by_tag_name instead of others because others do not work. To my understanding, even if I believe it is essentially the same as find_element_by_css_selector, but using this instead will throw element not found error. I do not understand why.
Anyone has any idea? I just don't know why I am able to locate one element but not a list of them. I am guessing it is because the way I manipulated shadow-dom, but through searching on the Internet I was not able to find another way of manipulating it. Any help is appreciated, thank you!

Selenium click on XPath button

I have the following code when I inspect on Chrome.
<span id="button-1111-btnInnerEl" class="x-btn-inner x-btn-inner-center" unselectable="on" style="">New Email</span>
I need to click on the label "New Email", but how should invoke it in Selenium (I'm using Python).
def CreateMail():
EmailButton="//*[contains(text(),'New Email')]"
driver.find_elements_by_xpath(EmailButton) // there is no method to enable click.
You can use execute_script
driver.execute_script("document.getElementById('button-1111-btnInnerEl').click()")
driver.find_element_by_id("button-1111-btnInnerEl").click()
Thanks all for your help. Finally i found the answer to my question.I had to add a wait statement, before finding the key. key wasn't present when the page loads, so had to wait a little bit to find the correct key.
def CreateMail():
try:
element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID, "button-1143-btnInnerEl")))
driver.find_element_by_id("button-1143-btnInnerEl").click()
except TimeoutException:
print ("Loading took too much time!")
Hope This XPath will work for you.If you want to validate xpath using your chrome browser just paste this text on your chrome console $x("//*[text()='New Email']") and check how many elements found using this XPath
driver.find_elements_by_xpath("//span[text()='New Email']")
Your statement : "driver.find_elements_by_xpath(EmailButton)" . Click does not work on group of elements. It is actionable only on single element. So you use a singular finder.
driver.find_**element**_by_id(EmailButton).click()
As per the HTML you have shared, the id attribute looks dynamic to me. So we must construct a dynamic xpath or css. Additionally instead of find_elements we have to use find_element so a single WebElement is returned and we can invoke the click() method. Finally, if you look at the node properly, the unselectable attribute is on so we will take help of JavascriptExecutor as follows :
myElement = driver.find_element_by_xpath("//span[starts-with(#id, 'button-')][#class='x-btn-inner x-btn-inner-center']")
driver.execute_script("arguments[0].click();", myElement);
Actually there is different way for locating elements
but in your case there is a ID,
so you can prefer id if its exists
find solution below :
driver.find_element_by_id("button-1111-btnInnerEl").click()

How to use Selenium function back() and I loss my variable in Python?

I'm new to Python.
I met a BIG problem in Python!!
I visit a website and put about 200 options from a dropdownlist in a array.
I want to click every options in the array and click javascript button to submit.
Take something I want from that page and back to previous page click another option.
Do those actions about 200 times in a for loop.
Here is the code:
for option in arrName:
if count > 0:
option.click()
string = u'Something'
link2 = browser.find_element_by_link_text(string.encode('utf8'))
link2.click()
//"do something I want"
browser.back()
count = count +1
In this code, I don't want to use first option.
PROBLEM comes,after the program click the second option, click the link2, and browser.back(), it answer me:
` StaleElementReferenceException: Message: stale element reference: element
is not attached to the page document
that means the options in array disappear?
How should I use the options in the array when the browser.back() in for loop?
Thanks
Yes, this is happening because of DOM refresh. You cannot simply iterate over an array and click back and forth. Best option is to find the element in runtime and then click. Avoid option.click() instead, find the next element with find_element. If you are not sure how to accomplish that then please provide the html

Categories