Alessandro Celeghin
Alessandro Celeghin

Reputation: 4189

Angular 6 Jasmine Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

I am not able to test some features of my application because sometimes (very often) protractor test fails in the beforeEach function.

Probably I am missing something important because the test fails randomly, I found some discussion about maximize the timeouts but it doesn't solve the problem.

I see that the beforeEach doesn't get executed entirely when a test fails, only the first instruction is executed ( browser.get ) then the browser still on the same page all time.

I am trying with allScriptsTimeout: 45000 this is some tests.

describe('Rebus', function() {
  // mi posiziono nella lista ticket dopo ogni test e clicco su nuovo ticket

  beforeEach(function() {

    browser.get(Utils.baseUrl + '/tickets');

    browser.wait(function() {
      return element(by.id('newTicket')).isPresent();
    }, 5000);
    element(by.id('newTicket')).click();



    /**Ora passo dalla lista ticket a selezione blocco*/
    browser.wait(function() {
      return element(by.id('0')).isPresent();
    }, 5000);

    element(by.id('0')).click();
    element(by.id('newTicket')).click();
  });

  it('should buy ordinary ticket eurolevel 3', function() {
    // A questo punto dovrei essere arrivato al form del nuovo ticket
    selectArea('0');
    fillLicensePlate(5, 3);
    fillCountry();
    fillPassengers();
    setEntryDate(now);
    setExitDate(now.add(1, 'd'));

    // vai avanti al secondo step
    element(by.id('stepperNext')).click();

    browser.wait(function() {
      return element(by.id('daysOfStay')).isDisplayed();
    }, 5000);

    // Controllo che il prezzo sia corretto e controllo i giorni di permanenza
    element(by.id('daysOfStay'))
      .getText()
      .then(function(text) {
        expect(text).toContain('1');
      });

    element(by.id('amount'))
      .getText()
      .then(function(text) {
        expect(text).toContain('510', 'Errore nella tariffa');
      });

    browser.wait(function() {
      return element(by.id('save')).isDisplayed();
    }, 5000);

    // salvo il ticket
    element(by.id('save')).click();

    // Controllo che il prezzo sia corretto e controllo i giorni di permanenza
    browser.wait(function() {
      return element(by.name('price')).isPresent();
    }, 5000);

    element(by.name('price'))
      .getText()
      .then(function(text) {
        expect(text).toContain('510', 'Errore nella tariffa');
      });

    expect(element(by.name('addPay')).isPresent()).toBeTruthy(
      'Bottone non presente'
    );
  });

  it('should buy HOTEL ticket eurolevel €3', function() {
    // A questo punto dovrei essere arrivato al form del nuovo ticket
    selectArea('0');
    fillLicensePlate(5, 3);
    fillCountry();
    fillPassengers();
    setEntryDate(now);
    setExitDate(now.add(1, 'd'));

    // Campi opzionali
    setHotelField();
    setAgencyField();

    // vai avanti al secondo step
    element(by.id('stepperNext')).click();

    browser.wait(function() {
      return element(by.id('daysOfStay')).isDisplayed();
    }, 5000);

    // Controllo che il prezzo sia corretto e controllo i giorni di permanenza
    element(by.id('daysOfStay'))
      .getText()
      .then(function(text) {
        expect(text).toContain('1');
      });

    element(by.id('amount'))
      .getText()
      .then(function(text) {
        expect(text).toContain('210', 'Errore nella tariffa');
      });

    browser.wait(function() {
      return element(by.id('save')).isDisplayed();
    }, 5000);

    // salvo il ticket
    element(by.id('save')).click();

    // Controllo che il prezzo sia corretto e controllo i giorni di permanenza
    browser.wait(function() {
      return element(by.name('price')).isPresent();
    }, 5000);

    element(by.name('price'))
      .getText()
      .then(function(text) {
        expect(text).toContain('210', 'Errore nella tariffa');
      });

    expect(element(by.name('addPay')).isPresent()).toBeTruthy(
      'Bottone non presente'
    );
  });

Upvotes: 3

Views: 17103

Answers (1)

Silvan Bregy
Silvan Bregy

Reputation: 2734

I think the problem is, that you are not waiting for asynchronous tasks. Most of the functions from browser object are asynchronous. Means that they are executed in different threads. So Whenever you call an asynchronous function it's not waited until it has finished. No, the next line of code is executed immediately. So in your particular case browser.get(), browser.wait() and element.click() functions are executed almost at the same time and it's never waited for one function to finish. They all run parallel and as the last function has finished your beforeEach() stops.

For waiting for asynchronous tasks you have to work with Promises Object. Following code would work in your test:

beforeEach(function() {
    browser.get(Utils.baseUrl + '/tickets').then(function () {
        // url '/tickets' opened now
        browser.wait(function() {
            return element(by.id('newTicket')).isPresent();
        }, 5000).then(function() {
            element(by.id('newTicket')).click();
           // next task here..
        });
    });
});

If you are using typescript this can be done in a very nice looking way, using await:

beforeEach(async function() {
    await browser.get(Utils.baseUrl + '/tickets');
    await browser.wait(function() { 
        return element(by.id('newTicket')).isPresent();
    }, 5000);
    await element(by.id('newTicket').click();
    // next task here..
});

When also using arrow functions it almost gets elegant:

beforeEach(async () => {
    await browser.get(Utils.baseUrl + '/tickets');
    await browser.wait(() => element(by.id('newTicket')).isPresent()),5000});
    await element(by.id('newTicket').click();
    // next task here..
});

If you have never heard about Promises just use your next day of work to learn them.

Upvotes: 1

Related Questions