Karate Driver interaction with iframe - karate

Having difficulty with Karate Driver and inputing data into fields that are in an iframe
Have tried using xpath and css selectors to the iframe so I could theoretically switch into and interact with the iframe without any luck. I can find the iframe but I am unsure how to switch context to the iframe so the scenario can continue inside the iframe. For example inputting values into fields in the iframe.
Help Please :)
Update:
Can successfully switch into an iframe but now running into an issue with nested iframe.
* switchFrame(0)
* click('.some-checkbox')
* switchFrame(0)
neither iframe has great css selectors. The second switchFrame with an index of 0 is not looking to the nested iframe.

I guess you have seen the docs here: https://github.com/intuit/karate/tree/develop/karate-core#switchFrame
I admit this is very tricky. Ideally you have a proper CSS or ID selector to the frame and this is an actual working example from a test I have. Note that the waitFor() may be what you are missing, especially when the <iframe> is some slow loading bloatware.
* waitFor('.some-css-name iframe').switchFrame()
* click('.some-checkbox')
* switchFrame(null)
And unfortunately I have found that this tends to work best on driver type: chrome and chromedriver

Related

NightwatchJS: Safari can't find nested iFrame

I'm having difficulty testing a piece of code using NightwatchJS with Selenium and SafariDriver.
I have an open issue for this on nightwatch repo, although am not sure if it is an issue with nightwatch or something deeper.
The HTML content to be tested looks something like:
<body>
<iframe id="top-iframe" src="about:blank">
#document
<html>
<body>
<container>
<!-- access this iframe to test -->
<iframe id="nested-iframe" src="news.google.com"></iframe>
</container>
</body>
</html>
</iframe>
</body>
Where #nested-frame will need to be accessed from the top level document for inspection of content.
The test code is using NightwatchJS, more details about config, setup and code are in the GitHub issue.
The Gist of the issue:
The problem is that to access the nested iFrame, it needs to first find #top-frame web element, use the returned web element and pass it to frame which makes the WebDriver call to change context of test session to that frame. This is all good with Chrome, FF, and Safari as they can all find this frame web element and make the switch into the frame context. My test that Safari was changing iFrame context, although not sure how good it is, was to try and find another DOM element other than the nested frame, which it could find. The problem comes when with Safari, after switching into #top-frame, it cannot find the #nested-frame web element, and Nightwatch returns a 404 no such element from the HTTP call. Strange, right?
It is very puzzling, my latest thinking was maybe it was a cross origin issue. But then I read on WebDriver switch to frame:
NOTE WebDriver is not bound by the same origin policy, so it is always possible to switch into child browsing contexts, even if they are different origin to the current browsing context.
And I also tried checking Disable Cross Origin Restrictions from Safari Developer menu.
As mentioned before, I can find another DOM element in the #top-frame. I tried things like 10-15s timeouts thinking maybe it needed to load. I can inspect the browser with debugger and see that #nested-frame is there and the content loads as expected. There are not console errors indicating any content failed to load.
It's very puzzling to me and I'm not sure how to further debug. Maybe someone else with a fresh perspective could have a suggestion or if someone has run into a similar situation as this. Throwing this out into the universe as information is limited on the topic too, so maybe this could help someone else. TIA!
iframes
As per the documentation iframe 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.
This usecase
As the top-level <iframe> is having src="about:blank" it is highly unlikely there can be any child <iframe>. Hence, in absence of any child <iframe> your attempt to access any nested <iframe> will fail.
Reference
You can find a relevant detailed discussion in:
Ways to deal with #document under iframe
After discussion with Selenium team, this appears to be a bug with Apple.
I have filed a ticket with Apple here.

Getting "Nosuch element Exception" in Selenium Though XPATH is correct. Not sure is this due to Shadow DOM. Please confirm

