Click on a link triggers an operation that creates new element. However, calling driver.findElement(By.id("")) after click returns does not find it.
I have tried the following code to wait for the element to appear.
wait.until(new ExpectedCondition()
{
public Boolean apply(WebDriver webDriver) {
System.out.println("Searching ...");
return webDriver.findElement(By.id("itemType1")) != null;
}
});
But I still can't find it until timeout.
You can maybe use the element.isDisplayed()
Så do it like this:
WebElement jrnrText = driver.findElement(By.id("id"))
if(jrnrText.isDisplayed()){
wait.until(presenceOfElementLocated(BY.id]("id")))
}
Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
return new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator)
}
}
}
Related
I want to extends selenium and implement something like this:
public class IsExistsWebElement extends WebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
And then using it like this (using page factory):
public class HomePage{
#FindBy(class = "button")
private IsExistsWebElement button;
public HomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public boolean isButtonExists() {
return this.button.isExists();
}
}
What is the best way to implement something like this?
If you are looking for custom implementation then you have to create a new framework on top of selenium and have to write your own implementation for most of the things.
For example RemoteWebElementclass implements the WebElement interface. But its not simple to write just below code and have the access as we do for WebElement
e.g. IsExistsWebElement element = driver.findElement(By.id("a"));
class IsExistsWebElement extends RemoteWebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
If you are looking for new framework on top of selenium and can afford the time(may be 3,6,9.. months depends on resources) and cost then happily go for it.
OR
Looking for managing the wait in generic way in page object model then
Create a BasePage class
Initiate explicit wait in constructor
Create wait methods for presence, visibility and so on
Extend this BasePage class in your other page class
e.g
public BasePage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(driver, TIMEOUT, POLLING);
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT), this);
}
public void waitForElementReady(WebElement element) {
try {
wait.until(ExpectedConditions.visibilityOf(element));
} catch (TimeoutException exception) {
System.out.println("Element didn't find in given time");
}
}
I have a code which waits for a time for element to disappear
new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfAllElements(elements));
Which internally calls Selenium's
isInvisible(WebElement element)
and isInvisible is defined as follows
try {
return !element.isDisplayed();
} catch (StaleElementReferenceException ignored) {
// We can assume a stale element isn't displayed.
return true;
}
Note: It only catches StaleElementReferenceException
and in isDispalyed when the element is referenced, pagefactory package's ElementLocator class's findElement is called method which throwsNoSuchElementException
This exception propogates to FluentWait class
Wherein
try {
V value = isTrue.apply(input);
if (value != null && (Boolean.class != value.getClass() || Boolean.TRUE.equals(value))) {
return value;
}
// Clear the last exception; if another retry or timeout exception would
// be caused by a false or null value, the last exception is not the
// cause of the timeout.
lastException = null;
} catch (Throwable e) {
lastException = propagateIfNotIgnored(e);
}
The exception is caught by Throwable, and this causes the timeout and I am not able to check whether all elements have been disappeared from the screen
P.S.
All my Elements are defined by #FindBy
Example
#FindBy(css = ".myclass-name")
private WebElement myWorkspaceButton;
So cannot use ExpectedConditions method taking By as argument
Is there any other way to check if all the WebElements have disappeared from the screen?
Or
Is there a solution to this problem?
You could write you own method for that in which you loop through all you elements and catch those exceptions.
public static ExpectedCondition<Boolean> invisibilityOfAllElements(
final List<WebElement> elements) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
for (WebElement element : elements) {
try {
if (element.isDisplayed()) {
return false;
}
} catch (StaleElementReferenceException | NoSuchElementException ex) {
// ignore
}
}
return true;
}
#Override
public String toString() {
return "invisibility of all elements " + elements;
}
};
}
I am not sure but probably you need to catch org.openqa.selenium.TimeoutException as well.
Selenium's check for visibility/invisibility assumes that elements are present in DOM so the options are in:
Add another Explicit Wait to hold on until all the elements matching the locator query are absent like:
new WebDriverWait(driver,10).until(ExpectedConditions.numberOfElementsToBeLessThan(By.your_locator("your_query"),1));
You can supress the exception by providing the relevant ignoring stanza like:
new WebDriverWait(driver, 10)
.ignoring(NoSuchElementException.class)
.until(ExpectedConditions.invisibilityOfAllElements(elements));
More information:
WebDriver Advanced Usage: Explicit Waits
How to use Selenium to test web applications using AJAX technology
I'm currently trying to revamp my Selenium test cases by implement the Page Object Model in them. However, the website I'm testing deals with a lot of modals. When I try to access certain modals, I get a NullPointerException. I can't tell if the driver isn't waiting for the element or what.
Here are my classes:
Page Object
public class ManualShipmentModal
{
WebDriver driver;
WebDriverWait wait;
#FindBy(id = "manual-order-modal")
WebElement modalBody;
#FindBy(name = "mailToName")
WebElement toName;
/* Constructor */
public ManualShipmentModal(WebDriver driver)
{
this.driver = driver;
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 100);
PageFactory.initElements(factory, this);
}
public boolean modalExists()
{
return modalBody.isDisplayed();
}
public void enterToAddress(String toName, String addressName)
{
wait.until(ExpectedConditions.visibilityOf(modalBody));
WebElement toAddress = driver.findElement(By.linkText(addressName));
this.toName.sendKeys(toName);
toAddress.click();
}
}
Test class
public class TEST_11
{
WebDriver driver;
LoginPage loginPageObj;
HeaderMenu headerMenuObj;
ManualShipmentModal manualShipmentModalObj;
#Before
public void setup()
{
driver = new ChromeDriver();
driver.get("testpage.com");
}
#Test
public void testCreateNewShipment()
{
loginPageObj = new LoginPage(driver);
headerMenuObj = new HeaderMenu(driver);
manualShipmentModalObj = new ManualShipmentModal(driver);
loginPageObj.login("username", "password");
headerMenuObj.createNewShipment();
manualShipmentModalObj.enterToAddress("Test", "The Usual Test");
}
#After
public void teardown()
{
driver.close();
}
}
It runs fine up until I call enterToAddress(). When it gets to that point, it throws a NullPointerException. It seems like the driver isn't waiting for the element to load even though I have an implicit wait defined as well as an explicit wait.
WebDriverWait wait isn't instantiated, so calling it throws a NullPointerException.
Use its constructor in ManualShipmentModal's constructor:
public ManualShipmentModal(WebDriver driver)
{
this.driver = driver;
long timeOutInSeconds = 10; // just an arbitrary value example
this.wait = new WebDriverWait(driver, timeOutInSeconds);
// the rest of your constructor as in the original code
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 100);
PageFactory.initElements(factory, this);
}
I have two classes, one that runs the methods to click on buttons etc. On the page, there is a button that is disabled and I have a WebDriverWait to wait for it to be enabled again by checking that the attribute "disabled" has been removed from the html element. However, when I run the test I get a nullPointerException. I think I know where it's coming from but having a problem trying to work a way around it.
This is the method that runs to get to perform the actions:
public void methodThatRuns(WebDriver driver) throws InterruptedException {
properties.inputTxt(driver, "100");
sundries.waitEnabledButton(driver, properties.nextButton(driver));
properties.nextButton(driver).click();
}
This is the waitEnabledButton method from another class that it calls to wait:
public void waitEnabledButton(WebDriver driver, final WebElement btn) throws NullPointerException {
WebDriverWait wait = new WebDriverWait(driver, 10);
System.out.println("Starting the wait");
try {
wait.until(new ExpectedCondition<Boolean>(){
public Boolean apply(WebDriver driver) {
final String attribute = btn.getAttribute("disabled");
if (attribute.equals(null)) {
return true;
}
else {
return false;
}
}
});
} catch (StaleElementReferenceException e) {
System.out.println("The disabled attribute was destroyed successfully and the script can continue."); //using this as the attribute gets destroyed when the button is enabled which throws a staleElement exception
}
System.out.println("Wait is over");
}
Any help on this would be greatly appreciated!
if (attribute.equals(null)) {
return true;
}`
If attribute is null then .equals call will lead to NPE. Try with attribute == null.
Im trying the code below but it seems it does not work... Can someone show me the best way to do this?
public void verifyThatCommentDeleted(final String text) throws Exception {
new WebDriverWait(driver, 5).until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver input) {
try {
input.findElement(By.xpath(String.format(
Locators.CHECK_TEXT_IN_FIRST_STATUS_BOX, text)));
return false;
} catch (NoSuchElementException e) {
return true;
}
}
});
}
Instead of doing findElement, do findElements and check the length of the returned elements is 0. This is how I'm doing using WebdriverJS and I expect the same will work in Java
i usually couple of methods (in pair) for verification whether element is present or not:
public boolean isElementPresent(By locatorKey) {
try {
driver.findElement(locatorKey);
return true;
} catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
}
public boolean isElementVisible(String cssLocator){
return driver.findElement(By.cssSelector(cssLocator)).isDisplayed();
}
Note that sometimes selenium can find elements in DOM but they can be invisible, consequently selenium will not be able to interact with them. So in this case method checking for visibility helps.
If you want to wait for the element until it appears the best solution i found is to use fluent wait:
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
});
return foo;
};
Hope this helps)
Use findElements instead of findElement.
findElements will return an empty list if no matching elements are found instead of an exception. Also, we can make sure that the element is present or not.
Ex: List elements = driver.findElements(By.yourlocatorstrategy);
if(elements.size()>0){
do this..
} else {
do that..
}
Unable to comment to The Meteor Test Manual, since I have no rep, but I wanted to provide an example that took me quite awhile to figure out:
Assert.assertEquals(0, wd.findElements(By.locator("locator")).size());
This assertion verifies that there are no matching elements in the DOM and returns the value of Zero, so the assertion passes when the element is not present. Also it would fail if it was present.
public boolean isDisplayed(WebElement element) {
try {
return element.isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
}
If you wan t to check that element is displayed on the page your check should be:
if(isDisplayed(yourElement){
...
}
else{
...
}
int i=1;
while (true) {
WebElementdisplay=driver.findElement(By.id("__bar"+i+"-btnGo"));
System.out.println(display);
if (display.isDisplayed()==true)
{
System.out.println("inside if statement"+i);
driver.findElement(By.id("__bar"+i+"-btnGo")).click();
break;
}
else
{
System.out.println("inside else statement"+ i);
i=i+1;
}
}
WebElement element = driver.findElement(locator);
Assert.assertNull(element);
The above assertion will pass if element is not present.
In Python for assertion I use:
assert len(driver.find_elements_by_css_selector("your_css_selector")) == 0
My answer is much more simpler and it works for me
while(true) {
if (driver.getPageSource().contains("Enter the text of the element you wanted to check")==false)
{//Put your code here
break;
}
else if (isElementPresent(element you are trying to find)==true)
{
//put your code here
break;
}
}
WebElement element = driver.findElement(locator);
Assert.assertFalse(element.isDisplayed());
The assertion will pass if the element is not present, otherwise it will fail.