How to switch between frames in Selenium WebDriver using Java - java

I am using java with WebDriver.I have to switch between two frames. I have recorded the test case in selenium IDE and in that I got the values as selectFrame relative=top select Frame=middle Frame
But there is a problem it is not able to recognize the relative=top and middleFrame. How can I solve this problem in Selenium WebDriver with Java?

WebDriver's driver.switchTo().frame() method takes one of the three possible arguments:
A number.
Select a frame by its (zero-based) index. That is, if a page has three
frames, the first frame would be at index 0, the second at index 1
and the third at index 2. Once the frame has been selected, all
subsequent calls on the WebDriver interface are made to that frame.
A name or ID.
Select a frame by its name or ID. Frames located by matching name
attributes are always given precedence over those matched by ID.
A previously found WebElement.
Select a frame using its previously located WebElement.
Get the frame by it's id/name or locate it by driver.findElement() and you'll be good.

to switchto a frame:
driver.switchTo.frame("Frame_ID");
to switch to the default again.
driver.switchTo().defaultContent();

First you have to locate the frame id and define it in a WebElement
For ex:- WebElement fr = driver.findElementById("id");
Then switch to the frame using this code:- driver.switchTo().frame("Frame_ID");
An example script:-
WebElement fr = driver.findElementById("theIframe");
driver.switchTo().frame(fr);
Then to move out of frame use:- driver.switchTo().defaultContent();

You can also use:
driver.switch_to.frame(0)
(0) being the first iframe on the html.
to switch back to the default content:
driver.switch_to.default_content()

Need to make sure once switched into a frame, need to switch back to default content for accessing webelements in another frames. As Webdriver tend to find the new frame inside the current frame.
driver.switchTo().defaultContent()

There is also possibility to use WebDriverWait with ExpectedConditions (to make sure that Frame will be available).
With string as parameter
(new WebDriverWait(driver, 5)).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("frame-name"));
With locator as a parameter
(new WebDriverWait(driver, 5)).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("frame-id")));
More info can be found here

This code is in groovy, so most likely you will need to do some rework. The first param is a url, the second is a counter to limit the tries.
public boolean selectWindow(window, maxTries) {
def handles
int tries = 0
while (true) {
try {
handles = driver.getWindowHandles().toArray()
for (int a = handles.size() - 1; a >= 0 ; a--) { // Backwards is faster with FF since it requires two windows
try {
Log.logger.info("Attempting to select window: " + window)
driver.switchTo().window(handles[a]);
if (driver.getCurrentUrl().equals(window))
return true;
else {
Thread.sleep(2000)
tries++
}
if (tries > maxTries) {
Log.logger.warn("Cannot select page")
return false
}
} catch (Exception ex) {
Thread.sleep(2000)
tries++
}
}
} catch (Exception ex2) {
Thread.sleep(2000)
tries++
}
}
return false;
}

Related

Unable to sendKeys() into input text field

