I have an element that is placed in 2 frames. So I wait for the parent frame to load, switch to it, wait for the child frame to load, switch to it, then i try to access my element. The frame switching throws no error but when I try to access the element within the child frame, it is throwing an selenium.common.exceptions.NoSuchFrameException with no message.
parentF = WebDriverWait(driver, 60).until(EC.visibility_of_element_located((By.ID, "parent")))
driver.switch_to.frame(parentF)
childF = WebDriverWait(driver, 60).until(EC.visibility_of_element_located((By.ID, "child")))
driver.switch_to.frame(childF)
program_select = WebDriverWait(driver, 60).until(EC.visibility_of_element_located((By.ID, "xyz")))
selenium.common.exceptions.NoSuchFrameException
...implies that Selenium driven WebDriver instance was unable to locate the <iframe> element.
You have adapted the right approach. Ideally, to locate an iframe you have to induce WebDriverWait inconjunction with expected_conditions set as frame_to_be_available_and_switch_to_it().
However, there can be numerous reasons behind seeing this error and some of the reasons and solutions are as follows:
The desired iframe may be a nested iframe within it's parent iframe. In those cases you have to induce WebDriverWait first to switch to the parent iframe and then to the child iframe as follows:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"parent_iframe_xpath")))
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"child_iframe_xpath")))
If you are switching between two sibling iframes then you first need to switch back to the default_content first and then switch to the sibling iframe as follows:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"sibling_iframe_A")))
driver.switch_to.default_content()
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"sibling_iframe_B")))
You can find a detailed discussion in How to address “WebDriverException: Message: TypeError: can't access dead object” and wait for a frame to be available using Selenium and Python
At times multiple iframes can have similar values for same attributes. In those cases, you may need to construct Locator Strategies which identifies the element uniquely using the src attribute as follows:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#id="iframe_id and #src='iframe_src'"]")))
Related
I wrote a simple application in python, but when trying to click a button, I get an error Element not interactable. Here is a part of the code where it happens. I did wait for the element to render.
WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.XPATH, '//*[#id="root"]/div[2]/div/div/div[2]/ul/li/button')))
driver.find_element(By.XPATH, '//*[#id="root"]/div[2]/div/div/div[2]/ul/li/button').click()
The error happens on this website: https://magiceden.io/ when clicking Connect Wallet in the top right corner and then trying to click Phantom in the opening window.
Reason behind this exception:
“element not interactabe” exception may occur due to various reason.
Element is not visible
Element is present in off screen (After scroll down it will display)
Element is present behind any other element
Element is disable
For your case it's locator, you can use below locator to click on it.
XPATH
//header/nav[1]/div[2]/div[2]/div[1]/button[2]
OR
//button[contains(#xpath,'1')]
OR
(//button[contains(.,'Connect Wallet')])[1]
The Syntax should be like
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "myXpath")))
element.click();
Imports
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
I have tested with First and third XPATH, it's working for me, let me know if this does not solve your issue.
while len(driver.find_elements(By.XPATH,"//*[#title='Next page']"))!=0:
The element is not found (and the while loop skept), I tried adding a timer
ui.WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH,"//*[#title='Next Page']")))
Still impossible to make selenium recognize the element. I don't think I saw anything that looked like an iframe on the source (I might have missed it).
Instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following locator strategy:
ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"//*[#title='Next Page']"))).click()
I've used Selenium for a number projects without problems. This one, however, no dice.
I'm trying to automate a check out process, and sometimes there is a prompt to re-input information. The window has a javascript popup (I think), and, while I can select the <div id="app"> portion without any problems, I CANNOT get find the iframe and focus on it.
So, this works:
driver.find_elements_by_id('app')
But, nothing works to recognize the frame and switch to it. For example, none these work:
driver.find_element_by_id()
driver.find_element_by_name()
driver.find_element_by_xpath()
And, I assume that because I can't find and switch to the iframe.
Help?
The element with the text as E-Mail Login is within an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe.zoid-visible[title='ec_payment'][name^='__zoid__ec__payment']")))
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#class='zoid-visible' and #title='ec_payment'][starts-with(#name, '__zoid__ec__payment')]")))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
driver.switch_to.frame(iframe_elem)
or
driver.switch_to_frame(iframe_id)
in your case you can use :
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"));
to switch back to main use:
driver.switch_to_default_content()
Try this code to switch to frame
frame = driver.find_element_by_xpath('//div[starts-with(#id, "zoid-ec-payment")]/iframe')
driver.switch_to.frame(frame)
Hi guess, today I struggled with a problem I cant fill card data.https://i.stack.imgur.com/VzN22.png
As I understood it appears cuz of nested html(html in html I'm not good in eng). So what do u supposed to do?
I tried to fill it by id, full xpath, selector etc...
Nothing works.
Some code what I used
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "cardCvc-input"))).send_keys("1234")
data.https://i.stack.imgur.com/VzN22.png
You need to switch to iframe first to access the element.The input element present inside an iframe.
Induce WebDriverWait() and frame_to_be_available_and_switch_to_it() and following css selector.
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='payment']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "cardCvc-input"))).send_keys("1234")
To come out from iframe you need to switch to default_content.
driver.switch_to.default_content()
Unable to use send_keys() for an iframe. How to select this iframe and which element inside this should be use for send_key()?
and iframe html code
<iframe class="textarea" src="/framework/html/blank.html" style="width: 99%; border-width: 1px; height: 332px;">
#document
<html webdriver="true">
<head>
</head>
<body> … </body>
</html>
</iframe>
How to send the value to description?
One more thing i want to know that this code of frame is not coming when i go for "view page source " in browser?
driver.switch_to.frame(driver.find_element_by_tag_name("iframe")) assuming that driver is a healthy instance of webdriver. To continue with the default content do driver.switch_to.default_content()
EDIT: When you have switched to needed frame, locate your webelement as you always do. I guess (but not sure) in your case this will be a html/body, so
el = driver.find_element_by_xpath('html/body')
should be fine. And perform
el.send_keys('keys_to_send')
EDIT2: Before sending keys you may have to focus on the element (click should do the thing, a child element should appear). Or you can just place the needed text via JS.
driver.execute_script('document.body.innerHTML = "%s"' % text_var)
The Accepted answer works very well for the given question. However I have two reasons for adding one more answer and hope this answer might help someone landing this question with different ask.
Reason 1:
Accepted answer has one way of handling iframes inside a web page. However there are different ways to handle iframes.
By using index position of the frame
By using name of the frame
By using id of the frame
Reason 2:
It uses driver.find_element_by_tag_name("iframe") statement to find iframe element which may not work or return expected iframe web element when there are multiple iframe elements in the same page.
There are many articles out there to explain handling iframes in detail.
http://allselenium.info/handling-iframes-using-selenium-webdriver/
You can switch to the iframe using multiple approaches as per the prevailing condition of the HTML DOM.
If the <iframe> is the only iframe within the DOM Tree you can use the following line of code:
Using TAG_NAME:
driver.switch_to.frame(driver.find_element(By.TAG_NAME, "iframe"))
Locating the <iframe> element with a unique Locator Strategy:
Using css_selector:
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "iframe.textarea[src='/framework/html/blank.html']"))
Using xpath:
driver.switch_to.frame(driver.find_element(By.XPATH, "//iframe[#class='textarea' and #src='/framework/html/blank.html']"))
Ideally to switch to an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using TAG_NAME (only iframe present):
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.TAG_NAME, "iframe"))).click()
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe.textarea[src='/framework/html/blank.html']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css_selecor"))).send_keys("character_sequence")
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#class='textarea' and #src='/framework/html/blank.html']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#class='TlogBtn']/span[#class='mailicn']/img"))).send_keys("character_sequence")
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Reference
You can find a couple of relevant discussions in:
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
In order to handle iframes on a web page you need to switch to the iframes first that are present on the page using this command:
driver.switch_to.frame(frame_id)
This tutorial has a working example of handling iframe using selenium with python which will made you able to get through this issue.