Selenium Webdriver findelement i sendKeys() isn't behaving as expected - java

I am trying to identify elements in Firefox using below xpath and name values in selenium webdriver but it is not working. This is link to the web page which I want to automate. All of the input fields on this page look weird to me and I don't understand how to fill them.
driver.findElement(By.name("sender-postCode")).sendKeys("02791");
driver.findElement(By.xpath(".//*[#id='stepOneForm']/div[2]/div[4]/div[1]/div[1]/div[1]/input")).sendKeys("02791");
This is my code:
package SalesBar;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;
public class Salesbar {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
System.setProperty("webdriver.gecko.driver", "C:/Users/User/Documents/SeleniumWebDriver/geckodriver.exe");
ProfilesIni profil = new ProfilesIni();
FirefoxProfile myprofile = profil.getProfile("default");
WebDriver driver;
driver = new FirefoxDriver(myprofile);
driver.get("https://wwwuat.dpdpickup.pl/Wycen-i-nadaj-Online");
driver.findElement(By.xpath(".//*[#id='contentWrapper']/div/div/div[2]/div[1]/a")).click();
Thread.sleep(3000);
driver.findElement(By.xpath(".//*[#id='stepOneForm']/div[2]/div[3]/span[2]/label/span")).click();
Thread.sleep(3000);
driver.findElement(By.name("parcels-1-weight")).sendKeys("5");
}
Please let me know if there is a standard way in WebDriver to find and fill these fields.

An issue with all test automation tools is that the page may not have finished loading the DOM when the automation tool executes. There are various levels of sophistication that can be employed to get this to be 100% reliable. The first line of defense is to use ExpectedConditions. So for your first example,
WebDriver webDrive = ... // You have to initialize to a browser instance and navigate to your web page
By bySenderPostCode = By.name("sender-postCode");
Wait<WebDriver> wait_element = new WebDriverWait(webDriver, 40); // Wait up to 40 seconds
WebElement senderPostalCodeElement = wait_element.until(ExpectedConditions.visibilityOfElementLocated(bySenderPostCode));
senderPostalCodeElement.sendKeys("02791");
Complex pages with lots of executing JavaScript can be a pain. I use routines that that I have written to wait for angularJs to complete executing, wait for a loading spinner to complete, and finally for page readyState to equal complete:
waitForAngularToLoad(webDriver, 40);
wait_element.until((WebDriver dr1) -> (webDriver.findElement(mySpinner).getAttribute("class").contains("ng-hide")));
waitForBrowserReadystateComplete(webDriver);
These have to be tweaked for the environment that you have to operate in. Waiting for jQuery to complete is different than waiting for AngularJs. But what I gave you should get you going. Let me know how it turns out.
EDIT
I realize that telling you about my routines that I use to wait but not sharing the code was pointless. The loading spinner depends entirely on the implementation. There is no one way that is guaranteed to work everywhere but I gave you the general form which is common for AngularJs implementations.
Here are the others:
public void waitForBrowserReadystateComplete(WebDriver webDriver) {
for (int a=0; a<20; a++) {
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver;
if (javascriptExecutor.executeScript("return document.readyState")
.toString().equals("complete")) {
break;
}
sleepResponsibly(500);
}
}
public void sleepResponsibly(int timeMillisecond){
try{
Thread.sleep(timeMillisecond);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException(ex);
}
}
public boolean waitForAngularToLoad(WebDriver driver, int timeout) {
driver.manage().timeouts().setScriptTimeout(timeout, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver, timeout, 500L);
return wait.until(angularHasFinishedProcessing());
}
public static ExpectedCondition<Boolean> angularHasFinishedProcessing() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
"var el = document.querySelector('html');\n" +
"if (!window.angular) {\n" +
" callback('false')\n" +
"}\n" +
"if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(function(){callback('true')});\n" +
"} else {\n" +
" if (!angular.element(el).injector()) {\n" +
" callback('false')\n" +
" }\n" +
" var browser = angular.element(el).injector().get('$browser');\n" +
" browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
"}";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();
return Boolean.valueOf(isProcessingFinished);
}
};
}
Remember, the angular ones only work if your System Under Test is built using AngularJs.
EDIT 2 Finding elements
I use the google chrome browser to "find" elements. Open your web page under chrome. Right-click on the displayed element. Select Inspect -> Copy -> Copy Selector | Copy Xpath. You can do this under Firefox as well. Chrome is just force of habit.
EDIT3
jQuery
public boolean waitForJquery(WebDriver driver, int timeout) {
return waitFor(driver, "return jQuery.active;", "0", timeout);
}
public boolean waitFor(WebDriver driver, final String javascriptString, final String targetString, int timeout) {
WebDriverWait wait = new WebDriverWait(driver, timeout, 500L);
/*
* If you are curious about what follows see:
\ * http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedCondition.html
*
* We are creating an anonymous class that inherits from ExpectedCondition and then implements interface
* method apply(...)
*/
ExpectedCondition<Boolean> isLoaded = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
String jsReturnedValue = "";
try {
jsReturnedValue = String.valueOf(((JavascriptExecutor)driver).executeScript(javascriptString));
return (jsReturnedValue.equals(targetString));
} catch (Exception e) {
log.info("Looking for: " + javascriptString + ", e.message: " + e.getMessage());
return true; // If Javascript not found then don't wait for it
}
}
}; // Terminates statement started by ExpectedCondition<Boolean> isLoaded = ...
return wait.until(isLoaded);
}
And just to round it out, Ajax
public boolean waitForPrototypeAjax(WebDriver driver, int timeout) {
return waitFor(driver, "return Ajax.activeRequestCount;", "0", timeout);
}