I intend to automate a simple form fill Junit test on the following website: https://newdesign.millionandup.com
The input textfield i am attempting to send keys to is identified with id=email and i have tried the following two methods:
1.
WebElement passInput = driver3.findElements(By.className("sidebar__item-text")).get(0); // this xPath does the trick
wait.until(ExpectedConditions.visibilityOfElementLocated(emailLocator));
passInput.click();
passInput.sendKeys("emailID");
Thread.sleep(3000); // only to see the result
WebElement em1 = driver3.findElement(emailLocator);
JavascriptExecutor jse = (JavascriptExecutor)driver3;
//driver3.findElement(emailLocator).sendKeys(emString);
Thread.sleep(1000);
jse.executeScript("arguments[0].click()", em1);
jse.executeScript("arguments[0].value='prisoner24601#gouvernement.fr';", em1);
if (em1.isSelected()) {
System.out.println("email typed");
} else {
System.out.println("unable to send keys, element not interactable");
}
To no avail in both cases, the textfield is still not interactable and i am unable to type the data into it.
EDIT: As suggested in the comments i have attempted a third way:
3.
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[#id='email']")));
System.out.println("email input located");
element.click();
System.out.println("email input clicked");
element.sendKeys(emString);
Element is actually located, but, as soon as the methods click() or sendKeys() are called, the execution stops after stating "element not interactable"
The xpath - //input[#id='email'] is matching 9 elements in the DOM. Its important to find unique locators - Link to refer
And the pop-up for Register opens on mouse movement. After mouse movement, will be able to view and interact with the pop-up elements.
Used below xpath to send keys to the element Email Address and it worked for me.
//form[#id='frmLeadModal']//input[#id='email']
Try like below once, it might work for you too.
driver.get("https://newdesign.millionandup.com/#initial");
WebDriverWait wait = new WebDriverWait(driver, 30);
Actions actions = new Actions(driver);
actions.moveByOffset(100, 100).perform();
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//form[#id='frmLeadModal']//input[#id='email']"))).sendKeys("example#email.com");

Is there a way to search webelement on a main window first, if not found, then start searching inside iframes?

Requirement: Bydefault, search for webelement on main window, if found perform action else search for webelement inside iframes and perform required action
Selenium 3.141
'''
WebElement el = driver.findElement(By.xpath("//*[contains(text(),'here')]"));
boolean displayFlag = el.isDisplayed();
if(displayFlag == true)
{
sysout("element available in main window")
el.click();
}
else
{
for(int f=0;f<10;f++)
{
sysout("element available in frameset")
switchToFrame(frameName[f]);
el.click();
System.out.println("Webelement not displayed");
}
}
'''
My script is failing at first line itself. It is trying to find element in main window but element is actually available in iframe.
But the requirement is to search first in main window and then only navigate to iframes. How to handle such usecase?
Any suggestion would be helpful? Thank you.
Yes, you can write a loop to go through all the iframes if the element not present in the main window.
Java Implementation:
if (driver.findElements(By.xpath("xpath goes here").size()==0){
int size = driver.findElements(By.tagName("iframe")).size();
for(int iFrameCounter=0; iFrameCounter<=size; iFrameCounter++){
driver.switchTo().frame(iFrameCounter);
if (driver.findElements(By.xpath("xpath goes here").size()>0){
System.out.println("found the element in iframe:" + Integer.toString(iFrameCounter));
// perform the actions on element here
}
driver.switchTo().defaultContent();
}
}
Python Implementation
# switching to parent window - added this to make sure always we check on the parent window first
driver.switch_to.default_content()
# check if the elment present in the parent window
if (len(driver.finds_element_by_xpath("xpath goes here"))==0):
# get the number of iframes
iframes = driver.find_elements_by_tag_name("iframe")
# iterate through all iframes to find out which iframe the required element
for iFrameNumber in iframes:
# switching to iframe (based on counter)
driver.switch_to.frame(iFrameNumber+1)
# check if the element present in the iframe
if len(driver.finds_element_by_xpath("xpath goes here")) > 0:
print("found element in iframe :" + str(iFrameNumber+1))
# perform the operation here
driver.switch_to.default_content()

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

I am getting element is not attached to the page document error for the above code. Moreover I want to know how to handle elements which 'appear' as a result of an action on the target page.
WebDriver driver = new ChromeDriver();
driver.get("https://www.irctc.co.in/eticketing/loginHome.jsf");
driver.manage().window().maximize();
driver.findElement(By.linkText("Sign up")).click();
//Verify whether the navigation is to the correct page
String title=driver.getTitle();
if (title.equals("IRCTC Next Generation eTicketing System")){
driver.findElement(By.id("userRegistrationForm:userName")).sendKeys("abcdef");
driver.findElement(By.linkText("Check Availability")).click();
WebElement text=driver.findElement(By.xpath(".//*[#id='userRegistrationForm:useravail']"));
boolean availability=text.isDisplayed();
try {if(availability==true){
System.out.println("The user id is available. Please enter other details to complete registration");
}}
catch (NoSuchElementException e){
System.out.println("The user id is not available. Please enter a different user ID.");
}
}
else
System.out.println("You are on a wrong page");
}
}
You need to create a custom wait to handle the element that will appear because of an action. So technically speaking, you are waiting for an expected condition to be true.
private void waitForElement(String element) {
WebDriverWait wait = new WebDriverWait(Driver, 10); // Wait for 10 seconds.
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element)));
WebElement element = driver.findElement(By.xpath(element));
element.click(); // The element is now present and can now be clicked
}
In the above code you know the string / xpath of the element. You can pass it into this method and will wait for 10 seconds for the execpected conditon to become true. When it is true, the element can then be clicked.
Rather than catching an exception, the preferred way is to use .findElements() (plural) and then check for empty. If the collection is empty, the element doesn't exist on the page. If it exists, grab .get(0) and use it.
I added a few other optimizations to your code. I would do something more like this.
driver.get("http://toolsqa.com/automation-practice-table/");
driver.findElement(By.linkText("Sign up")).click();
// Verify whether the navigation is to the correct page
if (driver.getTitle().equals("IRCTC Next Generation eTicketing System"))
{
driver.findElement(By.id("userRegistrationForm:userName")).sendKeys("abcdef");
driver.findElement(By.linkText("Check Availability")).click();
List<WebElement> text = driver.findElements(By.id("userRegistrationForm:useravail"));
if (!text.isEmpty())
{
// element found
if (text.get(0).isDisplayed())
{
System.out.println("The user id is available. Please enter other details to complete registration");
}
}
else
{
// element NOT found
System.out.println("The user id is not available. Please enter a different user ID.");
}
}
else
{
System.out.println("You are on a wrong page");
}
If you perform some action and then need to wait for an element to appear, you can use WebDriverWait. An example is below that waits for a BUTTON to be visible and clicks it.
By buttonLocator = By.id("theButtonId");
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement button = wait.until(ExpectedConditions.visibilityOfElementLocated(buttonLocator));
button.click();
There are many other options under ExpectedConditions that you should check out in the docs linked.

