Wait element By iOSXCUITFindBy - automation

I need to add in my declaration a way to wait the element, for so then to click it. I am using Appium with Java, in a IOS device.
#iOSXCUITFindBy (xpath = "//XCUIElementTypeButton[#name=\"Enviar depois\"]")
private RemoteWebElement BtnEnviarDepois;
public void ClickBtnEnviarDepois(){
**// I need to Add a way to wait the element here**
BtnEnviarDepois.click();
}
I need to add in the declaration something like this, but I don't know how to implement:
public void wait(By ID) {
WebDriverWait wait = new WebDriverWait(DriverFactory.getDriver(), (180));
WebElement element = wait.until(ExpectedConditions.elementToBeClickable((ID)));
}

Simplest way to initialise wait and reuse it in the page objects is to use the concept of Inheritance. Here's one example how you can do it.
Page class:
public class MyPage extends BasePage {
#iOSXCUITFindBy(xpath = "//XCUIElementTypeButton[#name=\"Enviar depois\"]")
private WebElement btnEnviarDepois;
public MyPage(AppiumDriver driver){
super(driver);
}
public void ClickBtnEnviarDepois(){
waitForElementToBeClickable(btnEnviarDepois).click();
}
}
BasePage class:
public class BasePage {
private final WebDriverWait wait;
public BasePage(AppiumDriver driver){
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
public WebElement waitForElementToBeClickable(WebElement element){
return wait.until(ExpectedConditions.elementToBeClickable(element));
}
}
Some people don't like to write custom methods like waitForElementToBeClickable(). So alternatively, you can slightly change the code as below:
Page class:
public class MyPage extends BasePage {
#iOSXCUITFindBy(xpath = "//XCUIElementTypeButton[#name=\"Enviar depois\"]")
private WebElement btnEnviarDepois;
public MyPage(AppiumDriver driver){
super(driver);
}
public void ClickBtnEnviarDepois(){
wait.until(ExpectedConditions.elementToBeClickable(btnEnviarDepois)).click();
}
}
BasePage class:
public class BasePage {
protected final WebDriverWait wait;
public BasePage(AppiumDriver driver){
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
}

Related

In Page Object Model do i have to create webdriver all the time?

I'm using the Page Object Model I just started i created 2 packages one is com.automation.pages another one is com.automation.testcases.
In both packages I created a class for the login page it works fine I'm sharing the code below.
package com.automation.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver ldriver)
{
this.driver=ldriver;
}
#FindBy (xpath="//input[#name='email'] ") WebElement email;
#FindBy (xpath="//input[#name='password']") WebElement password;
#FindBy (xpath="//body/div[2]/div[2]/div[2]/form[1]/div[3]/div[2]/button[1]") WebElement loginbutton;
public void logintoLabaiik(String email1, String password1 )
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
email.sendKeys(email1);
password.sendKeys(password1);
loginbutton.click();
}
}
The problem I'm facing when I working on the new page is when I created a driver and when using ldriver it throws me an error also when I replace the "l" still it throws me the error. kindly solve my problem.
package com.automation.pages;
import org.openqa.selenium.WebDriver;
public class TaxSetup {
WebDriver driver;
public TaxSetup(WebDriver driver)
{
this.driver.ldriver;
}
}
It looks you have an issue in TaxSetup constructor.
This should work.
public TaxSetup(WebDriver driver){
this.driver=driver;
}
Take a look at how to create 2 Page Object classes and use them in tests:
LoginPage
public class LoginPage {
final WebDriver driver;
public LoginPage(WebDriver driver){
this.driver=driver;
}
// page implementation
}
TaxSetup
public class TaxSetup {
final WebDriver driver;
public TaxSetup(WebDriver driver){
this.driver=driver;
}
// page implementation
}
How to use in test
public class SomeTest {
WebDriver driver;
LoginPage loginPage;
TaxSetup taxSetupPage;
#BeforeClass
public void initDriverAndPages() {
driver = ... // e.g. new ChromeDriver()
loginPage = PageFactory.initElements(driver, LoginPage.class);
taxSetupPage = PageFactory.initElements(driver, TaxSetup.class);
}
#Test
public void someTest() {
// implement test using loginPage, taxSetupPage as you like
}
#AfterClass
public void quitDriver() {
driver.quit();
}
}
Please correct the below line in your TaxSetUp constructor.
this.driver.ldriver;
This is suppose to be
this.driver = driver;
And yes, you have to pass the WebDriver instance for all the page classes that you create as part of your application otherwise they will assign default value to the driver which is null.

