Selenium WebDriver -- How can I know a certain line has executed successfully? - java

I am testing a web application and my sample test case has three steps:
Enter Username
Enter Password
Click 'Login'
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
driver.findElement(By.id("LoginButton")).click();
I need to generate a report which specifies which steps passed and which failed. Is there some mechanism by which I can know that each of those lines executed successfully? Does Selenium have some kind of inbuilt Activity/Event Listener?

If you want log all basic steps like click, navigate, on find element, etc
I recommend you add some event listener. You can use the class EventFiringWebDriver.
An example:
EventFiringWebDriver events = new EventFiringWebDriver(this._driver);
events.Navigated += new EventHandler<WebDriverNavigationEventArgs>(eventAfterNavigate);
and you can define the event handler as
private void eventAfterNavigate(object sender, WebDriverNavigationEventArgs e)
{
Log("URL visited: " + e.Driver.Url); // Call to your favourite log method
}
You can find more possible event handlers in the Webdriver API reference: http://selenium.googlecode.com/svn/trunk/docs/api/dotnet/html/AllMembers_T_OpenQA_Selenium_Support_Events_EventFiringWebDriver.htm

You may use either Verify or Assert to be sure that something is present or absent on the page. Verify will return you Boolean and continue running while Assert on false will stop you test(s).
In this particular case you may verify that you typed username into element with id=username. So your code could look like this:
driver.findElement(By.id("username")).sendKeys(username); // this will enter username
assertEquals(selenium.getValue("id=username"), username); // this will check that text in your username field is 'username' (also you may use Assert.IsTrue)
As far as I know there is verifyTextPresent in Selenium 2 Webdriver, so you may use this:
try
{
assertEquals(selenium.getValue("id=username"), username); // put message into your log: success
}
catch (Exception)
{
// put message into your log: failed
}
I suggest to verify Button click but waiting for some notification that you logged in: e.g. text "Hello, {username}" might appear, or new element (absent before log in) might appear as well. So if this element is present - you are definitely logged in.

If you want to see if each step is successful, then I put some asserts (depending on your unit testing framework) to verify that the steps succeeded.
For example, to check that the username field actually received input, you could immediately verify that the username field has the text of whatever the username is that was typed in.
Some pseudo code:
IWebElement element = driver.findElement(By.id("username"));
element.sendKeys(username);
assertsEquals(username, element.text);
Likewise, to verify that a click was successful, you could check and assert that an element that is expected on the next page exists, which would then indicate that the login was successful.

If Selenium dose not throw Exception then lines are executed successfully.
But question is how do you define success? I would check site that was loaded after click on LoginButton to be sure that behavior of web application is like you expect.

Related

PhantomJS sending keys to wrong input

I have a Java application with selenium and phantomJS.
I built a test to login to an application. There is a step where I send the username and password keys, like so:
this.usernameField.sendKeys(username);
this.passwordField.sendKeys(password);
The fields are identified by ID.
The test works fine in Chrome, but in PhantomJS, both keys are sent to the username input.
For example: username: John - Password: banana
In Chrome: Username: [John] Password: [banana]
In PhantomJS: Username: [Johnbanana] Password: []
If I put a break point and wait after sending the username but before sending the password, then release it, it results in: "Username: [John] Password: [banana]"
Sometimes I get "[Johnban] [ana]" or "[Johnbana] [na]" and so on.
Is this a known bug? I was using PhantomJS from org.seleniumhq.selenium:selenium-java:3.4.0 just fine, but now I had to update versions to org.seleniumhq.selenium:selenium-java:3.141.59 and include com.codeborne:phantomjsdriver:1.4.4.
How can I fix this without putting "wait" all over the code?
It is not a bug. You may have the same situation even in your Chrome if your page loads faster than the code execution. It seems like it is the case in your PhantomJS.
What you can do is to avoid wait everywhere in your code, wrap the waiting behavior in some class, wait until the element is visible and take the action in your upper layers.
You can use presenceOfElementLocated to check and get the element
public class ElementFinder {
public WebElement find(By locator) {
WebDriverWait wait = new WebDriverWait(driver, timeout);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
return element;
}
}
Then find and call your sendKeys. To avoid casting (you should) WebElement, you can use generics, just wanted to give the idea in the example.
Also, you can have a look for PageObjects by Martin Fowler here. It makes it easy for those kinds of operations like I suggested above wrapping InputElements and its behaviors in some object, also for the rest of the page.
Did you try putting in a loop that checks if the entered value by your script is what you expected? Sometimes this will do the trick.
So, in this particular case, switching the order to "password" first and then "username" fixed the issue.
Just to be clear, the page in question is Jira.

