I am using page object model using page factory selenium using Java
I have page class for example:
`public class Login extends BasePage {
#Findby(css ="Abc")
WebElement ele1;
#Findby(css ="xyz")
WebElement ele2;
#Findby(css ="xyz")
WebElement ele3;
public void verifyVisibilityOfAllElements {
List<Webelements> elementList = new ArrayList<Webelements>;
elementList.add(ele1);
elementList.add(ele2);
elementList.add(ele3);
for(Webelements ele:elementList){
if(ele.isDisplayed){
system.out.println("element is displayed" +ele);
} else {
system.out.println("element is not displayed" +ele);
}
}
}
}`
I want to check if all the elements defined in the page class are displayed on the webpage. I want to perform this on in all my page classes. Looking for reusable generic method which can be written in BasePage and can be reuse in all the other pages.
With the use of WebDriverWait with And operator you can create method like this:
public boolean validateAllTheElementsPresented(WebElement el1, WebElement el2, WebElement el3){
try{
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.and(ExpectedConditions.presenceOfElementLocated(el1),
ExpectedConditions.presenceOfElementLocated(el2),
ExpectedConditions.presenceOfElementLocated(el3)));
return true;
}catch (Exception e){
return false;
}
}
You can so like this below using Java Reflection
Create a Abstract Base Class
package com.af.steps;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.lang.reflect.Field;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.PageFactory;
public abstract class BasePage<T> {
static WebDriver driver;
static {
//just for testing purpose , driver instance should be handled in separate class
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
}
public void base(Class<?> pageClass) throws InstantiationException, IllegalAccessException {
T page = null;
page = (T) PageFactory.initElements(driver, pageClass);
Field[] fields = page.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.getType().equals(WebElement.class)) {
WebElement value = (WebElement) field.get(page);
if (value != null) {
System.out.println(value.isDisplayed());
}
}
}
}
protected abstract void checkDisplayed() throws InstantiationException, IllegalAccessException;
}
Your Page Class should call it like this , I have Tested this On google and works fine
Implement the checkDisplayed and class the base method from Abstract class and pass the Class to it, it will initialize the page suing page factory and check if all webelements are displayed or not
import org.apache.poi.ss.formula.functions.T;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class PageClass extends BasePage<T> {
#FindBy(xpath = "//input[#class=\"gLFyf gsfi\"]")
WebElement ele1;
#FindBy(xpath = "//input[#class=\"gNO89b\"]")
WebElement ele2;
#FindBy(xpath = "//input[#class=\"RNmpXc\"]")
WebElement ele3;
void loadUrl() {
driver.get("https://www.google.com/");
}
public static void main(String[] a) throws IllegalAccessException, InstantiationException {
PageClass pageClass = new PageClass();
pageClass.loadUrl();
pageClass.checkDisplayed();
}
#Override
protected void checkDisplayed()
throws InstantiationException, IllegalAccessException {
base(this.getClass());
}
}
you will an output like below for above example
true
false
false
Related
I'm new to automation, using JAVA with Selenium to do some basic tests on a website. I've stumbled upon a Cookies pop-up.
Seems like the element is not visible on the page when I'm trying to click it(waitForElementToBeVisible is not doing it either).
I've read all the related posts on SO and YT videos on how to bypass this, it doesn't seem to work for me.
package pageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class Login {
private static final String BASE_URL = "https://www.demo.guru99.com/V4/";
private static final By USER_ID = By.name("uid");
private static final By PASSWORD = By.name("password");
private static final By LOGIN_BTN = By.name("btnLogin");
private static final By ACCEPT_PRIVACY = By.xpath("//*[#id=\"save\"]/span[1]/div");;
private WebDriver driver;
public Login(WebDriver driver) {
this.driver = driver;
}
public void navigate() {
driver.get(BASE_URL);
}
public void setUsername(String username) {
driver.findElement(USER_ID).clear();
driver.findElement(USER_ID).sendKeys(username);
}
public void setPassword(String password) {
driver.findElement(PASSWORD).clear();
driver.findElement(PASSWORD).sendKeys(password);
}
public void clickLogin() {
driver.findElement(LOGIN_BTN).click();
}
public void clickAcceptPrivacy() {
driver.findElement(ACCEPT_PRIVACY).click();
}
// public String popupText() {
// String text = driver.findElement(ACCEPT_PRIVACY).getText();
// return text;
// }
//
// public void waitAcceptPrivacy() {
// new WebDriverWait(driver, Duration.ofSeconds(3)).until(ExpectedConditions.elementToBeClickable(ACCEPT_PRIVACY)).click();
// }
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import pageObjects.Login;
import java.util.concurrent.TimeUnit;
public class TestDrive {
private final WebDriver driver = new ChromeDriver();
private final Login login = new Login(driver);
#Before
public void setup() {
//use Chrome driver
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
#After
public void tearDown() {
driver.quit();
}
#Test
public void Test1() throws InterruptedException {
login.navigate();
Thread.sleep(1000);
login.clickAcceptPrivacy();
login.setUsername("mngr473114");
login.setPassword("ajybEvu");
Thread.sleep(2000);
login.clickLogin();
}
}
}
This is the error I'm getting:
org.openqa.selenium.NoSuchElementException: Unable to find element with locator By.xpath: //*[#id="save"]/span[1]/div
Tried different xpaths, css; tried ExpectedConditions.
I'm expecting to close the pop-up by clicking the Accept All button.
Thank you!
I didn't get any popups on this page. But probably this popup contained in 'iframe' block if so, you should switch to 'iframe' at first and only then do some action with element
//Store the web element
WebElement iframe = driver.findElement(By.cssSelector("iframe path"));
//Switch to the frame
driver.switchTo().frame(iframe);
//Now we can click the button
driver.findElement(ACCEPT_PRIVACY).click();
Check this out https://www.selenium.dev/documentation/webdriver/interactions/frames/
You could try is to use an explicit wait to wait for the element to be present before interacting with it. You can use the ExpectedConditions class to wait for the element to be visible and clickable before interacting with it.
public void clickAcceptPrivacy() {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement acceptPrivacy = wait.until(ExpectedConditions.elementToBeClickable(ACCEPT_PRIVACY));
acceptPrivacy.click();
}
I am trying to pass the webElement name to another class for Webdriver operations.I am using the pagefactory model.
I want to print the name of the webelement variable as well in another class.
The below is the code I have.
Class A:
Class A{
#FindBy(how = How.XPATH, using = "//div[text()='Example_23']")
public WebElement exampleTab;
}
Class B:
class B{
public static void Click(WebElement objName) throws Exception
{
objName.click();
System.out.println("Clicked on"+ objName);
}
}
Desired Output:
Clicked on exampleTab
Actual Output:
Clicked on com.sun.proxy.$Proxy14
You can do that using below code :
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
class A {
public WebDriver driver;
#FindBy(how = How.XPATH, using = "//div[text()='Example_23']")
public WebElement exampleTab;
public void initElements(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
}
public class B {
public static void main(String r[]) {
A a = new A();
System.setProperty("webdriver.chrome.driver",
"D:\\ECLIPSE-WORKSPACE\\playground\\src\\main\\resources\\chromedriver-2.35.exe");
WebDriver driver = new ChromeDriver();
a.initElements(driver); // instantiating class A elements
driver.navigate().to("url");
driver.manage().window().maximize();
Click(a.exampleTab);
}
public static void Click(WebElement objName) throws Exception {
objName.click();
System.out.println("Clicked on" + objName);
}
}
I'm trying to automate prestashop test cases by Selenium WebDriver. Am I doing it correct, especially with page object model?
This is my HomePagePOM class:
package pageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.Alert;
public class HomePagePOM {
private static WebElement element = null;
private static WebDriver driver = null;
public static String correctLogin = "aaaa";
public static void enterPage(WebDriver driver) {
driver.get("http://website.com");
}
public static WebElement homeLogo(WebDriver driver) {
element = driver.findElement(By.id("header_logo"));
return element;
}
public static WebElement searchBar(WebDriver driver) {
element = driver.findElement(By.id("search_query_top"));
return element;
}
public static WebElement searchBarButton(WebDriver driver) {
element = driver.findElement(By.name("submit_search"));
return element;
}
public static WebElement contactUs(WebDriver driver) {
element = driver.findElement(By.id("contact-link"));
return element;
}
public static WebElement signIn(WebDriver driver) {
element = driver.findElement(By.className("header_user_info"));
return element;
}
}
This is my LoginPagePOM class:
package pageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class LoginPagePOM {
private static WebElement element = null;
private static WebDriver driver = null;
public static String correctLogin = "client";
public static String incorrectLogin = "client_incorrect";
public static String correctPassword = "pass_correct";
public static String incorrectPassword = "pass_incorrect";
public static WebElement createAccountField(WebDriver driver) {
element = driver.findElement(By.id("email_create"));
return element;
}
public static WebElement registeredEmailField(WebDriver driver) {
element = driver.findElement(By.id("email"));
return element;
}
public static WebElement registeredPasswordField(WebDriver driver) {
element = driver.findElement(By.id("passwd"));
return element;
}
public static WebElement registeredSubmitButton(WebDriver driver) {
element = driver.findElement(By.id("SubmitLogin"));
return element;
}
public static WebElement createAccountButton(WebDriver driver) {
element = driver.findElement(By.id("SubmitCreate"));
return element;
}
}
And this is my LoginPageCorrectLogin class, which execute one single test case - correct login to the prestashop website:
package testCases;
import pageObjects.HomePagePOM;
import pageObjects.LoginPagePOM;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class LoginPageCorrectLogin {
public static WebDriver driver = null;
public static WebElement element = null;
public static void main(String[] args) {
driver = new FirefoxDriver();
HomePagePOM.enterPage(driver); //Enter home site
HomePagePOM.signIn(driver).click(); //Find Sign In option and click
LoginPagePOM.registeredEmailField(driver).sendKeys(LoginPagePOM.correctLogin); // Input correct login to field
LoginPagePOM.registeredPasswordField(driver).sendKeys(LoginPagePOM.correctPassword); //Input correct password to field
LoginPagePOM.registeredSubmitButton(driver).click(); // Click on submit button
}
}
I'm begginer at Selenium, but I want to using best practises. Is it correct? For this example I will create other classes like LoginPageCorrectPassword, LoginPageIncorrectLogin and LoginPageIncorrectPassword.
Any advice about page model object will be very helpful.
As this is an open ended question, here are some general pointers:
You probably won't want multiple pages for correct password,
incorrect password, etc as those most likely really aren't different
pages.
Move your strings, like URL and usernames/passwords to a
string-table/resource-file/config-file/something. Having them set
in the code means you are forced to edit code if, for instance, a
password changes; there are many other negatives as well.
Make general actions into your Page object. Simple example:
LoginPagePOM.login(username, password, isValidLogin) This way you won't have the login code repeated everywhere, it is easier to understand, and you'll only have to change 1 spot if/when your login page chan
When you write your objects, encapsulate all the elements as much as you can so that the methods are not tied to accessing the raw elements. They should be more of an action.
Here's what I came up from looking at your code above.
First, I created a browser object to deal with browser related actions. Browser specific actions are things like maximize, resize, clear cookies, etc.
public class Browser {
public static Browser newBrowser(WebDriver driver) {
return new Browser(driver);
}
private final WebDriver driver;
private Browser(WebDriver driver) {
this.driver = driver;
}
public HomePage gotoHomePage() {
driver.get("http://website.com");
return new HomePage(driver);
}
}
Here's a simpler version of Homepage. Your method should describe an action. It's easier to read that way.
public class HomePage {
private final WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
}
public LoginPage signIn() {
driver.findElement(By.className("header_user_info")).click();
return new LoginPage(driver);
}
}
Next is the login page. If you do notice, I have two versions of login method, for success and for failures. Maybe it's just me but when I do automation, I already know what the outcome of the action and all I'm doing is translating that to be automated. So, login with failure might go to a different page and successful login might go to a different page. Well, we need to deal with them on both cases so that our objects won't break. The most important thing to remember is that conditionals (if-else) should be minimized in your test cases.
public class LoginPage {
public static String correctLogin = "client";
public static String incorrectLogin = "client_incorrect";
public static String correctPassword = "pass_correct";
public static String incorrectPassword = "pass_incorrect";
private final WebDriver driver;
public LoginPage(WebDriver driver) {
super();
this.driver = driver;
}
public FailurePage registerAndFail(String email, String password) {
driver.findElement(By.id("email")).sendKeys(email);
driver.findElement(By.id("passwd")).sendKeys(password);
driver.findElement(By.id("SubmitLogin")).submit();
return new FailurePage(driver);
}
public SuccessPage registerAndSucceed(String email, String password) {
driver.findElement(By.id("email")).sendKeys(email);
driver.findElement(By.id("passwd")).sendKeys(password);
driver.findElement(By.id("SubmitLogin")).submit();
return new SuccessPage(driver);
}
}
And here's how you will write the test.
public class LoginPageCorrectLogin {
public static void main(String[] args) {
Browser browser = Browser.newBrowser(new FirefoxDriver());
HomePage homepage = browser.gotoHomePage();
// assertions here
LoginPage loginPage = homepage.signIn();
//assertions here
SuccessPage sucessPage = loginPage.registerAndSucceed(LoginPage.correctLogin, LoginPage.correctPassword);
// assertions here
}
}
I'm building an automation project using Selenium, Java, Cucumber..
I have 3 different classes at this time running the automation code
- Container Class: storing all the WebElements as single methods
- View Class: where all the logic hapens. exp: Performing clicks to the Webelement stored in the container class.
-Steps Class: Where I assert or verify the different pieces of a scenario
My problem is I'm not finding the webelements in the webside when I call the container methods from my view class...
I know the path are OK because if I build the entire scenario in the step class all WebElements are located without issues
I know the view class is excuting the container class because I set a prinln in the container method and is showing up every time the view class attempt to find the WebElement.
Container Class
package com.automation.automation.prototype.containers;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class loginContainer {
private WebDriver driver;
public loginContainer(WebDriver driver) {
this.driver = driver;
}
public WebElement loginEmail(){
//xpath that is not beign located
return driver.findElement(By.xpath("//*[#id='email']"));
}
}
View Class
package com.automation.automation.prototype.views;
import com.automation.automation.prototype.containers.loginContainer;
import org.openqa.selenium.WebDriver;
import com.automation.automation.prototype.containers.loginContainer;
public class loginView {
private static loginContainer login;
public loginView(WebDriver driver) {
login = new loginContainer(driver);
}
public boolean insertEmail( String email) throws InterruptedException{
boolean valid = false;
int flag = 0;
int attemps = 0;
do{
attemps++;
try{
login.loginEmail().click();
login.loginEmail().sendKeys(email);
System.out.println("Element Found!: "+attemps);
valid = true;
flag = 1;
}
catch(Exception e){
Thread.sleep(1000);
System.out.println("Element Searching: "+attemps);
}
}while (attemps <20 && flag ==0);
return valid;}
}
Step Class
package com.automation.automation.prototype;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import static org.junit.Assert.assertTrue;
import com.automation.automation.prototype.containers.URLs;
import com.automation.automation.prototype.containers.loginContainer;
import com.automation.automation.prototype.views.loginView;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class steps {
private WebDriver driver;
private static URLs URL;
private static loginView LoginView2;
//private static loginContainer LoginContainerstep;
public steps(){
URL = new URLs(driver);
//LoginContainerstep = new loginContainer(driver);
LoginView2 = new loginView(driver);
}
#Given(value = "^Launch$")
public void login() throws Throwable{
driver = new FirefoxDriver();
driver.get(URL.fbURL);
System.out.println(URL.fbURL);
}
#Then(value = "^insertCredentials (.*)$")
public void insertCredentials_and_and(String email) throws InterruptedException{
assertTrue("ELEMENT IS NOT SHOWING UP", LoginView2.insertEmail(email));
}
Try to minimize the code. Better to make a common class where you can put login, setup and teardown function, and use the main class (containing main logics and calling the function required from common). Secondly, try to take care for access modifiers. Thirdly, try to check the different types XPATH can be defined. Hope it will help.
Try to use this : instead of a retry
public WebElement findElementSafe(By selector, long timeOutInSeconds) {
try {
return findElement(selector, timeOutInSeconds);
} catch (TimeoutException e) {
return null;
}
}
public WebElement findElement(By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.presenceOfElementLocated(selector));
return findElement(driver, selector);
}
public void waitForElementToAppear(By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(getDriver(), timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
}
public void waitForElementToDisappear(By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(getDriver(), timeOutInSeconds);
wait.until(ExpectedConditions.invisibilityOfElementLocated(selector));
}
When I start a test, 3-4 drivers will spawn, but only one of them will actually run the test. I do not want more than one driver spinning up. I'm using intellij, and a maven project. I'm using cucumber-jvm on top of selenium. I feel like I'm missing something simple, but I'm not able to pin point the problem area.
Versions:
Selenium 2.42.2
Cucumber-junit 1.1.5
Chromedriver 2.42.2
Test runner code:
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#Cucumber.Options(
features = "automation/src/main/resources/applicationLogin.feature",
format = {"pretty", "html:target/cucumber", "json:target/cucmber.json"})
public class ApplicationLoginTest {
}
Gherkin script:
Feature: Application login
As a user
I want to login to the application
So I can see the dashboard
Scenario: Login to the application
Given I am on the page "product URL"
And I enter "username" into the username field
And I enter the "password" into the password field
And I click the "submit" button
And I accept the "User Agreement"
Then I should be on the "dashboard" page
Stepdefs:
package stepdefs;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import objectmaps.LoginMap;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import static com.thoughtworks.selenium.SeleneseTestBase.assertTrue;
public class ApplicationLoginStepDefs {
protected WebDriver driver;
protected LoginMap loginMap;
#Given("^I am on the page \"([^\"]*)\"$")
public void I_am_on_the_page(String page) throws Throwable {
driver = new ChromeDriver();
driver.manage().window().maximize();
loginMap = PageFactory.initElements(driver, LoginMap.class);
driver.get(page);
}
#And("^I enter \"([^\"]*)\" into the username field$")
public void I_enter_into_the_username_field(String arg1) throws Throwable {
loginMap.getUsernameField().sendKeys("automation");
}
#And("^I enter the \"([^\"]*)\" into the password field$")
public void I_enter_the_into_the_password_field(String arg1) throws Throwable {
loginMap.getPasswordField().sendKeys("a");
}
#And("^I click the \"([^\"]*)\" button$")
public void I_click_the_button(String arg1) throws Throwable {
loginMap.getLoginButton().submit();
}
#And("^I accept the \"([^\"]*)\"$")
public void I_accept_the(String arg1) throws Throwable {
Thread.sleep(2000);
loginMap.getBetaUserTermsAgree().click();
}
#Then("^I should be on the \"([^\"]*)\" page$")
public void I_should_be_on_the_page(String text) throws Throwable {
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("ng-binding")));
assertTrue(driver.getCurrentUrl().contains(text));
driver.quit();
}
}
Page object abstraction layer:
package objectmaps;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class LoginMap {
protected String hawkeyeLoginPage = "product URL";
#FindBy(id = "hk-login-username")
private WebElement usernameField;
#FindBy(id = "hk-login-password")
private WebElement passwordField;
#FindBy(xpath = "//button[contains(text(),'Agree')]")
private WebElement betaUserTermsAgree;
#FindBy(xpath = "//button[contains(text(),'Cancel')]")
private WebElement betaUserTermsCancel;
public WebElement getUsernameField() {
return usernameField;
}
public WebElement getPasswordField() {
return passwordField;
}
public WebElement getBetaUserTermsAgree() {
return betaUserTermsAgree;
}
public WebElement getBetaUserTermsCancel() {
return betaUserTermsCancel;
}
public WebElement getLoginButton() {
WebElement element = getUsernameField();
return element;
}
public void loginToHawkeye() throws Exception{
usernameField.sendKeys("automation");
passwordField.sendKeys("a");
getLoginButton().submit();
Thread.sleep(2000);
}
public void acceptUserAgreement() throws Exception{
Thread.sleep(2000);
getBetaUserTermsAgree().click();
}
public String getHawkeyeLoginPage() {
return hawkeyeLoginPage;
}
}
#Before
public void setUp() {
driver = new ChromeDriver();
driver.manage().window().maximize();
loginMap = PageFactory.initElements(driver, LoginMap.class);
}
#Before will run before each test method, so a new driver will be created each time.
You may want to try out #BeforeClass
I figured it out, and it maybe what you were saying Arran but I found my issue to be with classes and not necessarily methods. I have several step definition classes (many methods within each class), and when you execute one cucumber-jvm test, it appears that cucumber-jvm will load all of those step definition classes, and if there are before and after annotations within said classes, they will execute. And in my case, I had it set up to where the before would spin up a WebDriver instance. I moved the functionality from the before methods and into the various steps within my step definition classes