I am using TestNG with java to execute my scripts.
I have a fixed tab bar with 5 elements fixed for all time once the user logged in to the application.
I am able to execute the script by clicking on the first element from the list, but for the second time when I try to click on another element from the tab bar it is failing continuously. I tried adding explicit waits, but is not helping me either.
Here is a snippet of my code:
afterLogin.java
public class afterLogin {
WebDriver driver;
WebDriverWait wait;
#FindBy(xpath="//*[#id=\"root\"]/div/div[2]/div/div[1]/div[1]/div[3]")
WebElement button1;
#FindBy(xpath = "//*[#id=\"root\"]/div/div[2]/div/div[1]/div[1]/div[2]")
WebElement button2;
public afterLogin(WebDriver driver){
this.driver = driver;
wait = new WebDriverWait(driver,Duration.ofSeconds(300));
}
public void clickButton1() {
wait.until(ExpectedConditions.visibilityOf(button1);
button1.click();
}
public void clickButton2(){
wait.until(ExpectedConditions.visibilityOf(button2));
button2.click();
}
}
testCase1.java
#Test
public void init() throws Exception {
afterLogin obj = PageFactory.initElements(driver, afterLogin.class);
obj.clickButton1();
}
testCase2.java
#Test
public void init() throws Exception {
afterLogin obj = PageFactory.initElements(driver, afterLogin.class);
obj.clickButton2(); /////THIS IS FAILING
}
I was able to solve this by using Thread.sleep(1000). I will try to update my code to use Implicit waits, but this solves the purpose for now.
Related
I have a few que.
public class LoginPage {
private WebDriver driver;
#FindBy(xpath = "//*[#id=\"textfield-1015-inputEl\"]")
private WebElement loginFiled;
#FindBy(xpath = "//*[#id=\"textfield-1017-inputEl\"]")
private WebElement passwordField;
#FindBy(xpath = "//*[#id=\"button-1021-btnIconEl\"]")
private WebElement signButton;
public LoginPage(WebDriver driver) {
this.driver=driver;
}
public void init(){
PageFactory.initElements(driver, this);
}
public void singIntoSystemAsUser(String login,String password) {
try {
Logger logger = Logger.getLogger(LoginPage.class.getName());
logger.log(Level.INFO,"zdes");
loginFiled.sendKeys(login);
passwordField.sendKeys(password);
signButton.click();
}
catch (Exception e){
Logger logger = Logger.getLogger(LoginPage.class.getName());
logger.log(Level.INFO,e.getMessage());
}
}
#BeforeMethod(alwaysRun = true)
public void browserSetup() {
options = new ChromeOptions();
options.setPageLoadStrategy(PageLoadStrategy.NONE);
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(5000,
TimeUnit.MILLISECONDS);
driver.manage().timeouts().pageLoadTimeout(5000,
TimeUnit.MILLISECONDS);
driver.manage().timeouts().setScriptTimeout(5000,
TimeUnit.MILLISECONDS);
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
driver.get("https://junior.webquik.ru/");
loginPage = new LoginPage(driver);
homePage = new HomePage(driver);
}
#Test(description = "Sign into account")
public void signIntoSystem() throws InterruptedException {
loginPage.singIntoSystemAsUser("U0191767","06258");
Assert.assertEquals(driver.getTitle(),"webQUIK 7.6.2");
}
After launch test a got the exception stale element reference: element is not attached to the page document
I have this exception a few weeks ago and i fix this just by add implicitlyWait,but now i added pageObject patter to my project
and its refuse to work,can you guys tell me what the damn hell wrong with program????
Also a tried change something by removing #FindBy from LoginPage class and add WebElemtn .. = driver.findElement instead,
and i got exception whos telling me that he cant find element on page,
but if ш manually go on page,press f12 and try to find this element i will find it.Pls help
When i tried to fix errors i got the new problem, i got the exception whos tells me that my loginPage object is null, i change code a little bit,and a give to this object the memory,but i have exception anyways.
When I use POM class, getting Nullpointer exception. however if I use driver.findelement directly in class, it works correct. Can you please pour in your thougts to fix this?
#Test
public void testFlow() throws InterruptedException {
UtilityClass.setUpPath();
WebDriver driver = new ChromeDriver();
try{
driver.navigate().to("http://demo.guru99.com/payment-gateway/check_credit_balance.php");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.findElement(By.id("card_nmuber")).sendKeys("1234567891234567");
System.out.println(driver.findElement(By.id("card_nmuber")).getAttribute("value"));
HomePage hp = new HomePage(driver);
hp.clickSubmit();
}
finally{
driver.quit();
}
}
public class HomePage {
WebDriver driver;
public HomePage(WebDriver driver){
this.driver = driver;
}
#FindBy(name = "submit")
private WebElement signIn ;
public void clickSubmit() {
signIn.click(); }} }}
Error: java.lang.NullPointerException
Your page object field is not associated with a WebElement. You need to add a constructor that would call
PageFactory.initElements(driver, this)
Your constructor of course has to take WebDriver as an argument
In HomePage class:
By signIn = By.name("submit");
public void clickSubmit() {
driver.findElement(signIn).click(); }}
Found the correct way of using POM without Page factory. This is working code
I am working on PageFactory in Page Object Model and TestNG framework for automation. I am using beforeFindBy method in WebDriverEventListener to listen for the presence of an element. When an element is not present, NoSuchElementException is thrown and I catch the exception using try-catch block. How to stop executing remaining steps in #Test method. I do not want to use try-catch in my #Test method. Any suggestion on changes in my design is most appreciated. Below is my design.
LoginPage
public class LoginPage {
#FindBy(xpath = "//img[#src='/webres_5786257bd7c8a5.72130757/themes/default/images/login/logo.png']")
WebElement loginLogo;
public LoginPage(WebDriver driver, ExtentTest test) {
this.driver = driver;
PageFactory.initElements(driver, this);
this.test = test;
}
public void verifyLoginPageLogo() throws IOException {
Assert.assertTrue(loginLogo.isDisplayed());
test.log(LogStatus.PASS, "Logo is displayed", takeScreenshot(driver, test));
}
}
Listenter
public class CustomListeners extends TestListenerAdapter implements WebDriverEventListener {
//All Implemented Methods
public void beforeFindBy(By by, WebElement element, WebDriver driver) {
try {
driver.findElement(by);
} catch (NoSuchElementException e) {
System.out.println("Element " + by + "not found");
}
}
}
Test class
#Listeners(CustomListeners.class)
public class Test1 extends BaseTestSuite {
LoginPage lp;
TabMenu tm;
#Test(priority = 0, testName = "Verify Login")
public void login() throws Exception {
lp = new LoginPage(driver, test);
tm = new TabMenu(driver, test);
driver.get(Constants.url);
lp.verifyLoginPageLogo(); //Element not present here
lp.setUserName("dmin");
lp.setPassword("admin");
lp.clickLoginBtn();
tm.verifyTabMenu();
tm.isCurrentTab("Dashboard");
}
}
The Login PageObject ideally should not contain assertion code. That code should be in your test class. Also the Extent functionality should also be in the test class and not the PageObject.
There is no need for a testng listener or a webdrivereventlistener. In the PageObject if restructure the verifyLoginPageLogo() method to below -
public boolean isLoginPageLogoDisplayed() throws IOException {
//Write logic to check if element is displayed.
//Return false in case of exception etc
}
In the test class do this -
Assert.assertTrue(lp.isLoginPageLogoDisplayed());
If an ArrertionError is thrown the remaining steps are skipped automatically.
ALso look at creating a BasePageObject which has utility methods for checking presence, displayed, finding elements etc etc. Just extend this.
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();
}
}
I'm trying to test one specific Selenium's Actions class method, which is as below.
public Actions sendKeys(java.lang.CharSequence... keysToSend)
Sends keys to the active element. This differs from calling WebElement.sendKeys(CharSequence...) on the active element.
public class Demo_1 {
private WebDriver driver;
private Actions action;
private String baseUrl;
#Before
public void setUp() throws Exception {
File file = new File("C:\\Users\\ProgramFiles\\firefox.exe");
FirefoxProfile profile = new FirefoxProfile();
FirefoxBinary binary = new FirefoxBinary(file);
driver = new FirefoxDriver(binary, profile);
action = new Actions(driver);
baseUrl = "http://www.mortgagecalculator.org";
}
#Test
public void testUntitled() throws Exception {
driver.get(baseUrl + "/");
driver.findElement(By.name("param[homevalue]")).click();
driver.findElement(By.name("param[homevalue]")).clear();
action.sendKeys("300000");
}
#After
public void tearDown() throws Exception {
//driver.quit();
}
}
I can do this alternatively, but in some cases when there is no WebElement, action.sendKeys can help to send CharSequence without any WebElement as parameter.
Can some come up with similar kind of issue, as the above code is not working :(
Cause its Actions class object so you need to tell the driver the actions you are performing.
action.sendKeys("300000").perform();
Will do the needful.