I am writing a code that enters the username and password into a URL and submits that page. but I keep getting this error
"Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException:
Unable to locate element: {"method":"name","selector":"username"}"
Below is the code
package org.openqa.selenium.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class LoginPage {
private final WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
// Check that we're on the right page.
if (!"Outreach Configuration".equals(driver.getTitle())) {
// Alternatively, we could navigate to the login page, perhaps logging out first
throw new IllegalStateException("This is not the login page");
}
}
// The login page contains several HTML elements that will be represented as WebElements.
// The locators for these elements should only be defined once.
// By usernameLocator = By.name("username");
// By passwordLocator = By.name("password");
// By loginButtonLocator = By.name("submit");
// The login page allows the user to type their username into the username field
public LoginPage typeUsername(String username) {
// This is the only place that "knows" how to enter a username
driver.findElement(By.name("username")).sendKeys(username);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
// The login page allows the user to type their password into the password field
public LoginPage typePassword(String password) {
// This is the only place that "knows" how to enter a password
//driver.findElement(passwordLocator).sendKeys(password);
driver.findElement(By.name("password")).sendKeys(password);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
// The login page allows the user to submit the login form
public HomePage submitLogin() {
// This is the only place that submits the login form and expects the destination to be the home page.
// A seperate method should be created for the instance of clicking login whilst expecting a login failure.
// driver.findElement(By.name("submit")).submit();
// Return a new page object representing the destination. Should the login page ever
// go somewhere else (for example, a legal disclaimer) then changing the method signature
// for this method will mean that all tests that rely on this behaviour won't compile.
return new HomePage(driver);
}
// The login page allows the user to submit the login form knowing that an invalid username and / or password were entered
public LoginPage submitLoginExpectingFailure() {
// This is the only place that submits the login form and expects the destination to be the login page due to login failure.
// driver.findElement(By.name("submit")).submit();
// Return a new page object representing the destination. Should the user ever be navigated to the home page after submiting a login with credentials
// expected to fail login, the script will fail when it attempts to instantiate the LoginPage PageObject.
return new LoginPage(driver);
}
// Conceptually, the login page offers the user the service of being able to "log into"
// the application using a user name and password.
public HomePage loginAs(String username, String password) {
// The PageObject methods that enter username, password & submit login have already defined and should not be repeated here.
typeUsername(username);
typePassword(password);
return submitLogin();
}
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
// And now use this to visit Google
driver.get("URL Goes Here");
LoginPage login = new LoginPage(driver);
HomePage a=login.loginAs("username","Password");
}
}
I reffered it from http://code.google.com/p/selenium/wiki/PageObjects
Try to add
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
before HomePage a=login.loginAs("username","Password");.
It is not quite good approach, but it will help to find out where is the problem. This is just a pause before next step. You shouldn't use it in future, because it is not pretty good practice. It is better to use wait for condition check this out for more information.
Related
I have two feature files in Cucumber that are linked to corresponding step files. The problem is that when one of the step file finishes execution then it closes all the browser windows (because of driver.quit()) whereby killing the execution of other step file which hasn't done processing yet.
Here each step file opens a new browser window, executes the tests within it and then closes and quits the browser. Currently I have just two step files but in the future there are going to be many more.
Is there anything in Cucumber that would always get executed after all the steps are executed?
How do I solve this problem?
HelpStep.java
#Ignore
public class HelpStep {
private WebDriver driver;
#Before
public void setup() {
System.out.println("Into the setup method of HelpStep...");
this.driver = BrowserConfig.getIEWebDriver();
}
#Given("^The user is on the Help page$")
public void onPage() {
System.out.println("The user is on the Help page");
}
#When("^The user clicks on the links within the Help page$")
public void clickLinks() {
System.out.println("The user clicks on the links within the Help page");
}
#Then("^The user is navigated to that section$")
public void validate() {
System.out.println("The user is navigated to that section");
}
#After
public void cleanUp() {
System.out.println("Into the cleanUp method of HelpStep...");
//FOLLOWING METHOD CALL KILLS ALL THE OPEN BROWSERS ALSO :(
BrowserConfig.releaseResources(this.driver);
}
}
LinkStatsStep.java
#Ignore
public class LinkStatsStep {
private WebDriver driver;
#Before
public void setup() {
System.out.println("Into the setup method of LinkStatsStep...");
this.driver = BrowserConfig.getIEWebDriver();
}
#Given("^The user is on the Link Statistics page$")
public void onPage() {
System.out.println("The user is on the Link Statistics page");
}
#When("^The user does a search$")
public void clickLinks() {
System.out.println("The user does a search");
}
#Then("^The user is displayed search result$")
public void validate() {
System.out.println("The user is displayed search result");
}
#After
public void cleanUp() {
System.out.println("Into the cleanUp method of LinkStatsStep...");
BrowserConfig.releaseResources(this.driver);
}
}
TestRunner.java
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty", "json:target/cucumber-reports/cucumber.json"},
features = {"src/test/resources/features"})
public class TestRunner extends ApplicationTests {
}
BrowserConfig.java
public class BrowserConfig {
private static final String IE_DRIVER_EXE = "drivers/IEDriverServer.exe";
private static final String WEBDRIVER_IE_DRIVER = "webdriver.ie.driver";
private static final String BASE_URL = "https://www.google.com";
public static WebDriver getIEWebDriver() {
String filePath = ClassLoader.getSystemClassLoader().getResource(IE_DRIVER_EXE).getFile();
System.setProperty(WEBDRIVER_IE_DRIVER, filePath);
InternetExplorerOptions options = new InternetExplorerOptions().requireWindowFocus();
options.setCapability(INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
options.setCapability(ENABLE_ELEMENT_CACHE_CLEANUP, true);
options.setCapability(IE_ENSURE_CLEAN_SESSION, true);
options.setCapability(ACCEPT_SSL_CERTS, true);
options.setCapability("nativeEvents", false);
options.setCapability(INITIAL_BROWSER_URL, BASE_URL);
System.out.println("Initializing IE Driver now...........");
WebDriver driver = new InternetExplorerDriver(options);
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
return driver;
}
public static void releaseResources(WebDriver driver) {
System.out.println("Releasing resources now.....");
if (null != driver) {
driver.close();
driver.quit(); //CLOSES ALL THE OPEN BROWSER SESSIONS LEAVING OTHER STEP EXECUTIONS INCOMPLETE
}
}
}
help.feature
Feature: Check that the user is able to navigate to Help page
Scenario:
Given The user is on the Help page
When The user clicks on the links within the Help page
Then The user is navigated to that section
link-stats.feature
Feature: Check that the user is able to navigate to Link Statistics page
Scenario:
Given The user is on the Link Statistics page
When The user does a search
Then The user is displayed search result
System.outs
Initializing IE Driver now...........
Listening on port 47613
Into the setup method of LinkStatsStep...
Initializing IE Driver now...........
Listening on port 5009
The user is on the Help page
The user clicks on the links within the Help page
The user is navigated to that section
Into the cleanUp method of HelpStep...
Releasing resources now.....
Into the cleanUp method of LinkStatsStep...
Releasing resources now.....
Into the setup method of HelpStep...
Initializing IE Driver now...........
Listening on port 17291
Into the setup method of LinkStatsStep...
Initializing IE Driver now...........
Listening on port 23793
The user is on the Link Statistics page
The user does a search
The user is displayed search result
Into the cleanUp method of HelpStep...
Releasing resources now.....
Into the cleanUp method of LinkStatsStep...
Releasing resources now.....
Looking at your code it would appear to be correct.
Calling quit should close all open windows associated with that webdriver session. It should not close windows of other webdriver sessions. So I think you are facing a problem in the IEDriverServer.
If this is the case and if you are running your tests in a JVM that shuts down after all tests have been executed. Then as a work around you can use shut down hooks to call quite and close all web driver sessions. For example:
private static final Thread CLOSE_THREAD = new Thread() {
#Override
public void run() {
// Start a new webdriver to call quit on
// For IE this will terminate all webdriver sessions
getIEWebDriver().quit();
}
};
static {
Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
}
Posted the answer here as this question is more or less similar earlier one.
https://stackoverflow.com/a/55836832/2325154
It is because driver management not done properly. I would suggest to use qaf which does driver and resource management. With QAF your step file will look like below:
public class HelpStep {
//setup or tear-down not required here...
#Given("^The user is on the Help page$")
public void onPage() {
//you can access driver any where like below:
//WebDriver driver = new WebDriverTestBase().getDriver();
System.out.println("The user is on the Help page");
}
#When("^The user clicks on the links within the Help page$")
public void clickLinks() {
System.out.println("The user clicks on the links within the Help page");
}
#Then("^The user is navigated to that section$")
public void validate() {
System.out.println("The user is navigated to that section");
}
}
To access driver object any where in the code you can get it from test base.
WebDriver driver = new WebDriverTestBase().getDriver();
Below are examples of interacting with element anywhere in the code:
Using findBy
driver.findElement("name=q").click();
Using element factory
import static com.qmetry.qaf.automation.ui.webdriver.ElementFactory.$;
...
$("name=q").click();
Using inbuilt step library
import static com.qmetry.qaf.automation.step.CommonStep.*;
...
click("name=q");
in example above name=q is element locator using name as locator strategy, which will automatically converted to By.name.
LinkStatsStep
import static com.qmetry.qaf.automation.step.CommonStep.*;
...
public class LinkStatsStep {
#Given("^The user is on the Link Statistics page$")
public void onPage() {
get("/");
}
#When("^The user does a search$")
public void clickLinks() {
System.out.println("The user does a search");
click("elementlocator");
//$("elementlocator").click();
}
#Then("^The user is displayed search result$")
public void validate() {
verifyLinkWithPartialTextPresent("link text");
//$("partialLink=link text").verifyPresent();
}
}
Your gherkin file will remain same. To run your gherkin file use GherkinScenarioFactory
You can specify browser to use using driver.name property. You don't need to write code for creating or tearing down driver. You can set behavior of driver session by using selenium.singletone property.
#this will tear down driver after each testcase/scenario
selenium.singletone=method
#this will tear down driver after each xml test node in configuration file
selenium.singletone=test
#this will tear down driver after each xml test node in configuration file and will reuse same driver session for testcases/scenario configured under same xml test node.
selenium.singletone=test
#this will tear down driver after each xml suite node in configuration file.
selenium.singletone=suite
I am having some troubles with splitting the business logic from a single controller into different controllers.
Problem:
At the beginning of my application,i ask user for username and password to perform login.After that,and if the login succeeds,i want to show to the user the main scene which includes some basic operation my app can do.The problem is : to perform any basic operation(for example,find groups the user belongs to) i need to know the username the user used when he logged in.At first, i made a single controller and passed to it the username from the login scene.Here is the login method from the login controller:
private void login(){
boolean loginResult = false;
try {
//Returns True if the user can login with the given username and password
loginResult = userRemote.login(username_field.getText(), password_field.getText());
if (!loginResult) {
Alert alert = new Alert(Alert.AlertType.ERROR, "The username and/or password are incorrect");
alert.showAndWait();
} else {
loadMain();
}
} catch (RemoteException e) {
e.printStackTrace();
Alert alert = new Alert(Alert.AlertType.ERROR, "Unable to connect to the server.Please try again later");
alert.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
}
If the login succeeds,i load the main scene passing it the username.Here is the code:
FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/fxml/main.fxml"));
Parent root = loader.load();
Controller controller = loader.getController();
controller.init(username_field.getText());
Stage stage = (Stage) ( (Node) (sign_in_btn) ).getScene().getWindow();
Scene scene = new Scene(root);
scene.getStylesheets().add("/gui/view/css/style.css");
stage.setScene(scene);
In the Controller i save the username in a field,here is the init method that is called :
void init(String username) throws IOException {
this.username = username;
//some other code
}
After that i have the username in the my Controller of the main Scene,but the problem is that because of so many operation the controller has to do,the code in that controller is huge(about 800 lines of code).
I want to ask if there is any way to pass the username to other controllers from a single controller?
The operations my application performs are : finds tasks of the user,finds groups of the user,creates tasks,creates groups,deletes tasks,delete groups.
I use a group of toggle buttons that make the nav bar :
So whenever the user clicks any of the toggle buttons,an appropriate operation is performed using the username he gave when he logged in.
I want each toggle button to load a single fxml view,and each of the views to have its own controller that does the appropriate action using the username.But i don't know how to save the username and pass it to those controllers.
Right know i use a single controller that doesn't use any fxml files,it just creates the appropriate gui,depending on the toggle button that was clicked,and performs the business logic.
I am trying to create a Test Case with Selenium, where I will create an application in one Page named "Policy". In this Application I want to create some Members. To go from Policy page to Members Page you have to press the button "Members" after you've successfully created the Policy Application. After creating all the members you need you have to navigate back to Policy page to continue.
(Main Menu Page -> Policy Page -> Members Page -> Policy Page)
I am using Page Object Pattern. I successfully log in the App, navigate to Policy Page, create the Application, but cannot go to Members Page in order to continue my Test. And of course, get back to Policy page. How can I do that? My test fails after message "Policy Created succesfully" is shown in Eclipse Console.
My code is:
#Test
public void TEST1_NavigateToPolicy() throws Exception {
MenuPage.policySelection();
}
#Test
public void TEST2_PolicyCreation() throws Exception {
PolicyPage.handleMultipleWindows("Policy");
PolicyPage.createPolicy( some requirements here);
PolicyPage.checkMessageByIdContains("Operation Apply executed Successfully", MESSAGE);
System.out.println("Policy Created succesfully");
}
#Test
public void TEST3_MemberCreation() {
//Navigate to Member Page and Create Member
PolicyPage.clickButton(MEMBERS_BUTTON);
}
Unless I'm testing the actual navigation via the UI I like to do as much navigating as possible by browsing directly to the page I need. It gives the test fewer opportunities to fail, and is often quicker as it can save extra steps.
So, I'd browse directly to the page simply using:
driver.get("yourURL");
Navigation between Policy and Members page can be done by:
#Test
public void TEST3_MemberCreation() {
// Create a policy
TEST2_PolicyCreation();
// Store the current window handle
String policyPageWindow = _webDriver.getWindowHandle();
// Clicking the "Members" button on Policy page
WebElement clickMemBerPageButton = _webDriver.findElement(By.name("MEMBERS_BUTTON"));
clickMemBerPageButton.click();
// switch focus of WebDriver to the next found window handle (that's your newly opened "Members" window)
for (String winHandle : _webDriver.getWindowHandles()) {
_webDriver.switchTo().window(winHandle);
}
//code to do something on new window (Members page)
// Switch back to policy page
_webDriver.switchTo().window(policyPageWindow);
}
Then this will be my sample code for you.
#Test
public void TEST3_MemberCreation() {
homePage = login(admin);
PolicyPage policyPage = homePage.NavigateToPolicyPage();
policyPage.handleMultipleWindows("Policy");
policyPage.createPolicy( some requirements here);
policyPage.checkMessageByIdContains("Operation Apply executed Successfully", MESSAGE);
System.out.println("Policy Created succesfully");
}
MembersPage membersPage = policyPage.clickMembersButton;(You have to handle the page navigation code inside this method and return MembersPage object)
membersPage.createMember(Data);
}
MembersPage clickMembersButton(){
element.click();
switchTo.window(newWindowHandle);
return new MembersPage();
}
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);
}
}
Using JAVA and SELENIUM LIBRARY:
I have a web automator that until now has worked flawlessly, using FirefoxDriver.
My code follows:
System.out.println("Creating new web driver");
WebDriver driver = new HtmlUnitDriver(BrowserVersion.FIREFOX_3_6);
System.out.println("Parsing CARD OFFICE PAGE\nAccessing webpage");
driver.get(myWebsite);
System.out.println("Setting login credentials");
WebElement id = driver.findElement(By.id("quickloginphrase"));
WebElement pw = driver.findElement(By.id("quickpassword"));
id.sendKeys(username);
pw.sendKeys(password);
System.out.println("Submitting credentials");
System.out.println(driver.getCurrentUrl());
pw.sendKeys(Keys.ENTER);
System.out.println("Credentials submitted");
Before I started using HTMLUnitDriver, the program managed to login to the webpage, but now I get redirected to a "login failed" page. I think the pw or username are being entered improperly. Is there some subtle difference between FirefoxDriver and HTMLUnitDriver that I'm not aware of?
well, possibly you come across with the following issues here:
1)
pw.sendKeys(Keys.ENTER);
enter button handler is not handled properly
2)
id.sendKeys(username);
pw.sendKeys(password);
you are sending improper login-pass
possible solution: try to press login button instean of pressing 'enter' key using
driver.findElement(By.xpath(//....blablabla)).click();
so I provide you some code which I use to login properly and validation of successful login:
public void doAdminLogin() throws IOException {
String curTitle=driver.getTitle();
locatorFindingHandling("login.logininput", "login.admin.login");
locatorFindingHandling("login.passinput", "login.admin.pass");
locatorFindingHandling("login.loginbutton");
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
String newTitle=driver.getTitle();
Assert.assertFalse(curTitle.equals(newTitle));
}
public void locatorFindingHandling(String key, String key1) throws IOException {
driver.findElement(By.xpath(propertyKeysLoader(key))).sendKeys(propertyKeysLoader(key1));
}
So as I've mentioned above try to investigate workaround. hope this works for you)