How should I use WebElements and Actions through page object model? - selenium

I have a button on my Webpage which I want to click once the required piece of information is entered. I am currently using By to establish all the elements of the page but want to use WebElements for this button and then use Actions to click it later.
How should I do that in my Page Object class.
I tried with below approach :
WebElement addressinput = driver.findElement(By.xpath("//input[#id='pac-input']"));
By addressinput = By.xpath("//input[#id='pac-input']");//this works fine
But on running the Test class as TestNG it shows null pointer exception on WebElement line. Tried to do it with By as well but the button just won't recieve the click. It works pefectly fine with WebElements and action which I have tried before without using POM below is the reference code for that :
WebElement button = driver.findElement(By.xpath("//button[#id='btn_gtservice']"));
Actions action = new Actions(driver);
action.moveToElement((WebElement) CheckAvailability).click().perform();
driver.switchTo().defaultContent();

You've got
action.moveToElement((WebElement)CheckAvailability)
That should be
action.moveToElement((button)CheckAvailability)
As it is, you'll be getting a null pointer as you have no variable named WebElement defined

When using PageFactory in PageObjectModel if you expect the element to be loaded after some information is entered, through some JavaScript and it might not be immediately present on the page already you can use the Actions once the element is returned through WebDriverWait support with a normal locator factory as follows:
Code Block:
package com.pol.zoho.PageObjects;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.interactions.Actions;
public class ZohoLoginPage {
WebDriver driver;
public ZohoLoginPage(WebDriver driver)
{
PageFactory.initElements(driver, this);
}
#FindBy(xpath="//button[#id='btn_gtservice']")
public WebElement myButton;
public void doLogin(String username,String userpassword)
{
WebElement button = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(ZohoLoginPage.getWebElement()));
new Actions(driver).moveToElement(button).click().perform();
}
public WebElement getWebElement()
{
return myButton;
}
}
You can find a detailed discussion in How to use explicit waits with PageFactory fields and the PageObject pattern

Related

Page Object Patern in Java Selenium - update of elements

I use Page Object Pattern in Java Selenium and I've got problem with updating element after click action.
There is a list of X elements on page and button that enables to scroll them (after clicking on button, new elements are displayed on the list, old ones disappear)
There are two classes:
public abstract class WebPage {
protected WebDriver driver;
WebPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(30)), this);
}
and
public class ChildClass extends WebPage{
#FindBy(selector)
List<WebElement> elements;
By nextButton = By.id(xxx);
ChildClass(WebDriver driver) {
super(driver);
}
public void iterateAllElements(){
for (WebElement element: elements){
//some action
}
if(buttonIsEnabled())
clickOnButton();
iterateAllElements();
}
}
Please tell me why object "elements" is not initialized with new values after invoking clickOnButton(); function? I cannot get elements that are displayed on 2nd, 3rd page ect
There are still elements from 1st view on the list. It works fine in debug mode, but problem occurs when I want to run it.

Want to know about tag name locator in Selenium Webdriver