Sendkeys without element selenium java

I'm trying to write a simple java based selenium code where I would load a page, give the desired values to username & password.
Once the page loads username is already focused but I can enter values into username or password
Using MAC - Eclipse
I am new to coding sorry so any help would be greatfully received
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
WebDriver driver = new FirefoxDriver();
driver.get("http://dc1.racbusinessclub.co.uk/login/");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
Thread.sleep(2000);
driver.findElement(By.tagName("body")).sendKeys("rac-dc");
Thread.sleep(2000);
driver.findElement(By.tagName("body")).sendKeys(Keys.TAB);
Thread.sleep(2000);
Below is basic way of doing it.
driver.findElement(By.id("username")).sendKeys(username);
driver.findElement(By.id("password")).sendKeys(password);
pause(3);
WebElement button = driver.findElement(By.tagName("button"));
button.sendKeys(Keys.RETURN);
And once logged-in you can assert the url like below
Assert.assertTrue(driver.getCurrentUrl().endsWith("/yourURL"));
You can get username and password id from the browser by Right click on the page and select Inspect.
Even if the field is already focused, you must specify which element you wish to "send the keys" to. So grab the id of the username field, and then use sendKeys, like so:
driver.findElement(By.id("userNameInputBox")).sendKeys("rac-dc");
Also, worth noting that using Thread.sleep in your scripts is bad practice. If there's something you're waiting for, check for the presence of that element, rather than waiting an arbitrary amount of time.
Edit: Actually, seeing your response above I can see you're trying to interact with an alert popup, which you can do with:
driver.switchTo().alert().sendKeys(yourString);
Alternatively, you can skip that entirely and navigate to the page with your credentials in the URL - remember not to hard-code these:
driver.get("http://username:password#http://dc1.racbusinessclub.co.uk/");

Test whether both username and password fields are empty

#Test
public void loginWithEmptyFields() throws InterruptedException {
driver.findElement(By.linkText("Tu Log In / Register")).click();
driver.findElement(By.name("j_username")).clear();
driver.findElement(By.name("j_username")).sendKeys("");
driver.findElement(By.name("j_password")).clear();
driver.findElement(By.name("j_password")).sendKeys("");
Thread.sleep(1000);
driver.findElement(By.className("loginButtonMain")).click();
Thread.sleep(1000);
}
Assert code should check whether both username and password fields are empty, if the fields are empty the login button is disabled and should get the title the page which is 'Login - Tu Clothing'.
However the below code is not working please help!
boolean actualEmptyLoginButton =
driver.findElement(By.cssSelector(".loginButtonMain")).isEnabled();
Assert.assertTrue(actualEmptyLoginButton, "Login Button is not displayed");
String actualEmptyLoginTitle = driver.getTitle();
Assert.assertEquals("Login | Tu clothing", actualEmptyLoginTitle);
As far as I understand your question, you are using Selenium to verify that the title of your login button has changed, after the fields for username and password are cleared.
It looks like some JavaScript is executed, when the content of the text field is cleared.
So I recommend to use a WebDriver for a real browser (e.g. Firefox). Also avoid Thread.sleep(). Better use an explicit wait for the condition, see more at the Selenium documentation for explicit and implicit waits.

Selenium made a sendKeys for two fields instead of one for some reason

