问题
I\'m trying to automate my tests with Protractor and Appium for an AngularJS site with jasmine framework in iPad simulator, sendkeys()
function is working for username and password, but when i click into the login button the test is passed, but the action isn\'t done : no redirection to home page, and no on click effect is displayed for login button, i\'m sure that element is located correctly ! because when i expect the gettext() to be equal to\"LOGIN\" it is passed but no redirection even if i put browser.sleep(8000);
Here my test script :
\"use strict\";
require(\"jasmine-expect\");
var wd = require(\"wd\");
describe(\'my app\', function() {
it(\'should make the login test\',function() {
// browser.ignoresynchronization=true;
browser.get(\"http://10.0.22.82:8080/jws/fetablet\");
expect(browser.getCurrentUrl()).toEqual((\"http://10.0.22.82:8080/jws/fetablet/#/login\"));
element(by.model(\'credentials.username\')).sendKeys(\'RET02\').then(function(){
element(by.model(\'credentials.password\')).sendKeys(\'RET02\').then(function(){
element(by.css(\'.login-button\')).click().then(function(){
browser.sleep(8000); expect(browser.getCurrentUrl()).not.toEqual(\"http://10.0.22.82:8080/jws/fetablet/#/login\");
});
});
});
});
});
Is there another method to locate the click button correctly? Here my html code :
<div class=\"login_lang\"> <md-button class=\"lang_button\" ng-click=\"changeLang()\">{{lang}}</md-button> </div>
<div layout=\"column\" flex layout-align=\"center center\" class=\"md-padding splash-background\"> <div class=\"login-logo\"> <img src=\"{{logoSrc}}\"> </div> <form class=\"login-form\" name=\"loginForm\" ng-submit=\"login()\">
<fieldset> <md-input-container class=\"md-block\">
<label translate=\"login.USERNAME\" ng-class=\"{\'floating-label-rtl\':dir===\'rtl\'}\"
class=\"login-label\">Username</label>
<input required ng-model=\"credentials.username\" ng-focus=\"onFocus()\" type=\"text\">
<div ng-messages=\"loginForm.credentials.username.$error\" ng-show=\"loginForm.credentials.username.$dirty\">
<div ng-message=\"required\" trans
late=\"login.MESSAGE_REQUIRED\">This is required.</div> </div> </md-input-container> <md-input-container class=\"md-block\"> <label translate=\"login.PASSWORD\" ng-class=\"{\'floating-label-rtl\':dir===\'rtl\'}\"
class=\"login-label\">Password</label> <input required ng-model=\"credentials.password\" ng-focus=\"onFocus()\" type=\"pa
ssword\">
<div ng-messages=\"loginForm.credentials.password.$error\" ng-show=\"loginForm.credentials.password.$dirty\"> <div ng-message=\"required\" translate=\"login.MESSAGE_REQUIRED\">This is required.</div> </div> </md-input-container>
<div layout-align=\"center center\" layout=\"column\" ng-if=\"oneTimePassword\"> <p class=\"login-otp-message\" translate=\"login.OTP_MESSAGE\">Enter the code which you received by SMS</p> <md-button class=\"md-warn login-otp-retry\" translate=\"login.OTP_RETRY\" ng-click=\"retry()\">Retry</md-button> </div> <md-input-container class=\"md-block\" ng-if=\"oneTimePassword\"> <label translate=\"login.SECURITY_CODE\" class=\"login-label\">Security code</label> <input required ng-model=\"credentials.securityCode\" ng-focus=\"onFocus()\" type=\"password\"> <div ng-messages=\"loginForm.credentials.securityCode.$error\" ng-show=\"loginForm.credentials.securityCode.$dirty\"> <div ng-message=\"required\" translate=\"login.MESSAGE_REQUIRED\">This is required.</div> </div> </md-input-container> <div layout-align=\"center\"> <section layout-align=\"center\" layout=\"row\" layout-sm=\"column\"> <div id=\"login-error\" md-caption class=\"msg-error\" ng-show=\"error\" class=\"label\">{{error}}</div>
<md-button type=\"submit\" class=\"md-raised login-button\" ng-disabled=\"clicked\" translate=\"login.LOGIN\">Login</md-button> </section>
</div> </fieldset> </form> <md-divider></md-divider> <footer class=\"login-footer\"> <div layout=\"row\" layout-align=\"center center\"> <md-button ng-click=\"goToCustomerCare()\" class=\"login-footer-link\" translate=\"login.CUSTOMER_CARE\">Contact Customer Care</md-button> <div> | </div> <md-button ng-click=\"showDisclaimer()\" class=\"login-footer-link\" translate=\"login.DISCLAIMER\">Disclaimer</md-button> </div> </footer> </div>
I put the details of Appium recorder about the login button
回答1:
There might be multiple reasons for that and it is going to be a guessing game anyway.
it could be that there is an another element matching the
.login-button
locator and you are clicking a different element. Let's improve the locator:element(by.css(".login-form .login-button")).click();
wait for the element to be clickable:
var EC = protractor.ExpectedConditions; element(by.model('credentials.username')).sendKeys('RET02'); element(by.model('credentials.password')).sendKeys('RET02'); var loginButton = element(by.css('.login-form .login-button')); browser.wait(EC.elementToBeClickable(loginButton), 5000); loginButton.click();
add a small delay before clicking the element (silly, but I see that helped sometimes):
element(by.model('credentials.username')).sendKeys('RET02'); element(by.model('credentials.password')).sendKeys('RET02'); browser.sleep(500); element(by.css('.login-form .login-button')).click();
another silly try, click 2 times (I cannot believe I actually advise that):
var loginButton = element(by.css('.login-form .login-button')); loginButton.click(); loginButton.click();
disable angular animations
click the button via browser.actions() moving to the element before the click:
var loginButton = element(by.css('.login-form .login-button')); browser.actions().mouseMove(loginButton).click().perform();
sort of an extension to the previous approach. Move to element, sleep for half a second and then click:
browser.actions.mouseMove(loginButton).perform(); browser.sleep(500); loginButton.click();
Or, if you would introduce a custom sleep() action, you can do:
browser.actions.mouseMove(loginButton).sleep(500).click().perform();
click the element via javascript:
var loginButton = element(by.css('.login-form .login-button')); browser.executeScript("arguments[0].click();", loginButton);
And, after the form is submitted, instead of browser.sleep()
, you can wait for URL to change explicitly, please see:
- Protractor- Generic wait for URL to change
As a side note, in Protractor, you use the $ and $$ shortcuts for the CSS locators:
var loginButton = $('.login-form .login-button');
回答2:
Try executing those commands without using the promise chain. It can be a problem in the previous chain.
"use strict";
require("jasmine-expect");
var wd = require("wd");
describe('my app', function() {
it('should make the login test',function() {
browser.get("http://10.0.22.82:8080/jws/fetablet");
expect(browser.getCurrentUrl()).toEqual(("http://10.0.22.82:8080/jws/fetablet/#/login"));
element(by.model('credentials.username')).sendKeys('RET02');
element(by.model('credentials.password')).sendKeys('RET02');
element(by.css('.login-button')).click();
browser.sleep(8000);
expect(browser.getCurrentUrl()).not.toEqual("http://10.0.22.82:8080/jws/fetablet/#/login");
});
PS: You can avoid using the 'then' function when you do not need to use the result of the method. It is controlled by the control flow
回答3:
Just adding browser.sleep after the click worked for me:
it('Some test', function () {
element(by.css("button[type='submit']")).click();
browser.sleep(1000);
});
回答4:
I have one more suggestion, you can expect particular element need to be displayed and clear the text-box. You can actually write in promise, that is the best way.
var loginButton = element(by.css('.md-raised.login-button'));
var userName = element(by.model('credentials.username'));
var password = element(by.model('credentials.password'));
this.username = function(sendUserName) {
expect(userName.isDisplayed()).toBeTruthy();
userName.clear().then(function(){
userName.sendKeys(sendUserName).then(function(){
expect(password.isDisplayed()).toBeTruthy();
});
});
};
this.password = function(password) {
expect(password.isDisplayed()).toBeTruthy();
password.clear().then(function(){
password.sendKeys(password).then(function(){
browser.wait(EC.elementToBeClickable(loginButton), 10000);
});
});
};
this.clickloginbutton = function() {
expect(loginButton.isDisplayed()).toBeTruthy();
loginButton.click().then(function(){
expect('something').not.toBeNull();
});
}
来源:https://stackoverflow.com/questions/36871071/click-function-isnt-working-in-protractor-scripts