Related

Cucumber-JVM: Parallel execution not exactly parallel

I had coded two features file and each of the features file open different browser URL for example one is open google.com and secnd one open amazon.com but this is not the case.
Bothe browsers open google.com. Moreover, it cannot interact with the browser, any actions coded to the browser is not get executed. Besides this, closing first browser cause second browser has null pointer exception.
Cucumber version 6 I start with AbstractCucumberTesNG inheritance. Then i create Login.Feature and follow by AddProduct.Feature.
The expected behaviour should be one browser open phptravels.net website and another browser open http://sellerceter.lazada.my.
This is not the case with my current situation where it open two browsers with phptravels.net, after cloing one browser it open seller.lazada website.
public class AddProduct {
private WebDriverWait timeWait;
private AddProductPageObject page;
private ChromeDriver driver;
private Logger log = LogManager.getLogger(AddProduct.class);
// ======================================================================
public AddProduct() {
}
#Given("navigate to manage product")
public void navigateToManageProduct() {
log.info("Start Login");
try {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
this.timeWait = new WebDriverWait(driver, 30);
page = PageFactory.initElements(driver, AddProductPageObject.class);
driver.navigate().to("https://sellercenter.lazada.com.my/apps/seller/login");
timeWait.until(ExpectedConditions.visibilityOfElementLocated(page.getLazadaSellerLogo()));
// Input username
driver.findElement(page.getUsername()).click();
driver.findElement(page.getUsername()).clear();
driver.findElement(page.getUsername()).sendKeys("nicholaswkc34#gmail.com");
// Input password
driver.findElement(page.getPassword()).click();
driver.findElement(page.getPassword()).clear();
driver.findElement(page.getPassword()).sendKeys("wlx_+279295");
// Click submit btn
driver.findElement(page.getSignInButton()).click();
//assertThat(page.getPageTitle())
Wait wait = new Wait();
wait.implicitWait(driver, 5);
} catch (Exception e) {
log.error(e);
}
}
}
public class Login_FE {
private WebDriverWait timeWait;
private LoginPageObject page;
private ChromeDriver driver;
private Logger log = LogManager.getLogger(Login_FE.class);
// ======================================================================
public Login_FE() {
}
#Given("Launch the homepage and login")
public void launchTheHomepageAndLogin() {
log.info("Start Login");
try {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
timeWait = new WebDriverWait(driver, 30);
// Instantiate LoginPageObject
page = PageFactory.initElements(driver, LoginPageObject.class);
log.info("Navigate to phptravels homepage");
driver.navigate().to("https://www.phptravels.net/admin");
timeWait.until(ExpectedConditions.visibilityOfElementLocated(page.getPhpLogo()));
Actions inputAct = new Actions(driver);
inputAct.sendKeys("admin#phptravels.com").perform();
driver.findElement(page.getUsername()).sendKeys("admin#phptravels.com");
Wait wait = new Wait();
wait.implicitWait(driver, 3);
}catch(Exception e) {
log.error(e);
}
log.info("Login Successfully");
}
}
Im using the same concept for testing mobile apps. So in order to open 2 browsers and to interact with them separately you have to store the driver while initiating in a threadlocal like below :
private static ThreadLocal<AppiumDriver<MobileElement>> appiumDriver = new ThreadLocal<>();

Extent Report 3 Add Screenshot