I made a pretty simple selenium test, where I want to open web page, clear field value, start entering text for this field, select first value from the hint drop down.
Web site is aviasales.com (I just found some site with a lot of controls, this is not an advertisement)
I did
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).clear();
and it was working perfectly, I also checked via console that this is the only one object on a page like:
document.getElementById('flights-origin-prepop-whitelabel_en')
So, in next line I'm sending value:
DriverFactory.getDriver().findElement(By.id("flights-origin-prepop-whitelabel_en")).sendKeys("LAX");
but it send LAX value for both "flights-origin-prepop-whitelabel_en" and "flights-destination-prepop-whitelabel_en" for some reason, then i tried
DriverFactory.getDriver().findElement(By.id("//input[#id='flights-destination-prepop-whitelabel_en'][#placeholder='Destination']")).sendKeys(destinationAirport);
but I got the same result:
What could be a reason and how to fix this?
Thank you!
Yep... there's some weird behavior going on there. The site is copying whatever is entered into the first field into the second for reason I don't understand. I gave up trying to understand it and found a way around it.
Whenever I write code that I know I'm going to reuse, I put them into functions. Here's the script code
driver.navigate().to(url);
setOrigin("LAX");
setDestination("DFW");
...and since you are likely to use these repeatedly, the support functions.
public static void setOrigin(String origin)
{
WebElement e = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(origin);
e.sendKeys(Keys.TAB);
}
public static void setDestination(String dest)
{
WebElement e = driver.findElement(By.id("flights-destination-prepop-whitelabel_en"));
e.click();
e.clear();
e.sendKeys(dest);
e.sendKeys(Keys.TAB);
}
You can see the functions but basically I click in the field, clear the text (because usually there's something already in there), send the text, and then press to move out of the field and choose the default (first choice).
The reason of your issue is the ORIGIN and DESTINATION inputbox binded keyboard event which used to supply an autocomplete list according to your typed characters.
The binded keyborad event breaks the normal sendKeys() functionality. I met similar case in my projects and questions on StackOverFlow.
I tried input 'GSO' into DESTINATION by sendKeys('GSO'), but I get 'GGSSOO' on page after the sendKeys() complete.
To resolve your problem, we can't use sendKeys(), we have to use executeScript() to set the value by javascript in backgroud. But executeScript() won't fire keyborad event so you won't get the autocomplete list. So we need find out a way to fire keyborady event after set value by javascript.
Below code snippet worked on chrome when i tested on aviasales.com:
private void inputAirport(WebElement targetEle, String city) {
String script = "arguments[0].value = arguments[1]";
// set value by javascript in background
((JavascriptExecutor) driver).executeScript(script, targetEle, city + "6");
// wait 1s
Thread.sleep(1000);
// press backspace key to delete the last character to fire keyborad event
targetEle.sendKeys(Keys.BACK_SPACE);
// wait 2s to wait autocomplete list pop-up
Thread.sleep(2000);
// choose the first item of autocomplete list
driver.findElement(By.cssSelector("ul.mewtwo-autocomplete-list > li:nth-child(1)")).click();
}
public void inputOrigin(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepop-whitelabel_en"));
return inputAirport(target, city);
}
public void inputDestination(String city) {
WebElement target = driver.findElement(By.id("flights-origin-prepopflights-destination-prepop-whitelabel_en"));
return inputAirport(target, city);
}

Selenium Java handle object(alert dialog) exception without delaying. (unpredictable Java pop-up)

Goal: alert pop up. whether it's shown or not, I want it to continue. if it shows, have to select the checkbox, and hit continue. if not, ignore.
Blocker: if alert shows, it will handle the action and dialog will be closed. but when it's not, selenium hangs there without handling condition when it's not shown.
background: I use UFT before, maybe my logic could be wrong.
the pop up is application alert(not systems), so assumed "switch to(),accept()/dismiss() won't work. and I will add handle alert right after login and within the login method below.
Selenium framework background. : we use selenium maven framework, serenity BDD. object is set at the beginning of the page. and serenity.properties handle the time out default and so on.
Pop up objects (if it appears):
#FindBy(xpath = "//input[#id='notification-ack']")
private WebElement PcoNoticeChbx; //this is a check box, needs to be checked
#FindBy(xpath = "//button[contains(.,'Continue')]")
private WebElement PcoNoticeContinueBtn;//button to close the alert
*Log in method *
public void loginIntoExtApplication(String baseURL, String loginURL, String uId, String pwd, String extAppEnv)throws Exception {
gotoExtLoginPage(baseURL, loginURL);
enterLoginCredential(uId, pwd);
openAt("https://" + extAppEnv + ".programportaltest.hrsa.gov/sdms-
extranet/index.xhtml");
My Approaches:
//1.
if (PcoNoticeChbx!=null) {
PcoNoticeChbx.click();
PcoNoticeContinueBtn.click();
} else {
System.out.println("Dialog didn't display, no need any action");
}
//2. hanged here after login actions.
if(!getDriver().findElements(By.xpath("//*[#id='submit']")).isEmpty()){
PcoNoticeChbx.click();
PcoNoticeContinueBtn.click();
}
else {
System.out.println("Dialog didn't display, no need any action");
}
//3. added to watch doesn't work, it shows pending, below code failed too. I ran my Maven in Junit in debug mode. it used to work fine. but watch elements always show (pending)..
boolean isPresent = getDriver().findElements(By.id("noticebox")).size() >0
System.out.println("the diaolog exist= " + isPresent);
//4. even tried the try-catch method.
try{
PcoNoticeChbx.click();
PcoNoticeContinueBtn.click();
}catch (Exception e){
// Printing logs for my report
Log.error("Report Category button element is not found.");
// After doing my work, now i want to stop my test case
throw(e);
}
return;
}
//5. tried list webelemets:
List temp = webdriver.findElements(org.openqa.selenium.By.id("noticebox"));
if (temp.Count > 0 && temp[0].Displayed) {
// script to execute if element is found
} else {
// continue the test
}
//6. and below
if (!WebDriver.findElements(By.xpath("//*[#id='submit']")).isEmpty()==true);
{
        //handle the dialog
    }
else{
//continue
}
// 7.tried with a boolean value, but it also hangs on here first steps
boolean Nbox = PcoNoticeChbx.isDisplayed(); {
if (Nbox==false)
{
System.out.println("Dialog didn't display, no need any action");
}
else if (Nbox==true) {
PcoNoticeChbx.click() ;
PcoNoticeContinueBtn.click();
}
If this is like the popups that I've dealt with they work like this:
Customer comes to site and the site checks for the existence of a cookie. If that cookie exists, the popup is never launched (ideal state). If that cookie does NOT exist (typical state), after a specified period of time a popup appears.
Customer dismisses the popup and a cookie is created with an expiration time
Once that expiration time passes, the cookie expires and the popup will fire again
You need to do some investigation and find the cookie that is created once the popup is dismissed. Clear your cache, browse to the site, and note all the cookies that exist. Wait for the popup and dismiss it. Now find the cookie that was just created and examine it. This is the cookie you need to create. There are a lot of tutorials on creating cookies. It's pretty straightforward.
Once you learn how to create the cookie, you add it to your script as described below:
Navigate to some page on the domain that you know doesn't exist, e.g. www.domain.com/some404page. We do this because it won't trigger the popup countdown and we need to be on the domain to create the cookie.
Create the cookie
Do your normal test
No more popups.
Solution found for my case.
this maybe very easy. but takes some times for me to research. hopefully it will help you.
after use of many methods, for this javascripts confirmation alert. i have used below method. all of help of .CurrentlyVisible() method. because this one, and i guess only this one will give you result even when the element does not exist or null..
if (element(NoticeContinueBtn).**isCurrentlyVisible**()==true) {
PcoNoticeChbx.click();
PcoNoticeContinueBtn.click();
//else just continue
}

Categories