I am trying to automate webpages with selenium(java).
I am working on an automation tool with which an WebElement can be spied and saved. These saved webobjects can be used to perform certain actions later.
When spying an WebElement, I will get (x,y) coordinates with which I execute the following script that returns a WebElement:
webObject = (WebElement) driver.executeScript(String.format("return document.elementFromPoint(%s, %s);",new Object[] { x, y }), new Object[0]);
If (x,y) lies on a different frame, this script returns WebElement of that Frame which can be used for switching the driver. I keep on executing the same script until I get the WebElement which is not a Frame. While saving this, I save xPath which is relative to the current Frame and ID's of the Frames that I have switched so far.
Later, when performing some actions I locate the WebElement based on ID's of the Frames and xPath.
So is there a convention/standard followed by the developers to always create ID attribute for frame/iframe? If this is not true what other attributes I can rely on?
There is several ways to work with frame/iframe using Selenium WebDriver. You can refer to below stackoverflow question for more understanding about handling of iframe using Selenium WebDriver:
How to identify and switch to the frame in selenium webdriver when frame does not have id
As per best practices, each and every frame should have the ID and Name attribute specified. But in real time scenario it is observed sometime the ID/Name of the frame is not directly visible in the current HTML DOM.
Switching to frames
We can switch over to frames by 3 ways.
By Frame Name:
Name attribute of iframe through which we can switch to it.
Example:
driver.switchTo().frame("name_of_frame");
By Frame ID:
ID attribute of iframe through which we can switch to it.
Example:
driver.switchTo().frame("id_of_frame");
By Index:
Suppose if there are 100 frames in page, we can switch to the iframe by using index.
Example:
driver.switchTo().frame(0);
driver.switchTo().frame(1);
Switching back to the Main Frame:
We can switch back to the main frame by using defaultContent.
Example:
driver.switchTo().defaultContent();
Let me know if this Answers your Question.
Related
I'm trying to select an iframe in selenium java but the element doesn't have a Name or Id attribute. How should I get it? (I want to use the switchTo to switch to it)
The website I am trying to get the iframe from is jklm.fun and the xpath of the iframe is
"/html/body/div[2]/div[4]/div[1]/iframe"
(you need to be in a game for the iframe to exist)
Same way you select anything, based on their tree position: regular CSS selector. You query-select body div div div iframe and you're almost certainly going to get it (unless you have lots of three-deep divs with iframes in them, in which case what on earth is going on on that webpage =), but if that still gives you multiple options, narrow the query selector using tactical :nth-child(...) pseudo-classes.
I would not suggest to go with absolute xpath :
/html/body/div[2]/div[4]/div[1]/iframe
rather have a relative xpath.
Having said that, as far as switching is concerned, there are multiple ways:
Using driver.switchTo()
This basically provides 3 overloaded methods: -
with index :-
driver.switchTo().frame(index)
with name or ID:-
driver.switchTo().frame(nameOrId)
with web element
driver.switchTo().frame(frameElement)
so out of these 3, we can easily use 2 of them since id or name isn't available in your case.
Using the index:
driver.switchTo().frame("here pass the index if you know. ")
Using frame web element:
driver.switchTo().frame(driver.findElement(By.xpath("/html/body/div[2]/div[4]/div[1]/iframe")))
this should work for you.
The other way we have is with Explicit waits:
new WebDriverWait(driver, 20).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("/html/body/div[2]/div[4]/div[1]/iframe")));
This is more convenient, way to switch to iframe in angular or react based Application.
Firstly, I have tried driver.switchTo().frame("framename"); but it does not switching to that.
driver.switchTo().frame("xxx");/// Throws an {"status":7,"value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters."}}
After dig into deeper, I found that the particular frame locators were not even present inside the page source. Any idea on how to switch to that frame.
P.S. I'm using WinApp driver.
Note: Same scenario in web, I'm able to switch using switchTo iframe elements.
I think you have a mismatch here. What you need to input at frame(" ") is not a string. It should be:
driver.switchTo().frame(driver.find_element_by_xpath("xpath of the iframe"));
I am a beginner in Selenium Automation, and stuck with a situation, where, if I open a page xyz.com, and login, then there are some text box and dropdown and buttons to be clicked but the thing is, after the driver get to that page, I can see those elements, and can get the ID and necessary tags, but these whole page consist of 3 different (.do) page.
For example:
1. main page is abc.do
2. left panel is mno.do
3. center is xyz.do
Image of Inspect Element in IE
and my elements exists in xyz.do, and links in mno.do.
I am using eclipse to code, Selenium 3.1, IE 11
How can I switch between them so that my driver can find the elements, write now its showing element cannot be found, and when I pulled the source code its providing of only first .do page.
Please help.
Thanks.
It seems the page is using frames or iframes, but because you do not provide a URL, it's only a guess.
So, to switch a frame/iframe, simply use the switchTo method:
driver.switchTo().frame0); // Frame by number
driver.switchTo().frame("iframe1"); // Frame by selector
After that call, you switch into the "context" of that page/frame/iframe.
Currently I have a problem - I want to switch out of current frame to parent. Application have a lot of of inner frames, so using driver.switchTo().defaultContent() is not the case. In this discussion possible solution is suggested - you should remember all frames you visited and and iterate over them from the top using
driver.switchTo().defaultContent()
The main problem is in that fact, that in my application I, sometimes, forced to use switching to frames located by xpath and other locators - use switch by WebElement. And as it is already mentioned in discussion above after switching all located WebElement becomes invalid and can't be used for switching. So I should have some way to find this element inside frame again. Although i can locate index of this frame element executing some js calls(i.e (WebElement)executeScript("window.frames[i]").equals(myWebElement)), but it is not the case as index may change when some frames deleted from page. Either I can try to find frame names and id's but they may not be specified.
So I see the only possible solution - set some attribute to frames that parent of currently selected - for Example attribute active with value true. Also I should be able to do this for all methods that can switch frame (there exist 3). In all methods I can receive WebElement representing frame, but as far as I know to change attribute value you should execute some js code. So the problem is how to locate current WebElement in js.
Thanks for reading this all.
look at this code snippet above.that's the best way you can locate the current element in Js
passing the element as an argumet to execute script and referring to it in js using arguments[0]
WebElement element = driver.findElement(By.id("foo"));
String contents = (String)((JavascriptExecutor)driver).executeScript("return arguments[0].innerHTML;", element);
you would have to implement a custom logic using javascript
if the element has id then you can use the findElementById() method available in javascript else use the findElementsByName() and then iterate over the array and match other properties to narrow down to your element
I would like for Selenium to navigate a menu via arrow keys--Starting with clicking the top menu item then pressing "DOWN", "DOWN", ...
The problem is that you have to always supply a specific element to send the "DOWN" to.
Is there any way to get the current element?
I tried:
by.xpath(".")
but it said that the expression was unrecognized or didn't return a proper object.
I expect I'm jsut missing some stupid trick.
In Selenium 2.0, if you are using WebDriver to drive the tests in the browser, you can use the WebDriver.TargetLocator class to get the element in focus, in a window/frame:
WebDriver driver = ... // initialize the driver
WebElement currentElement = driver.switchTo().activeElement();
If no element is in focus, the active element would turn out to be the body of the document being displayed, which might be the case when you launch a new page, for instance. When you invoke methods like click, sendKeys etc. you'll find the WebElement returned by the above invocation will always represent the element in focus.
This was tested using FirefoxDriver, and I would suspect that the same would be true of other drivers, except for the HtmlUnitDriver and similar drivers that do not use a full-fledged browser under the hood.
in python:
element = driver.switch_to.active_element
Don't know of a more straightforward way than accessing document.activeElement
How do I test which element has the focus in Selenium RC?
In Ruby/Capybara:
page.driver.browser.switch_to.active_element
Note that this returns a Selenium::WebDriver::Element not a Capybara::Node::Element.