3

I am trying to call done() for async tests but that is not working, i am getting 'undefined is not a function' error.

describe('Login screen tests', function () {
  var ptor = protractor.getInstance();
  beforeEach(function(){
    console.log('In before Each method');
    ptor.get('http://staging-machine/login/#/');
  });

  it('Blank Username & Password test', function(done) {
    ptor.findElement(protractor.By.id("submit")).click();
    var message = ptor.findElement(protractor.By.repeater('message in messages'));
    message.then(function(message){
      message.getText().then(function(text) {
        console.log("Message shown:"+text);
        expect(message.getText()).toContain('Username or Password can\'t be blank');
        done();
      });
    });
  });
});

I tried to google around, and found that there might be some issue with jasmine, but i am still unable to resolve this. Because the error seems to be really unexpected. Any help would be appreciated.

Vikram
  • 509
  • 1
  • 11
  • 26
  • Are you sure you need to call done() for theses tests? What is the behaviour without it? – Michal Charemza Mar 28 '14 at 11:13
  • I dont get any error if i dont use 'done'. But i want to use it coz i have a number of async test cases running. And to make it work sequentially i found an option to use 'done', but i am unable to use it here. – Vikram Mar 28 '14 at 11:22
  • I think all protractor tests are async, and the ones I've seen/written run sequentially, without needing to call done(). Can you give a bit more context to what you're trying to achieve, and why you think done() is necessary? – Michal Charemza Mar 28 '14 at 17:55
  • maybe I dint understand properly. But, as I read to solve asynchronicity in our tests, jasmine-node provides a way to tell that a particular 'it' block is asynchronous. It is done by accepting a 'done' callback in the specification (it function) which makes Jasmine wait for the done() to be executed. – Vikram Mar 29 '14 at 05:33
  • What you say might be right for Jasmine when run by Karma, but Protractor changes the behaviour of Jasmine to work with the asynchronous nature of protractor tests. There is more information at https://github.com/angular/protractor/blob/master/docs/control-flow.md – Michal Charemza Mar 29 '14 at 09:07

1 Answers1

2

Are you sure you're getting undefined is not a function in line done() ?

I think your problem is here: ptor.findElement(protractor.By.repeater('message in messages')) because by then your clearly are on an Angular page so, regarding webdriver's findElement for a repeater: you should not be doing that.

Anyway, I would do 2 things:

  1. Upgrade Protractor to latest
  2. Rewrite the whole test like below since calling done() here is not required at all.

Rewrite:

describe('Login screen tests', function () {
  // Page Objects. TODO: Extract to separate module file.
  var submitBtnElm = $('#submit');
  var messagesRepElms = element.all(by.repeater('message in messages'));

  describe('Blank Username & Password test', function() {
    // Moved login get out of beforeEach since you need to get it once
    it('Opens an Angular login page', function() {
      browser.get('http://staging-machine/login/#/');
    });

    it('Clicks submit btn without entering required fields', function() {
      submitBtnElm.click();
    });

    it('Should trigger validation errors', function() {
      expect(messagesRepElms.first().isPresent()).toBeTruthy();
      expect(messagesRepElms.first().getText()).
        toContain('Username or Password can\'t be blank');
    });
  });
});
Leo Gallucci
  • 16,355
  • 12
  • 77
  • 110