I know and use all of the locator except tag name locator. I am confused when and why i use tag name locator also how can i use this locator. I am trying but failed. So please some body help me.
"tagName" is used to identify / find / select WebElement(s) by the HTML tag name.
You can find more information about HTML tag name at this link:HTML Introduction
Sample code to find all the anchor tag elements on the Mercury Tours Demo AUT home is page:
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class TagNameDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.setProperty("webdriver.chrome.driver","C:\\selenium\\Drivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String baseUrl = "http://www.newtours.demoaut.com/";
driver.get(baseUrl);
List<WebElement> anchortags = driver.findElements(By.tagName("a"));
for(WebElement anchortag : anchortags)
{
System.out.println(anchortag.getText());
}
driver.close();
driver.quit();
}
}
When we have duplicate element locators like classname, id and identified by unique tag name then we can use this locator.
example:
driver.findElement(By.tagName("a")).findElement(By.xpath(//*[#class='submit'])).click();
some web elements are designed only with the tag name and don't have other locators, in that case, we can use tagName locator
when we have dynamic changes in other locator values and difficult to use them. In this scenario, tagName is almost unique and can identify elements easily.

Selenium(datepicker issue) [duplicate]

This question already has answers here:
Select from a DatePicker in Python
(3 answers)
Closed 3 years ago.
Am trying to automate a date picker,on clicking the ok button date should be displayed in date box.I have two date pickers like for a start date and the other is for the end date.One date picker is registering the date but the other date picker is not registering the date,neither i get any error.Please help,it's urgent.Here is my code..
package DatePicker;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class DatePickerTest
{
WebDriver driver;
Actions builder;
#BeforeMethod
public void setup()
{
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
driver.get("http://localhost/able/public/index.php/get_inputs");
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
System.out.println("Hello client");
}
#Test
public void TestDate() throws Exception
{
WebDriverWait wait=new WebDriverWait(driver,3);
Boolean invisible=wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("preloader")));
if(invisible)
{
driver.findElement(By.xpath("//*[#id=\"add-edit-form\"]/div[3]/div[1]")).click();
}
Thread.sleep(2000);
WebElement web11=driver.findElement(By.className("dtp-btn-ok"));
web11.click();
Thread.sleep(2000);
driver.findElement(By.id("Contract_e_date")).click();
Thread.sleep(1000);
builder= new Actions(driver);
//Thread.sleep(1000);
WebElement web2=driver.findElement(By.className("dtp-btn-ok"));
//Thread.sleep(1000);
builder.moveToElement(web2).click(web2);
//web2.click();
Thread.sleep(1000);
builder.perform();
}
}
Look here:
WebElement web11=driver.findElement(By.className("dtp-btn-ok"));
WebElement web2=driver.findElement(By.className("dtp-btn-ok"));
If your 2 datepickers have the same CSS class - Selenium will always find the first one and perform operations on the first item found.
Quick and dirty solution would be switching to WebDriver.findElements() function which returns the List of WebElements like:
List<WebElement> datepickers = driver.findElements(By.className("dtp-btn-ok"));
WebElement web11 = datepickers.get(0);
WebElement web2 = datepickers.get(1);
A better solution would be choosing the right Locator Strategy so your locator would uniquely match this or that datepicker (look into their parents, associated text, etc.)
Also be aware that using Thread.sleep is a some form of a performance anti-pattern, consider using WebDriverWait instead, check out How to use Selenium to test web applications using AJAX technology for more details if needed.

Not able to identify element on the screen- how to use tab

Screenshot of the element I want to click:
I automating my website(new to automation). once i login i get to another page where selenium web driver is not able to find any of the elements(I tried all possibilities even sso related).
Only solution i could find was using tabs and enter.
So when i enter that page i need to click 9 time "TAB" key from the keyboard and then enter so that my login is verified. since i don't have any element using which i can perform the tab and enter actions. is there a way where once i get to that page the web driver starts pressing "TAB" key 9 times and then "Enter" on 10 time.
Please help I have been working on this over a week now and not getting
anywhere.
optimist_creeper-main class:
package Modules;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
import Modules.HomePage;
public class MainClass {
String appUrl = "als-stg-1.mtvn.ad.viacom.com/webqa/";
#Test public void MainTest() {
System.setProperty("webdriver.gecko.driver", "C:\\Shayni Coding\\Automation\\Gecko\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get(appUrl);
HomePage home = new HomePage();
home.HomePageTest(driver);
}
}
Home Page class:
public class HomePage {
#BeforeClass public void beforeClass() {
System.out.println("before class");
}
public void HomePageTest(WebDriver driver) {
driver.manage().window().maximize();
WebElement email = driver.findElement(By.id("cred_userid_inputtext"));
email.sendKeys("shayni#outlook.com");
WebElement pass = driiver.findElement(By.id("cred_password_inputtext"));
pass.sendKeys(Keys.ENTER);
pass.click();
String expectedTitle = "VMS Web";
String actualTitle = driver.getTitle();
Assert.assertEquals(expectedTitle,actualTitle);
}
}
Thanks.
Just get a random object like the body tag and use that to send your key presses.
e.g.
WebElement dummyElement = driver.findElement(By.xpath("/html/body"));
for (int i = 0; i < 9; ++i) {
dummyElement.sendKeys(keys.TAB);
}
dummyElement.sendKeys(keys.ENTER);
The above code finds the body take and sets it as an element. It then presses the tab key 9 times and then presses the enter key. Which is what you asked for. Hope that helps.

Refresh is not working using sendkeys ,Selenium JAVA