Wait until element doesn't exists using AjaxElementLocatorFactory

I'm using page factory and AjaxElementLocatorFactory in my selenium project. I would like to implement something like this:
#FindBy(className = "loading-container")
private WebElement loadingElement;
public LoadingPage(WebDriver driver) {
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 100);
PageFactory.initElements(factory, this);
}
public void waitLoadingToFinish() {
waitUntilElementDoesn'tExist(loadingElement);
}

I am receiving java.lang.NullPointerException at stepDefinition

I am using POM pattern in cucumber and in StepDefinition package I created one 'Hooks.java' to launch the browser and 'CustomersModuleSteps.java' to add new customer when I am executing the runner file I am receiving the below error. someone please look into it and advise.
Error:```
************ open URL ************
************ Enter Username & password ************
************ clicking on login button ************
************ Validating page Title ************
************ clicking on CustomersMenu **********
Given user clicks on customers menu # com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu() in file:/Users/rajasekhar/eclipse-workspace/nopCommerse/target/test-classes/
java.lang.NullPointerException
at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
at com.sun.proxy.$Proxy19.click(Unknown Source)
at com.nopCommerse.Base.ElementExtension.ClickOnIt(ElementExtension.java:55)
at com.nopCommerse.pageObjects.CustomersModuleObjects.clickCustomersMenu(CustomersModuleObjects.java:31)
at com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu(CustomersModuleSteps.java:32)
at ✽.user clicks on customers menu(com.Features/CustomersModule.feature:4)
When user clicks on customers menu item # com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu_item() in file:/Users/rajasekhar/eclipse-workspace/nopCommerse/target/test-classes/
************ clicking on logout link ************
************ closing the Browser ************
Failed scenarios:
com.Features/CustomersModule.feature:3 # Add a new customer
1 Scenarios (1 failed)
2 Steps (1 failed, 1 skipped)
0m24.213s
My Base class
public class TestBase extends ElementExtension {
public WebDriver driver;
public Logger logger;
public Properties configProp;
public CustomersModuleObjects custmod;
public LoginPageObjects lp ;
}
My CustomersModuleSteps.java
package com.nopCommerse.StepDefinition;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import com.nopCommerse.Base.TestBase;
import com.nopCommerse.pageObjects.CustomersModuleObjects;
import io.cucumber.java.Before;
import io.cucumber.java.en.*;
public class CustomersModuleSteps extends TestBase {
#Before
public void setup() {
//object creation for logger
logger = Logger.getLogger("EmployeeRestApi"); //added logger
PropertyConfigurator.configure("Log4j.properties"); //added logger
logger.setLevel(Level.DEBUG);
}
#Given("user clicks on customers menu")
public void user_clicks_on_customers_menu() {
logger.info("************ clicking on CustomersMenu **********");
custmod = new CustomersModuleObjects(driver);
custmod.clickCustomersMenu();
}
#When("user clicks on customers menu item")
public void user_clicks_on_customers_menu_item() {
logger.info("************ clicking on customer Menu item **********");
custmod.clickCustomerMenuItem();
}
}
And this is my page factory class
package com.nopCommerse.pageObjects;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
import com.nopCommerse.Base.TestBase;
public class CustomersModuleObjects extends TestBase {
WebDriver driver;
//constructor of CustomersModule class
public CustomersModuleObjects(WebDriver ldriver) {
driver = ldriver;
PageFactory.initElements(ldriver,this);
}
//Identify webElements
#FindBy(how = How.XPATH,using = "//a[#href='#']//span[contains(text(),'Customers')]")
WebElement CustomersMenu;
#FindBy(how = How.XPATH,using ="//a[#href='/Admin/Customer/List']//span[contains(text(),'Customers')]")
WebElement customerMenuItem;
//action methods for elements identified
public void clickCustomersMenu() {
ClickOnIt(CustomersMenu);
}
public void clickCustomerMenuItem() {
ClickOnIt(customerMenuItem);
}
}
This could be for two reasons in my experience:
You are not initializing the WebDriver correctly, so that you could debug and check that driver is not null at this point CustomersModuleSteps.java:32
The XPath for the element is not the correct one, so that you could install an extension for google chrome (I use xpath helper) and check that you are locating correctly the element in the Page.
In addition to you could improve the structure, extending a little bit the POM Patterns and get the code cleaner splitting the Page Actions and Page Objects as you can see in the following example:
Web Page Element definition
public class LoginPageElements {
protected WebDriver driver;
public LoginPageElements(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
//Mapping web elements
#FindBy(id = "userName")
protected WebElement TxtUserName;
#FindBy(id = "Password")
protected WebElement TxtPassword;
#FindBy(id = "Login")
protected WebElement BtnLogin;
}
Web Page Actions definition
public class LoginActions extends LoginPageElements {
WebDriverWait wait;
public LoginActions (WebDriver driver, WebDriverWait wait) {
super(driver);
this.wait = wait;
}
public void Login() {
fillUserName();
fillPassword();
ClickLogin();
}
private void fillUserName() {
wait.until(ExpectedConditions.visibilityOf(TxtUserName));
TxtUserName.sendKeys("User");
}
private void fillPassword() {
wait.until(ExpectedConditions.visibilityOf(TxtPassword));
TxtPassword.sendKeys("Pass");
}
private void ClickLogin() {
wait.until(ExpectedConditions.visibilityOf(BtnLogin));
wait.until(ExpectedConditions.elementToBeClickable(BtnLogin));
BtnLogin.submit();
}
Test Class
public class LoginExample {
WebDriver driver;
WebDriverWait wait;
LoginActions loginActions;
#BeforeClass
public void setDriver() {
System.setProperty("webdriver.chrome.driver", ClassLoader.getSystemResource("chromedriver.exe").getPath());
driver = new ChromeDriver();
wait = new WebDriverWait(driver, 10);
loginActions = new LoginActions(driver, wait);
driver.manage().window().maximize();
}
#Test()
public void testLogin() {
driver.get("http://www.YourLoginPage.com/");
loginActions.Login();
}
#AfterClass
public void close() {
driver.quit();
}
}
Hope this could help you and so that you will be able to find where the problem is easier

FindBy in pageFactory (webdriver) doesn't work correctly

I want to write tests in selenium WebDriver with PageFactory, but if I add annotations in PageFactory form in class
#FindBy(id="email")
public WebElement mailLink;
and usage:
mailLink.sendKeys("mail#mail.com");
I get a NullPointerException every time. Another way:
driver.findElement(By.id("email")).sendKeys("mail#mail.com");
returns correct value. Where is the problem with first method?
My code:
I have got driver initialization in FaceClass:
public class FaceClass {
protected WebDriver driver;
public FaceClass(WebDriver driver){
this.driver = driver;
}
public HomePage navigateToApp(){
driver.navigate().to("https://facebook.pl");
return PageFactory.initElements(driver, HomePage.class);
}
}
and class with business logic:
public class HomePage extends FaceClass{
public HomePage(WebDriver driver) {
super(driver);
// TODO Auto-generated constructor stub
}
#FindBy(id="email")
public WebElement mailLink;
#FindBy(id="pass")
public WebElement passLink;
#FindBy(how = How.ID, using="u_0_n")
public WebElement loginButton;
public ProfilePage navigateToProfile(){
try{
if(driver.findElement(By.id("pass")).isEnabled() || driver.findElement(By.id("pass")).isDisplayed()){
System.out.println("ok!");
}
//driver.findElement(By.id("pass")).sendKeys("pass_to_account");
//driver.findElement(By.id("email")).sendKeys("mail#mail.com");
//driver.findElement(By.id("u_0_n")).click();
mailLink.sendKeys("mail#mail.com");
passLink.sendKeys("pass_to_account");
loginButton.click();
} catch (Exception e) {
e.printStackTrace();
}
return PageFactory.initElements(driver, ProfilePage.class);
}
}
and test:
public class ExampleTest {
WebDriver driver;
#Before
public void setUp() throws Exception {
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver.exe");
DesiredCapabilities capabilities=DesiredCapabilities.chrome();
capabilities.setCapability("marionette", true);
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.navigate().to("https://facebook.pl");
}
#After
public void tearDown() throws Exception {
driver.quit();
}
#Test
public void test() {
//fail("Not yet implemented");
HomePage homepage = new HomePage(driver);
homepage.navigateToProfile();
}
}
All elements are enabled and visible
You did not initialize your elements before using. To initialize your page elements PageFactory method initElements. It's better if you call it in your constructor like this:
public HomePage(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
Hope it works.

Parallel execution using POM with PageFactory

I started encountering problems when I use static objects reference for WebDriver and run the tests in parallel.
public static WebDriver driver;
Hence I decided to use non-static object reference for the WebDriver.
private WebDriver driver;
Now when I use POM with Page Factory, my understanding is that everytime I create a Test I will have to be creating a new Object in the test class as shown below.
/* Constructor in the Page Object class */
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
2 testcases as shown below in the same class.
private LoginPage loginPage;
#Test
public void testCase1() {
loginPage = new LoginPage(getDriver());
loginPage.sendkeys("sometext");
}
#Test
public void testCase2() {
loginPage = new LoginPage(getDriver());
loginPage.sendkeys("sometext");
}
My question here is a
Am I right in creating page object for every test cases?
Is there any way I can optimize this? Because One doubt I got is that non-static object reference may be getting overridden and causing problems in one of the methods if I run them in parallel.
Sorry if my query is naive. Any help would be appreciated.
You do not need to initialize it again. Also, initialize the pages in #BeforeTest rather than in test cases.
Here i would like to give you example of Page object model. Hope you can relate this.
My Main test:
#Before
public void SelectBrowser(){
driver = WebUtils.SelectBrowser(driver,"Chrome");
}
#Test
public void LoginToGmail() throws InterruptedException{
//WebDriver driver = new FirefoxDriver();
//MAximize the Screen
driver.manage().window().maximize();
//Go to Gmail Login Page
SignInPage SignInPage = new SignInPage();
WebUtils.GoToSignInPageForPropertyFile(driver, "URL");
//Click on Next
SignInPage.ClickToLogin(driver, By.cssSelector("input[id='next']"));
Now Supporting class:
GoToSignInPageForPropertyFile method will be in WebUtils
Whatever i write in Webutils will be used by each page object class.
For e.g.
public class WebUtils {
public static pageobject.SignInPage GoToSignInPageForPropertyFile(WebDriver driver, String URL) {
ReadFileData File = new ReadFileData();
Properties Values = File.ReadFile();
driver.get(Values.getProperty("URL"));
return PageFactory.initElements(driver, pageobject.SignInPage.class);
}
}
Now the method ClickToLogin is defined under SignInPage class as:
public class SignInPage {
public EmailViewPage ClickToLogin(WebDriver driver, By by) {
WebUtils.Click(driver, by);
return PageFactory.initElements(driver, EmailViewPage.class);
}
}
Which will further be in Webutils
public class WebUtils {
public static void Click(WebDriver driver, By by) {
WebElement Element = driver.findElement(by);
Element.click();
}
}