Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click() function isn't working in protractor scripts

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="lo​​gin_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

Appium Inspector

like image 955
Emna Ayadi Avatar asked Nov 27 '22 21:11

Emna Ayadi


2 Answers

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');
like image 118
alecxe Avatar answered Dec 11 '22 01:12

alecxe


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

like image 41
flaviomeira10 Avatar answered Dec 11 '22 02:12

flaviomeira10