Ways to deal with #document under iframe
inline frames
As per the documentation in Using inline frames, an inline frame is a construct which embeds a document into an HTML document so that embedded data is displayed inside a subwindow of the browser's window. This does not mean full inclusion and the two documents are independent, and both them are treated as complete documents, instead of treating one as part of the other.
iframe structure and details
Generally, an iframe element is in the form of:
<iframe src="URL" more attributes>
alternative content for browsers which do not
support iframe
</iframe>Browsers which support iframe display the document referred to by the URL in a subwindow, typically with vertical and/or horizontal scroll bars. Such browsers ignore the content of the iframe element (i.e. everything between the start tag
<iframe...>
and the end tag</iframe>
). Browsers which do not support iframe (or have such support disabled) does the opposite, i.e. process the content as if the<iframe...>
and</iframe>
tags were not there. Thus, the content matters, despite being ignored by some browsers.So to summarize, inline frames do not mean an include feature, although it might sometimes serve similar purposes.
Note that, when inline frames are used, the browser (if it supports them) sends a request to the server referred to by the
URL
in the iframe element, and after getting the requested document displays it inside an inline frame. In this sense inline frames are a joint browser-server issue, but only the browser needs to be specifically iframe-aware; from the server's point of view, there's just a normal HTTP request for a document, and it sends the document without having (or needing) any idea on what the browser is going to do with it.
Something Smarter
As per the best practices while switching to an iframe you need to induce WebDriverWait as follows:
Switch through Frame Name (Java Sample Code):
new WebDriverWait(driver, 20).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.name("frame_name")));
Switch through iframe XPath (Python Sample Code):
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ptifrmtgtframe' and @name='TargetContent']")))
Switch through iframe CssSelector (C# Sample Code):
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.CssSelector("iframe#twitter-widget-0")));
Reference
You can find a couple of relevant discussions in:
- Python: How can I select a html element no matter what frame it is in in selenium?
- Java: Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?
- C#: How to wait for a frame to load before locating an element?
tl; dr
Inline frames vs. normal frames
Get element from within an iFrame
var iframe = document.getElementById('iframeId');
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
You could more simply write:
var iframe = document.getElementById('iframeId');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
and the first valid inner doc will be returned.
Once you get the inner doc, you can just access its internals the same way as you would access any element on your current page. (innerDoc.getElementById
...etc.)
IMPORTANT: Make sure that the iframe is on the same domain, otherwise you can't get access to its internals. That would be cross-site scripting. Reference:
- MDN:
<iframe>
Scripting - MDN: Same-Origin Policy: Cross-Origin Script API Access
Get IFrame's document, from JavaScript in main document
You should be able to access the document in the IFRAME using the following code:
document.getElementById('myframe').contentWindow.document
However, you will not be able to do this if the page in the frame is loaded from a different domain (such as google.com). This is because of the browser's Same Origin Policy.
How can I access the contents of an iframe with JavaScript/jQuery?
I think what you are doing is subject to the same origin policy. This should be the reason why you are getting permission denied type errors.
How to click on a link inside an iframe which is inside a frame using Selenium Webdriver and Java
I was able to get get it working by switching content by index. Using System.out.println(driver.getPageSource());
to log page source to console and make sure i am working at the right spot.
I tried to find iframes by tag and print their name as following.
List<WebElement> elements = DriverContext.driver.findElements(By.tagName("iframe"));
elements.forEach(element -> System.out.println(element.getAttribute("name"))); // printed 'menu' and 'body', perfect
But, while switching content to iframe using name, tried also using WebDriverWait,
driver.switchTo().frame(driver.findElement(By.name("menu")));
for whatever reason, it didn't work and kept throwing the exception as in the question.
Using index to switch to iframe followed by click on the element worked.
driver.switchTo().frame(0); // switch to frame
driver.switchTo().frame(0); // switch to first iframe
driver.findElement(By.id("elmt_XXXX_subMenu")).click();
Also, i had used WebDriverWait to wait for page load.
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(webDriver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete"));
How to interact with interactive elements inside iframe using Selenium
The html-select element is within an <iframe>
Solution
To select the <option>
element with index=36
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 XPATH:
driver.execute("get", {'url': 'http://rh.imss.gob.mx/tarjetonjubilados/(S(4symsfxrnmn3eneitlifwyjy))/default.aspx'})
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ifrPaginaSecundaria']")))
Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//select[@id='ddlDelegacion']")))).select_by_index(36)
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 ECBrowser Snapshot:
Related Topics
Convert Form Data to JavaScript Object With Jquery
Aren't Promises Just Callbacks
Sorting in JavaScript: Shouldn't Returning a Boolean Be Enough For a Comparison Function
What Is the Reason to Use the 'New' Keyword At Derived.Prototype = New Base
How to Replace a Character At a Particular Index in JavaScript
How to Declare a Namespace in JavaScript
Why Does Changing an Array in JavaScript Affect Copies of the Array
Link Tag Inside Browserrouter Changes Only the Url, But Doesn't Render the Component
What Are the Precise Semantics of Block-Level Functions in Es6
How to Check That a Number Is Float or Integer
Google Maps Js API V3 - Simple Multiple Marker Example
Convert a Unix Timestamp to Time in JavaScript
How to Get Image Size (Height & Width) Using JavaScript
Listening For Variable Changes in JavaScript
What Do Multiple Arrow Functions Mean in JavaScript
How to Loop Through a Plain JavaScript Object With the Objects as Members