I am having a problem with my Assertion, or rather with the "time" the assertion is being executed. So, the assertion is working as it should, however, it is going too fast, as it is executing without waiting for the page it should be targeting to load. Which means that the assertion is failing the test.
Having this in mind, I tried searching around how to add a "wait" to the assert to make it wait for the page to load before running, but with no success.
So, would anyone, please be able to help with this, as in how would I code so, that the assert "waits" for the page to load and then executes?
I've tried adding the wait to the header method, i tried adding the wait to the test script, but no success.
public class test1 extends DriverSetup{
//Here we are setting the method to use the homePage
private HomePage homePage = new HomePage(getDriver());
//Here we are setting the method logInPage
private AuthenticationPage authenticationPage = new AuthenticationPage(getDriver());
//Here are setting the method CreateAccountPage
private CreateAccountPage createAccountPage = new CreateAccountPage(getDriver());
//Here we are setting the method to access the Website HomePage with the driver
private void accessWebsiteHomePage (){
getDriver().get("http://automationpractice.com/index.php");
}
#Test
public void CreateAccount() {
accessWebsiteHomePage();
//Log in
homePage.logInBut();
//Authentication page "Create a new account" box
authenticationPage.setCreateAccountEmailAddress(emailGenerator.Email());
authenticationPage.CreateAccountButtonClick();
Assert.assertEquals("CREATE AN ACCOUNT", createAccountPage.HeaderCheckRightPage());
The assert should be targeting the "CREATE AN ACCOUNT" page, but it is targeting the "AUTHENTICATION" page, which comes before it, hence the test fails as the "actual" value being printed is the "AUTHENTICATION" page, not the "CREATE AN ACCOUNT" page.
You need to use an explicit wait. Here is one that will wait for the title to be equal to something:
private ExpectedCondition<Boolean> titleIsEqualTo(final String searchString) {
return driver -> driver.getTitle().equals(searchString);
}
You can make it more reliable by forcing the case of what you want to match like this:
private ExpectedCondition<Boolean> titleIsEqualTo(final String searchString) {
return driver -> driver.getTitle().toLowerCase().equals(searchString.toLowerCase());
}
You would then need to put the following in before your assertion:
WebDriverWait wait = new WebDriverWait(driver, 10, 100);
wait.until(titleIsEqualTo("CREATE AN ACCOUNT"));
I'm making the assumption that by header you mean the page title since you haven't shown the code that collects the header.
*Edit*
A non-lambda version of the above ExpectedCondition is:
private ExpectedCondition<Boolean> titleIsEqualTo(final String searchString) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return driver.getTitle().toLowerCase().equals(searchString.toLowerCase());
}
};
}
Related
So i have create successful test of adding a card to my profile and now i would like ot verify if card was added so i would like to check if "Your card was successfully added" text appeared, however for some kind of a reason the className not located.
This is an iframe however i do enter it to add the card details and submit them, so trying to understand why it cant locate the follow:
Adding card
public void addCard(Card card) {
switchToCardIframe()
.fillInCardNumber(card.getCardNumber())
.fillInCardHolder(card.getCardHolderName())
.fillInExpiryDate(card.getExpiryDate())
.fillInCvv(card.getCvv())
.clickOnToggle()
.clickOnAddButton();
}
This is how i locate the text
#FindBy(css = "payment-state-message")
private WebElement cardAddedIndicator;
Test
#Test
public void shouldSuccessfullyAddCard() {
myCards.addCard(cardData());
assertTrue(myCards.getCardAddedIndicator().isDisplayed());
}
I have also tried to check if another element displayed by escaping the iframe but no luck so any help appreciated
driver.switchTo().defaultContent()
I have also attempted Thread.sleep() for 10 seconds before taking getting the text from the css locater but not luck
Here is the base page where wait initialized
public class BasePage {
public WebDriver driver;
protected Wait wait;
public BasePage(WebDriver driver) {
initializePage(driver);
this.wait = new Wait(driver);
}
final protected void initializePage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(new AjaxElementLocatorFactory(driver, 20), this);
}
}
Your css is wrong, so instead of
#FindBy(css = "payment-state-message")
private WebElement cardAddedIndicator;
try this
#FindBy(css = ".payment-state-message")
private WebElement cardAddedIndicator;
also do not check for visibility by .isDisplay
rather have a text method called on it. Put some delay/wait as well.
String actualMessage = myCards.getCardAddedIndicator().getText();
String expectedMessage = "Your card was successfully added"
then assert these two based on their actual and expected behavior .
Conclusion :
When there is an iframe form and you submit it, it does not mean that its still the same iframe. In my case when I submitted the form then iframe disappeared however in order for for the element to be located I had to perform driver().switch().parentFrame()
FYI: First always check your locators and make sure they are right.
I'm just starting to learn selenium java.
I had this test code, its just basically open google.com page and get its title, and assert the title. my problem is every time I run the test, the Firefox gets called twice. I already search around about the possible issue, tried some of the fix. but nothing works for me.. tried changing "#BeforeTest" to "#BeforeClass" and to "#Before" still the same.
firefox version: 55.0.3
selenium version: 3.5.3
geckodriver : 0.19.0
here's my code:
public class ATest {
public String baseURL = "http://google.com";
public WebDriver driver;
#BeforeTest
public void setBaseURL() {
driver = new FirefoxDriver();
driver.get(baseURL);
}
#Test
public void verifyHomePageTitle() {
setBaseURL();
String expectedTitle = "Google";
String actualTitle = driver.getTitle();
Assert.assertEquals(actualTitle, expectedTitle);
}
}
#BeforeTest executes before tests so You need to remove setBaseURL() from Your test. It will be run before it anyway.
I haven't used Selenium with Java, only with Ruby. But my guess is that #BeforeTest directive makes setBaseURL() to be executed before each test. So here you have your first opened browser. Later when in your actual test what you do is you run setBaseURL() again, which opens second browser.
Remove setBaseURL() from verifyHomePageTitle(), or remove #BeforeTest
get method is called twice hence it loads page twice. Once in #BeforeTest and second in #Test by calling setBaseURL. Remove the setBaseURL from #BeforeTest, move the get method in actual #Test method and you should be fine
Here is what java doc says about get method
void get(java.lang.String url)
Load a new web page in the current browser window.
get
void get(java.lang.String url)
Load a new web page in the current browser window. This is done using an HTTP GET operation, and the method will block until the load is complete. This will follow redirects issued either by the server or as a meta-redirect from within the returned HTML. Should a meta-redirect "rest" for any duration of time, it is best to wait until this timeout is over, since should the underlying page change whilst your test is executing the results of future calls against this interface will be against the freshly loaded page. Synonym for WebDriver.Navigation.to(String).
Parameters: url - The URL to load. It is best to use a fully qualified URL
public class ATest {
public String baseURL = "http://google.com";
public WebDriver driver;
#BeforeTest
public void setBaseURL() {
driver = new FirefoxDriver();
}
#Test
public void verifyHomePageTitle() {
driver.get(baseURL);
String expectedTitle = "Google";
String actualTitle = driver.getTitle();
Assert.assertEquals(actualTitle, expectedTitle);
}
}
Links for reference
Java Doc : http://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/WebDriver.html#get-java.lang.String-
I'm doing some automation bits for work and right now I'm trying to automate a purchase through our storefront that should go to the paypal sandbox and complete the purchase. Everything looks good and I know the general flow works but I'm having trouble finding the webElements when I get to the first PayPal page.
The PayPal side of the flow consists of 2 pages. One to input the login information and another one to confirm the purchase. The second page works perfectly but the first one always gives me "Unable to find element" when I tell it to look for the email/password field and the login button. If make the driver print out the current URL for debugging purposes it correctly prints the payPal URL so it is looking at the right site. I also tried putting a 30 seconds delay to make sure it wasn't a timing issue and I get the same problem.
Here's the class file in question:
public class PayPalLoginPage extends AbstractPaymentPage {
//AbstractPaymentPage extends from AbrstractPageObject
private WebElement email; //Element ID is email
private WebElement password; //Element ID is password
#FindBy(id = "btnLogin")
private WebElement loginButton;
public PayPalLoginPage(WebDriver driver) {
super(driver);
PageFactory.initElements(driver, this);
}
public PayPalPurchaseConfirmationPage login (PayPalInfo payPalInfo) {
email.sendKeys(payPalInfo.getEmail());
password.sendKeys(payPalInfo.getPassword());
loginButton.click();
this.waitForPayPalLoadingCurtainToDisappear();
return new PayPalPurchaseConfirmationPage(this.getDriver());
}
The way I'm calling this class is like this:
case PAYPAL_PURCHASE:
setDriver(new PayPalLoginPage(getDriver()).login(getPaymentMethod()).confirmPayPalPurchase());
break;
So, the flow works perfectly up until it gets to the first payPal page and it just stops saying it can't find any of those 3 elements. If I set it to just wait there and manually fill up the information then it picks right up on the next page and works from them on (finding all the elements on the 2nd payPal page and acting on them).
I get the same behavior if I put the findElement.By line inside the login method and also the same result regardless of whether I'm trying to find them using id, name, xpath or css.
Any idea on what I could be missing?.
You are just defining the email and followings as WebElement but not assigning them to any webelement. See the following:
private WebElement email = driver.findElement(By.id("email_text_box_id"));
private WebElement password = driver.findElement(By.id("password_text_box_id"));
private WebElement loginbutton = driver.findElement(By.id("login_button_id"));
if you want PageObject to assign WebElements then you need to call the initElement inside of a case:
public class PayPalLoginPage extends AbstractPaymentPage {
//AbstractPaymentPage extends from AbrstractPageObject
private WebElement email; //Element ID is email
private WebElement password; //Element ID is password
#FindBy(id = "btnLogin")
private WebElement loginButton;
public PayPalPurchaseConfirmationPage login (PayPalInfo payPalInfo) {
email.sendKeys(payPalInfo.getEmail());
password.sendKeys(payPalInfo.getPassword());
loginButton.click();
this.waitForPayPalLoadingCurtainToDisappear();
return new PayPalPurchaseConfirmationPage(this.getDriver());
}
}
Call the PayPal login function:
public class UsingPayPalLoginPage {
public static void main(String[] args) {
// Create a new instance of a driver
WebDriver driver = new HtmlUnitDriver();
// Create a new instance of the PayPall page
// and initialise any WebElement fields in it.
PayPalLoginPage page = PageFactory.initElements(driver, PayPalLoginPage.class);
// call login of paypal.
page.login(payPalInfo);
}
}
I know there are several threads regarding this topic, but I am not necessarily looking for a solution, but rather an explanation. I work on a very large automation suite that tests a web application via mobile phones using browserstack. My stability is very low.. and it is due to this error getting thrown at me! Occasionally it will work and occasionally it will not.. I can not use Actions because Browserstack does not support that.. WHY does this error exist and has anyone had any success it working around it. I always wait for an object using wait.until(ExpectedConditions), but sometimes this does not work well enough. I cant quite catch it as an exception since it is an Unknown error. Also, our standards do not allow for a Thread.sleep(). Any ideas? Thank you so much
And here is a screen of some code..
You are waiting for a WebElement to be clickable, then again you are finding a list of WebElements and clicking the first element.
This does not guarantee that you are clicking the element you waited for it be clickable.
public void waitAndClickElement(WebElement element) {
driverWait.until(ExpectedConditions.elementToBeClickable(element)).click();
}
In your case,
public void clickImageView() {
driverWait.until(ExpectedConditions.elementToBeClickable(listImageView)).click() ;
}
Element is normally not click able due to following reasons .
Html is loading and client is still receiving updates from server
When Scrolling
It can be due to some object is overlapping target
problem 3 can not be resolved you need to fix your code in this wait i wait for HTML to ready and then verify is it click able or not this has eliminated such exceptions from my code
how ever i made a solution for problem 1 and 2 you can simply use my custom wait before clicking . call this function
public static void waitForElementPresent(final By by, int timeout,WebDriver driver)
After this if you are using browser other then chrome then call Scroll to that object this would fix you problem
Code
public static void waitForElementPresent(final By by, int timeout,WebDriver driver) {
waitForPageLoad(driver);
WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,40).ignoring(StaleElementReferenceException.class);
/* wait.until(new ExpectedCondition<Boolean>(){
#Override
public Boolean apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(by);
return element != null && element.isDisplayed();
}
}); */
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
wait.until(ExpectedConditions.presenceOfElementLocated(by));
wait.until(ExpectedConditions.elementToBeClickable(by));
WebDriverWait wait2 = new WebDriverWait(driver, 40);
wait2.until(ExpectedConditions.elementToBeClickable(by));
}
//wait for page to laod
public static void waitForPageLoad(WebDriver driver) {
ExpectedCondition<Boolean> pageLoadCondition = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(pageLoadCondition);
}
This is due to the speed at which selenium runs. It will try and find elements before the page has loaded, thus resulting in this error.
For the code sample you provided, the .until() returns the WebElement you are waiting for. You can use the code below to click it rather than scraping the page again.
public void clickImageView()
{
driverWait.until(ExpectedConditions.elementToBeClickable(listImageView)).click();
}
I am trying to write a method to verify page title using page objects but I am unable to do it. Could you please help me out how to write a method to verify page title after searching something in the google page.
Here is my 2 classes.
Class 1
public class GoogleSearchPage {
protected WebDriver driver;
#FindBy(name="q")
private WebElement SearchBox;
#FindBy(name="btnG")
private WebElement SearchButton;
public void SearchFor(String SearchTerm)
{
SearchBox.sendKeys(SearchTerm);
SearchButton.click();
}
}
Class2
public class TestSearchResults {
WebDriver driver;
GoogleSearchPage page;
#BeforeClass
public void Launch() throws Exception
{
driver = new FirefoxDriver();
driver.get("http://google.com");
}
#AfterClass
public void Close()
{
driver.quit();
}
#Test
public void ResultPage() {
System.out.println(page);
page=PageFactory.initElements(driver, GoogleSearchPage.class);
page.SearchFor("selenium");
}
}
Could you please help how to verify the title after displaying the Search results
Note: I am using TestNG.
Thanks in Advance,
Shiva Oleti.
Try this:
assertEquals("Your Page Title" , driver.getTitle());
driver.getTitle() - Returns Title of your current page.
You can get & verify title of page using python webdriver. See below codes
driver.title('title name')
assert 'title name' in driver.title('title name')
It will verify the title name. if it is there title name test case pass else through assert error.
Create a constructor in each page object. The constructor:
sets the instance driver value
waits for page load to complete (e.g. loading spinner not visible, jQuery.active == 0, document.readyState == 'complete')
verifies the page title (see other answers)
Issue PageFactory.initElement(driver, this);
Therefore you don't need a separate method to verify title. In each step you will have a new YourPageObjectPage() which checks the title automatically. Think DRY.