Reputation: 35
I'm using page object model and I'm stuck at how to put the browser.driver
elements as a variable.
Here is an example of using it with Protractor
's element
:
var Messages = function() {};
var messagesLink = element(by.css('a[href*="/Messages"]'));
Messages.prototype.visitPage = function() {
messagesLink.click();
};
exports.Messages = new Messages();
Then I can use Messages.visitPage();
throughout my test. The problem is when I try to do the same thing with browser.driver
:
var Login = function() {};
var usernameField = browser.driver.findElement(by.id('UserName'));
var passwordField = browser.driver.findElement(by.id('Password'));
var signOnButton = browser.driver.findElement(by.css('input[value="Sign On"]'));
var registeredUserName = 'user';
var registeredUserPass = 'pass';
Login.prototype.loginAsRegisteredUser = function() {
loginAs(registeredUserName, registeredUserPass);
};
var loginAs = function(userName, pass) {
usernameField.sendKeys(userName);
passwordField.sendKeys(pass);
signOnButton.click();
};
exports.Login = new Login();
The test instantly fails before even starting, throwing this error NoSuchElementError: Unable to locate element: *[id="UserName"]
. The reason why I'm using browser.driver
is because I'm accessing elements on a non-angular page. I want to try and keep angular and non-angular references separate from each other.
I'm not sure how Protractor
handles this but in Selenium
I can use the variable like so, static By cancelButton = By.id("cphMain_btnCancel");
.
So, is there anyway that this can be done using Protractor
?
Spec File:
var home = require('../../pages/home/Home.js').Home;
var headerHome = require('../../pages/home/HeaderHome.js').HeaderHome;
var login = require('../../pages/Login.js').Login;
describe('Registered User | DEV_Smoke |--- Home page: ', function() {
it('Navigates to the Home page', function() {
home.visitPage();
});
it('Prints the current URL (see build.log)', function() {
home.verifyHomeUrl();
});
it('Clicks Sign On link and signs in as a registered user', function() {
headerHome.clickSignOnLink();
login.loginAsRegisteredUser();
});
});
Upvotes: 1
Views: 756
Reputation: 14287
Easiest way would be to just wrap the findElement in functions and call them as needed
var Login = function() {};
var usernameField = function() {
return browser.driver.findElement(by.id('UserName')); //returns promise
}
var passwordField = function() {
return browser.driver.findElement(by.id('Password'));
}
var signOnButton = function() {
return browser.driver.findElement(by.css('input[value="Sign On"]'));
}
var registeredUserName = 'user';
var registeredUserPass = 'pass';
Login.prototype.loginAsRegisteredUser = function() {
loginAs(registeredUserName, registeredUserPass);
};
var loginAs = function(userName, pass) {
usernameField().sendKeys(userName);
passwordField().sendKeys(pass);
signOnButton().click();
};
exports.Login = new Login();
Upvotes: 2
Reputation: 5016
browser.driver is of type Webdriver
and when calling findElement
, selenium-webdriver will try to evaluate wherever it is stated in your code. So prior to your login method and possibly navigation to the login page, you are automatically looking for the WebElements for UserName
, Password
, and input[value="SignOn"]
.
In your code snippet, it looks like you should use element
. When using element
, at runtime, the findElement
will be evaluated. This allows for more reusable code.
For non-angular pages, you might have to provide your own syncing or some arbitrary sleep. This usually occurs with animations, long load screens, etc.
Also make sure you return your promises so the jasmine wrapper evaluates your function properly.
var usernameField = element(by.id('UserName'));
var passwordField = element(by.id('Password'));
var signOnButton = element(by.css('input[value="Sign On"]'));
// make sure you return your promises so the jasmine wrapper
// evaluates your function properly.
var loginAs = function(userName, pass) {
return usernameField.sendKeys(userName).then(() => {
return passwordField.sendKeys(pass).then(() => {
return signOnButton.click();
});
});
};
Upvotes: 2