Selenium "Element not found" due to incorrect XPath expression

I am completely new to Selenium and XPath. Today is the first time I am trying to execute a simple script using Selenium RC. Please find the code below.
package com.rcdemo;
import org.junit.Test;
import org.openqa.selenium.By;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
public class MathTest {
#SuppressWarnings("deprecation")
public static void main(String[] args) throws InterruptedException {
// Instatiate the RC Server
Selenium selenium = new DefaultSelenium("localhost", 4444 , "*firefox C:/Program Files (x86)/Mozilla Firefox/firefox.exe", "http://www.calculator.net");
selenium.start(); // Start
selenium.open("/"); // Open the URL
selenium.windowMaximize();
// Click on Link Math Calculator
selenium.click("xpath=.//*[#id='menu']/div[3]/a");
Thread.sleep(4500); // Wait for page load
// Click on Link Percent Calculator
selenium.click("xpath=//*[#id='content']/ul/li[3]/a");
Thread.sleep(4000); // Wait for page load
// Focus on text Box
selenium.focus("name=cpar1");
// Enter a value in Text box 1
selenium.type("css=input[name=\"cpar1\"]", "10");
// Enter a value in Text box 2
selenium.focus("name=cpar2");
selenium.type("css=input[name=\"cpar2\"]", "50");
// Click the Calculate button
selenium.click("xpath=.//*[#id='content']/table/tbody/tr/td[2]/input");
// Verify if the result is 5
String result = selenium.getText("//*[#id='content']/p[2]/span/font/b");
System.out.println(result);
if (result == "5") {
System.out.println("Pass");
} else {
System.out.println("Fail");
}
}
}
The issue is when executing the above code, an exception is happening at the getText() line. I copied that XPath from the developer tools of Google Chrome. Even when I checked manually once, the same XPath expression is showing. I have tried to find the solution for this from today morning. How can I get Selenium to find the element?
PS: In the result variable I have to capture the result after a calculation. For example, 10 % 50 = 5. This 5 I need to capture.
You need to wait for "Result" to get populated.
Here is the updated code snippet. It should work for you:
// Add this line
if (!selenium.isElementPresent("//*[#id='content']/p[2]/span/font/b"))
{
Thread.sleep(2000);
}
// Verify if the result is 5
String result = selenium.getText("//*[#id='content']/p[2]/span/font/b");
System.out.println(result);
// Update this line
if (result.trim().equals("5"))
{
System.out.println("Pass");
}
else
{
System.out.println("Fail");
}
And you need to use the .equals method to compare the two string values.
Note - A better approach is to replace Thread.sleep with dynamic wait methods, like waitForPageToLoad, waitForElementPresent (custom methods), etc.

Selenium is unable to locate any element in html page

I'm trying to make a small java app. that can log in to my university portal, I used Selenium in the following code:
//some import statements
public class Portal{
public Portal(){
File file = new File("C:/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
HtmlUnitDriver driver = new HtmlUnitDriver();
String target = "http://portal.kfupm.edu.sa/cp/home/loginf";
driver.get(target);
ArrayList <WebElement> inputs = (ArrayList<WebElement>) driver.findElements(By.tagName("input"));
System.out.println(inputs.size());
for(WebElement input : inputs){
System.out.println(input.getAttribute("value") + " " + input.getAttribute("name"));
// to insure the link is displaying something
ChromeDriver driver1 = new ChromeDriver();
driver1.get(driver.getCurrentUrl());
}
public static void main(String [] args){
new Portal();
}
}
the problem is when I use this target (my university portal) I get inputs.size() = 0; although, I'm sure there are elements with (input) tagName. Also I get the same resulst whatever was the method of (By) class I used.
However, when I change the target to any link (for example: "http://www.google.com" or "http://www.facebook.com" , I get elements in the inputs ArrayList (all elements of tagName (input) that are in the target html page). Can any body please tell me what is the problem and how can I solve it? thanks in advance..
The reason that you find zero elements with tag input is that all the elements lie inside a frame tag. Selenium is able to see to current window and all the elements that are defined inside frame tag (i.e. are inside a frameset) are invisile to it.
To see the element you will need to switch frame first, So that selenium has control inside the target frame and not in the outer window. Try this
driver.swtichTo().frame(0); // this will move selenium control inside first frame

Categories