I am trying to automate Salesforce application Using Selenium and getting NoSuchelementException though XPATH is correct and valid for particular object. When i have searched the issue, it might be reason for Shadow DOM.
For EX:
So XAPTH i have written like,
driver.findElement(By.xpath("//input[#name='Name']")).sendKeys("Jams");
or
driver.findElement(By.xpath("//input[#id='input-299']")).sendKeys("Jams");
This XPATH is highlighting in Console as well. But while automating it throws nosuchelement error.
So while checking for ShadowDOM option, am getting option like this for Name Object.
#shadow-root(user-agent)
Shadowroot DIV
-- nothing mentioned in div. it just open and closed tags.
How to automate this?
You can check if there are any iframes in your Dom. Simply do //iframe in your page developer mode(F12)> elements tab > search (Ctrf+F) area. If there are any, you will get the number of iframes.
Now if your textbox is in any of iframe use below code to go inside particular iframe first
driver.switch_to.frame("<name or Id of frame>")
then come out to frame use below:
driver.switch_to.parent_frame()
Also, if the issue is not related to frames check below for shadow-root related issue:
you can check below for shadow-root element ( Question is for Java, but you can co-relate):
How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector
The website contents are mostly created now using javascript. You may have to wait for certain elements to load before doing anything to it.
https://seleniumbyexamples.github.io/wait

Unable to switch to iframe in Selenium chromedriver when iframe is directly under body tag [duplicate]

For the portal I am testing now, I came with the problem that I could not create any xpath locators, after some time I figured out that it was because of an '#document', this cuts the path and makes the simple "copy xpath" to direct the path to a completely different element.
<iframe id="FRAMENAME" src="/webclient/workspace/launch-task/REMbl?ds=BP" width="100%" height="100%" frameborder="0" data-navitemname="navitemname" style="" xpath="1">
#document
<html>
CODE....
</html>
I found the solution for this is it is simply add a switchTo like this:
driver.switchTo().frame("FRAMENAME");
This works and makes the rest of the code to work properly but, takes some extra time processing this command till the code moves to the next line.
So I would like to ask, is there is a better solution for this? something smarter/faster?
I am concerned that when the point where I have lots of scripts comes, the execution time will take too long.
I don't use id locators for example because they are all dynamic so sometimes a xpath is required.
Thank you!
To work with elements inside iframe you must switch to this specific iframe.
Your solution .switchTo().frame("FRAMENAME"); is correct. Selenium does not have any other ways to work with iframe wrappers.
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

Scraping iframe using Selenium

I want to scrape ads in websites but many of them are dynamic and they are DOM objects. For example in
this snippet
I can get the iframe tag by Selenium but I cannot go any further. I think it is because of the XPATH. In this case the XPATH of the <html> inside the iframe is /html which is the same as the main page <html>.
This is the line of code that use:
element = WebDriverWait(self.driver,20).until(EC.presence_of_all_elements_located((By.XPATH, '/html')))
Any suggestions?
By default the selenium.webdriver object is set to the default page which it has parsed. To get the iframe data you will have to switch to the given iframe.
driver = webdriver.Chrome(executable_path=path_chrome)
# find the frame using id, title etc.
frame = driver.find_elements_by_xpath("//iframe[#title='iframe_to_get']")
# switch the webdriver object to the iframe.
driver.switch_to.frame(frame[i])
Always remember, if iterating over the iframes then to SWITCH BACK to the default webpage. Otherwise you won't be able to switch to other iframes in same code.
driver.switch_to.default_content()
Update
Below mentioned functions are deprecated now. So i have updated the answer.
driver.switch_to_frame('Any frame') #deprecated
driver.switch_to_default_content() #deprecated
To switch into an iframe on a page, you should use
driver.switch_to.frame:
iframeElement = driver.find_element_by_tag_name('iframe')
driver.switch_to.frame(iframeElement)
You can now use the driver to find elements within the iframe.
To switch back out of the iframe, use driver.switch_to_default_content()

How to work with iframe which is part of a webpage but not getting identified through webdriver?

I am trying to automate a webpage using webdriver,here i am struck with a iframe,which i dont know how to handle.
While i choose css for the iframe by selecting with ,it gives me #xEditingArea
again if I search the same iframe using the css or id,it is not identifying anything.
I tried everything
I want to write some message with the message body which is iframe.
Can anyone guide me how to handle this?
Thanks in advance.
If it is only one iFrame on your website you could try to access it with XPath and the tagname.
Directly accessing iframes is not possible, it has its own DOM elements and we have to switch to that particular frame and then perform the actions you want.
To select the iframe you want to work with, do:
driver.switchTo().frame("frame1");
Now, your driver set to work with the DOM the iframe one.
It's important to remember that maybe switching "back" will be needed. It's done like this:
driver.switchTo().defaultContent();
Using Python Selenium WebDriver, you can access a frame using:
from selenium import webdriver
browser = webdriver.Firefox()
browser.switch_to_frame("fame_name_or_id")
If you want to confirm that the frame was access correctly, just print out the page contents using:
print browser.page_source