I"m trying to build selenium with extent report but i could not get the save screenshot function working because i cannot reference the WebDriver object in the ITestListener class. Below is my sample code:
Test Runner.java:
#Listeners({com.peterwkc.Listener.TestListener.class})
public class ChromeTestManager {
private WebDriverManager webDriverManager = new WebDriverManager();
private WebDriver driver;
private LoginPages loginPages;
private AdminPages adminPages;
#BeforeClass
//#Parameters({"browser"})
public void setupTest(/*String browser*/) throws MalformedURLException {
System.out.println("BeforeMethod is started. " + Thread.currentThread().getId());
// Set & Get ThreadLocal Driver with Browser
webDriverManager.createDriver("chrome");
driver = webDriverManager.getDriver();
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
}
#DataProvider(name = "loginCredentials")
public static Object[][] getLoginCredentials() {
return new Object [][] {{ "Admin123", "admin123" }, {"testUser", "test"}, {"test", "test"}};
}
#Test(groups= {"Login"}, description="Invalid Login", priority = 0, dataProvider = "loginCredentials", invocationCount = 3)
public void login_invalid(String username, String password) {
loginPages.login_invalid(driver, username, password);
}
}
TestListener.java
public class TestListener implements ITestListener {
//Extent Report Declarations
private static ExtentReports extent = ExtentManager.createInstance();
private static ThreadLocal<ExtentTest> test = new ThreadLocal<>();
public TestListener() {
}
#Override
public synchronized void onTestFailure(ITestResult result) {
System.out.println((result.getMethod().getMethodName() + " failed!"));
test.get().fail("Exception Error : \n" + result.getThrowable());
/*String feature = getClass().getName();
String screenShot;
try {
screenShot = CaptureScreenshot.captureScreen(driver, CaptureScreenshot.generateFileName(feature));
test.get().addScreenCaptureFromPath(screenShot);
test.get().log(Status.FAIL, screenShot);
} catch (IOException ex) {
LogManager.logger.log(Level.INFO, "Exception: " + ex.getMessage());
}*/
}
}
Questions:
How to pass the WebDriver object from TestRunner.java to TestListener
class?
How to save screenshot in extent report 3?
Anything wrong with my code?
please help, thanks in advance!
Below are the steps to do this :
1 : Passing WebDriver object to Listener class
First create below method in ChromeTestManager class or at any another location from where you can call it, here suppose that it is present in ChromeTestManager class:
public static ITestContext setContext(ITestContext iTestContext, WebDriver driver) {
iTestContext.setAttribute("driver", driver);
return iTestContext;
}
It will set the driver object to the TestContext.
Now change your #BeforeClass setUp method to accept parameter ITestContext, below is the code :
public class ChromeTestManager {
private WebDriverManager webDriverManager = new WebDriverManager();
private WebDriver driver;
private LoginPages loginPages;
private AdminPages adminPages;
private static ITestContext context; // creating a ITestContext variable
#BeforeClass
//#Parameters({"browser"})
public void setupTest(ITestContext iTestContext) throws MalformedURLException {
System.out.println("BeforeMethod is started. " + Thread.currentThread().getId());
// Set & Get ThreadLocal Driver with Browser
webDriverManager.createDriver("chrome");
driver = webDriverManager.getDriver();
this.context = setContext(iTestContext, driver); // setting the driver into context
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
}
When you run this, it will run smoothly and will not produce an error (If you are thinking that how I will pass ITestcontext context, It is handled internally)
Now the driver has been added as an object to the ITestcontext ;
Now Accessing the driver in Listener :
#Override
public synchronized void onTestFailure(ITestResult result) {
WebDriver driver = (WebDriver) result.getTestContext().getAttribute("driver"); // here we are accessing the driver object that we added in Test class
}
2. Saving ScreenShot in extent report 3 (I am using dependency 3.1.5 in maven)
#Override
public synchronized void onTestFailure(ITestResult result) {
System.out.println("!!!!!!!!!!!!!!!!!!!! Test Failed !!!!!!!!!!!!!!!!!!!!");
WebDriver driver = (WebDriver) result.getTestContext().getAttribute("driver"); // accessing driver here
String feature = getClass().getName();
String screenShot;
try {
screenShot = CaptureScreenshot.captureScreen(driver, CaptureScreenshot.generateFileName(feature));
test.addScreenCaptureFromPath(screenShotPath); // I am assuming that the "screenShot" is fully qualified path with extension e.g "C:\Users\12345\Desktop\sfgfdh.PNG"
} catch (IOException ex) {
LogManager.logger.log(Level.INFO, "Exception: " + ex.getMessage());
}
}
3. Is there anything wrong with your code ?
No
You just need driver in Listener class and while adding screenshot in extent report ,
make sure that the path to screenshot is correct and is fully qualified path with extension.
Please let me know if you face an issue in this.
First of all don't instantiate Your webDriver in #BeforeClass, because this is called only once as annotation say before class, try using interface ITestListener and using beforeInvocation implementation for initialisation of WebDriver.
Second, You can't call PageFactory for all PageObjects at once, how do You think all 3 pages are initialised at once, this should be achieved in constructor for each page object, and when You init you page object (new Login) the elements are initialised as well, so this is not ok:
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
Third I don't see initialisation of ExtentReport test. It should looks something like this:
ExtentTest extentTest = ExtentTestManager.startTest(method.getName(), "");
Here is an example part of code from my implementation of calling screenshot, I'am calling it from afterInvocation, because I'm using concurrent driver initialisation, and so it had to be from here, but also can be achived via onTestFailure implementation:
public synchronized void afterInvocation(IInvokedMethod method, ITestResult testResult){
if (method.isTestMethod() && testResult.getStatus()==2) {
File scrFile = (dataMethod.getAndroidDriver()).getScreenshotAs(OutputType.FILE);
String dest = System.getProperty("user.dir") + "/resources/screenshots/" + dataMethod.getDriver().getSessionId() + ".png";
File destination = new File(dest);
try {
FileUtils.copyFile(scrFile, destination);
dataMethod.setScreenshotPath(destination.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
System.err.println("Path:" + dataMethod.getScreenshotPath());
}
You have to think more about structure,
Hope this helps...

How can I extract the text from a variable with Selenium WebDriver?

If I use "Inspect Element" on FireFox, I see this:
<span class="stock-number-value ng-binding">17109 </span>
When I use driver.getSource(), that 17109 is replaced by "vehicle.attributes.stockNumber".
My main goal is to use the driver to get whatever value is stored by vehicle.attributes.stockNumber, but I can't figure out how to get the contents of that variable using Selenium.
I suspect you are getting the source too early in the process while the angular is not yet ready and the bindings are not yet data-feeded. I'd use a custom wait condition function to wait for the "stock" to have a numeric value:
WebDriverWait wait = new WebDriverWait(webDriver, 510);
WebElement stock = wait.until(waitForStock(By.cssSelector(".stock-number-value")));
System.out.println(stock.getText());
where waitForStock is something along these lines:
public static ExpectedCondition<Boolean> waitForStock(final By locator) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
try {
WebElement elm = driver.findElement(locator);
return elm.getText().trim().matches("[0-9]+");
} catch (NoSuchElementException e) {
return false;
} catch (StaleElementReferenceException e) {
return false;
}
}
#Override
public String toString() {
return "stock is not yet loaded";
}
};
}

I am getting nullpointer exception when I perform click() for the same WebElement which I have performed earlier in my Code

I am getting some good handson on my Java ans Selenium. When I use the same "Input_Search_Box" Webelement to perform click method it throws a nullpointer exception. I have googled and tried few work around like adding Thread, adding Explicit wait but still no clue where i miss. Any suggestion would be greatly appreciated.
Here is my Code:
public class Testclass {
WebElement Input_Search_Box;
WebDriver driver;
#Test
public void openBrowser() throws Exception{
System.setProperty("webdriver.chrome.driver","E:\\Ecilpse\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://en.wikipedia.org/wiki/Main_Page");
driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
driver.manage().window().maximize();
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("window.scrollBy(0,500)");
WebElement Click_Create_Book = driver.findElement(By.xpath(".//*[#id='coll-create_a_book']/a"));
Click_Create_Book.click();
WebElement Start_Book_Creator_Btn = driver.findElement(By.xpath(".//*[#id='mw-content-text']/form/div/div[1]/button"));
Start_Book_Creator_Btn.click();
Input_Search_Box = driver.findElement(By.xpath(".//*[#id='searchInput']"));
Input_Search_Box.click();
Input_Search_Box.sendKeys("Selenium",Keys.ENTER);
for(int i =0;i<=8;i++){
try{
if(driver.findElement(By.xpath(".//*[#id='siteNotice']/div[2]/div[2]/div")).isDisplayed())
break;
}
catch(Exception e){
jse.executeScript("window.scrollBy(0,2500)");
}
}
for(int j=0;j<=5;j++){
if(driver.findElement(By.id("coll-add_article")).isDisplayed()) {
System.out.println("If Executed");
break;
}else
{
WebElement Book_Remove = driver.findElement(By.xpath(".//*[#id='coll-remove_article']"));
Book_Remove.click();
}
}
WebElement Add_This_Book = driver.findElement(By.xpath(".//*[#id='coll-add_article']"));
Add_This_Book.click();
Thread.sleep(3000);
for(int k =0;k<=6;k++){
jse.executeScript("window.scrollBy(0,-2500)");
Thread.sleep(3000);
}
Thread.sleep(4000);
System.out.println("Sctipr on hold for 4k seconds");
//Here is the Nullpointer error occuring
Input_Search_Box.click();
Input_SearchBox.sendKeys("JSCRIPT",Keys.ENTER);
}
}
If the page has changed/reloaded then you need to use find again.
Sometimes on user actions the page can trigger calls that can change the page that can change the state of the page and the current found objects are lost this can results in a stale element exception or null exception.

Selenium webdriver explicit wait

I'm writing some automated tests for using the selenium chrome driver. I trying to write a reusable method that will explicitly wait for elements to appear and then call this method in other classes. Seems pretty straight forward but its not doing what I want it do. Here is the method that I have.
public String waitForElement(String item) {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(
ExpectedConditions.elementToBeClickable(By.id(item)));
return item;
}
Then I call the method and pass it a parameter like this:
waitForElement("new-message-button");
That doesn't seem to become working, can someone give some insight?
You can use Explicit wait or Fluent Wait
Example of Explicit Wait -
WebDriverWait wait = new WebDriverWait(WebDriverRefrence,20);
WebElement aboutMe;
aboutMe= wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("about_me")));
Example of Fluent Wait -
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(20, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement aboutMe= wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("about_me"));
}
});
Check this TUTORIAL for more details.
public static void clickOn(WebDriver driver, WebElement locator, int timeout)
{
new WebDriverWait(driver,timeout).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(locator));
locator.click();
}
Call the above method in the main method then we will get explicitly wait functionality.
Your problem is that you passed String to method parameter:
public String waitForElement(String item) {
You have to pass your WebElement, something like:
public boolean visibilityOfElementWait(WebElement webElement) {
if (webElement != null) {
try {
WebDriverWait wait = new WebDriverWait(Driver.getCurrentDriver(), 20);
wait.until(ExpectedConditions.visibilityOf(wrappedElement));
highlightElement(webElement);
return true;
} catch (Exception e) {
return false;
}
} else
Logger.logError("PageElement " + webElement.getText() + " not exist");
return false;
}
public void highlightElement(WebElement element) {
if (!Config.getProperty(Config.BROWSER).equalsIgnoreCase("ANDROIDHYBRID")) {
String bg = element.getCssValue("backgroundColor");
for (int i = 0; i < 4; i++) {
Driver.getDefault()
.executeScript("arguments[0].style.backgroundColor = 'red'", element);
Driver.getDefault()
.executeScript("arguments[0].style.backgroundColor = '" + bg + "'", element);
}
// String highlightElementScript = "arguments[0].style.backgroundColor = 'red';";
// Driver.getDefault().executeScript(highlightElementScript, element);
}
}
We can develop implicit wait on our own.
Use this code; it should also work the same as implicit wait.
//=== Start of Implicit Wait Statement ===
public void implicit_Wait_ID(String str) throws Exception{
for(int i=0;i<60;i++){
try{
driver.findElement(By.id(str)).isDisplayed();
break;
}catch(Exception e){Thread.sleep(2000);
}
}
}
//=== End of Implicit Wait Statement ===
Use this method by passing the ID value:
public void loginGmail() throws Exception
{
driver.findElement(By.id("Email")).sendKeys("Mail ID");
driver.findElement(By.id("next")).click();
implicit_Wait_ID("Passwd");
driver.findElement(By.id("Passwd")).sendKeys("Pwd value");
driver.findElement(By.id("signIn")).click();
}
If it is Xpath, LinkText, just create one of the above methods for all locator types and reuse it n number of times in your script.
Just use this method.I hope it will work perfectly.
public void waitForElement(String item) {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("item")));
}
Then call the method :
waitForElement("new-message-button");
I wrote an explicit wait for my selenium test in the following manner:
I declared my WebElement to be found with an #FindBy annotation added referencing the Id as follows:
#FindBy(how = How.ID, using = "home")
private WebElement home;
Then my method that waits for an element to load was written as follows:
public WebElement isElementLoaded(WebElement elementToBeLoaded) {
WebDriverWait wait = new WebDriverWait(driver, 15);
WebElement element = wait.until(ExpectedConditions.visibilityOf(elementToBeLoaded));
return element;
}
This allowed me to reference any element I was waiting for by name that I had annotated with a find by, regardless of the #FindBy method used.
I built a package using Selenium and waiting was one of the biggest issues I had. In the end, the methods as you described above wouldn't work. I had to resort to doing a simple implicit wait for any dynamic elements, as described below
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
Code:
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
src
Hope that helps.

Categories

Resources