I am trying to automate google search,normal sendkeys is working ,but when I try to send using keys.F5 or ascii code ,refresh wont work
also when try to do location reload it gives error as " The method execute_script(String) is undefined for the type WebDriver
"
Tried instead of F5 ,F1 key also but no avail
` package com.at.sample;
import org.openqa.selenium.Keys;
import java.lang.Thread;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
// import org.openqa.selenium.Alert;
import java.util.List;
public class Refreshgoogle {
public static void main(String[] args) throws InterruptedException {
WebDriver driver;
System.setProperty("webdriver.chrome.driver","c://chromedriver.exe");
driver= new ChromeDriver();
//Launch the Application Under Test (AUT)
driver.get("http://google.com");
Actions action = new Actions(driver);
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("test data");
//sends normal keybaord strokes
// approch 1 driver.findElement(By.xpath("//html")).sendKeys(Keys.F5);
// approch 2.1 WebElement element1 = driver.findElement(By.xpath("//*[#id=\"tsf\"]/div[2]/div[1]/div[2]/div[2]"));
//approch 2.2 element1.sendKeys(Keys.F1);
// approch 3 driver.findElement(By.xpath("//*[#id=\"gsr\"]")).sendKeys(Keys.F5);
// driver.execute_script("location.reload(true);");
System.out.println(driver.getTitle());
// working driver.navigate().to(driver.getCurrentUrl());
}
}
`
There are 4 approaches
First 3 wont refresh pagea
when used 4th it shows error as The method execute_script(String) is undefined for the type WebDriver
You can refresh in below ways:
1.Using get method and recursive way
driver.get("https://URL.com");
driver.get(driver.getCurrentURL());
Using Navigate method and Recursively calling your URL
driver.get("https://URL.com");
driver.navigate.to(driver.getCurrentURL());
Using one valid webelement and send keys
driver.get("https://URL.com");
driver. findElement(By.id("username")).sendKeys(Keys.F5);
Hope this help.
Please refer below solution
driver.navigate.refresh();
If you want to refresh your page using keys then you can also use Robot class.
Robot robot = new Robot(); // Robot class throws AWT Exception
Thread.sleep(2000); // Thread.sleep throws InterruptedException
robot.keyPress(KeyEvent.VK_CONTROL); // press Control key down key of
robot.keyPress(KeyEvent.VK_F5);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_F5);
Thread.sleep(2000);
This is selenium related issue more details available here: https://github.com/webdriverio/webdriverio/issues/1344
WebElement(I) sendKeys() will not accept Keys (keyboard keys). This can be handled using Actions class only.
Additionally, if you need to refresh the page, use WebDriver() refresh() or get current URL using getCurrentUrl() of same interface and navigate() using same url as parameter.
Update:
Here is the detailed explanation on each approach:
1) As per 'https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/WebElement.html#sendKeys-java.lang.CharSequence...-', sendKeys() in WebElement(I) accepts only char sequence (i.e. string.).
// approch 1 driver.findElement(By.xpath("//html")) returns a WebElement and this element sendKeys will accept only char sequence. Hence, your approach r=to refresh using Keys.F5 won't work here.
2) // approch 2.1 WebElement element1 = driver.findElement(By.xpath("//*[#id=\"tsf\"]/div[2]/div[1]/div[2]/div[2]"));
//approch 2.2 element1.sendKeys(Keys.F1);
Same explanation as approach 1.
3) // approch 3 driver.findElement(By.xpath("//*[#id=\"gsr\"]")).sendKeys(Keys.F5);
Did the same kind of operation as approach 1 and is explained there.
4) If we need to use javascriptexecutor, first we need to create javascriptexecutor object like below and should call execute_script() using reference variable of that object:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(Script,Arguments);
If you are not created this object, you will get 'execute_script(String) is undefined for the type WebDriver', which is expected.
Hence, the 4 approaches what you tried will not refresh the page.
Instead, you can use below options:
1) Actions class sendKeys(): which will accept keyboard keys.
2) using driver.navigate().refresh();
3) Using javascriptexecutor after creating an object for the same (as explained in approach 4)
Try with this code:
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
public class TestRefresh {
public static void main(String[] args) {
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://www.google.com");
`// case 1:`
`driver.navigate().to(driver.getCurrentUrl());`
`// case 2:`
`((JavascriptExecutor)driver).executeScript("document.location.reload()");`
`// case 3:`
`driver.navigate().refresh();`
}
}