Search code examples
angularjsphantomjsprotractorangular-materialjasmine2.0

Protractor functional test does not update ng-model?


So in my basic angular app, I have a login form :

<form layout="column" class="form">
  <md-input-container>
    <label for="email" translate>login.email</label>
    <input id="email" type="email" ng-model="login.user.email" />
    <span ng-bind="login.user.email"></span>
  </md-input-container>
  <md-input-container>
    <label for="password" translate>login.password</label>
    <input id="password" type="password" ng-model="login.user.password" />
    <span ng-bind="login.user.password"></span>
  </md-input-container>
  <md-button class="hbd-primary"  ng-click="login.authenticate()" id="submit-button">
    <span translate>login.connection</span>
  </md-button>
</form>

I am currently writing functional tests with protractor and jasmine. Here is my login test :

it('should fail login with bogus credentials', function() {
  page.emailInput.clear().then(function() {
    page.emailInput.sendKeys('[email protected]');
  });
  expect(page.emailInput.getAttribute('value')).toBe('[email protected]');
  page.passwordInput.clear().then(function() {
    return page.passwordInput.sendKeys('boguspass');
  })
  .then(function() {
    expect(page.passwordInput.getAttribute('value')).toBe('boguspass');
    return page.submitButton.click();
  })
  .then(function() {
    expect(page.alert.element(by.id("login-alert-text")).getText())
      .toBe('Email ou mot de passe invalide');
  });
});

My problem is with the sendKeys() method, even if it writes the email and password correctly (visually it is in the inputs), when it triggers login function I noticed something weird with the request params : the fields email and password of my object user are empty eg "". But when I check the inputs 'value' attribute, it is correctly filled eg "[email protected]" & "boguspass".

So I searched a lot but found nothing so far, I have no idea where the issue could be...

Any leads would be very appreciated !

EDIT: additional code from controller and service.

Login controller

var vm = this;
vm.errors = '';
vm.user = {email: 'a', password: 'a', remember: true};
/**
*
* Log the user in.
*
**/
function authenticate() {
  vm.errors = '';
  retrieveToken(vm.user);
};

/**
*
* Get the jwt token. Change state depending on status.
*
**/
function retrieveToken(user) {
  authService.login(user)
    .success(function(data, status, headers, config) {
      saveToken(data.token);
      $state.go('employee');
    })
    .error(function(data, status, headers, config) {
      vm.errors = 'Email ou mot de passe invalide';
    });
};

/**
*
* Store the authenticated user.
*
**/
function saveToken(dataToken) {
  var token = jwtHelper.decodeToken(dataToken);
  var user = {
    id: token.id,
    firstName: token.firstName,
    lastName: token.lastName,
    roles: token.roles,
    token: dataToken
  };
  authService.setAuthentication(true, user);
};

authService

function auth($injector, constants) {
  var _authenticated = false;
  var _user = null;
  var service = {
    login: login,
    isAuthenticated: isAuth,
    setAuthentication: setAuth,
    getToken: getToken
  };

  /**
  *
  * Get the user authentication jwt.
  *
  **/
  function login(user) {
    return $injector.get('$http')
      .post(constants.baseApiUrl + 'authentication/login', user);
  };

  /**
  *
  * Return a boolean to check if user is connected to app.
  *
  **/
  function isAuth() {
    return _authenticated;
  };

  /**
  *
  * Set the current user authentication.
  *
  **/
  function setAuth(auth, user) {
    if (auth) {
      _authenticated = true;
      _user = user;
    }
    else if (auth === false) {
      _authenticated = false;
      _user = null;
    }
  };

EDIT2: When I set the fields email and password to anything, those values do not change when authenticating, even with the clear and sendKeys. But visually, the inputs are cleared and filled correctly. So I suspect the issue to be a data binding one. Maybe the two way binding is broken in some way.

EDIT3: Ok so under every inputs I added a span with a ng-binding to email and password model. When sendKeys and clear are used, the spans value do not change (eg 'a'). So there is a data binding issue ! Value change when I manually delete a character from the input.


Solution

  • So after hours and hours, I got the solution.

    When launching functional tests, I was using browser Sync and opened another browser to check if everything was ok.

    Somewhat, after using browser sync option open: false and letting phantomjs doing it's magic, everything work. Not sure why it was an issue but it is now resolved !