1
votes

I am having issues passing protractor tests. As far as it looks, the project is based on a default angular 5 application but with additional styles/templates/layouts/components. As as result, a default e2e test that comes with the angular does not pass. The protractor configuration looks identical to a default one.

The log tells:

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

Test:

describe('angular App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display welcome message', () => {
    page.navigateTo();
    expect(page.getParagraphText()).toEqual('Welcome to app!');
  }, 100000);
});

Page:

export class AppPage {
  navigateTo() {
    return browser.get('/');
  }

  getParagraphText() {
    return element(by.css('.test-header')).getText();
  }
}

I have done some debugging on the code itself. The navigation part executes successfully and navigates to the url but when it tries to resolve a promise from getText() the whole execution stops. Feels like it gets blocked.

Is there a way to find out what could be blocking the protractor execution or at least watch what kind of async tasks are being run whenever it tries to run a test?

Any other solutions to this?

I am pretty new to e2e tests, so any help would be appreciated. Thanks.

EDIT: Adding browser.waitForAngularEnabled(false) before browser.get('/') fixes the issue but I would think its just a temporary band-aid

3
If you are running the it as async, then shouldn't you await each promise? await page.navigateTo(); and expect(await page.getParagraphText()).toEqual('Welcome to app'); - cnishina
Apologies for incorrect code listing. I have fixed the question. I was testing the behavior in different ways and forgot to remove the async keyword from the method signature. As you have understood I tried to await the Promise explicitly but all I could find out is that it gets stuck on getText(). - DasBoot
Could you try to return text instead of promise. Just wrap your current return in variable and return it. - Oleksii
Could you clarify your idea by writing it. If you are talking about unwraping the Promise explicitly before returning the result, I have tried that. - DasBoot
Another suggestion. Remove , 100000);. Try that again without the browser.waitForAngularEnabled(false) call. Disabling it will remove the synchronous behavior. I believe your tests are currently passing by luck and could become flaky. The 100000 is an override to the jasmine.DEFAULT_TIMEOUT_INTERVAL... for "Custom timeout for an async spec." Does this mean that adding it in requires you to call done()? See jasmine.github.io/api/edge/global.html#it - cnishina

3 Answers

1
votes

I have found whats causing the issue, although I have not fully investigated it.

I have started dissecting the application by removing all of the modules till I finally removed the root Routes. The test began to work properly. After that I have changed the Router setup as in a ng new app but with no positive result. Then, started checking the configuration files and found a bunch of libraries registered as global in .angular-cli.json scripts array. One of them was pace.js, after removing it, the test came back alive.

I have not looked at the source of the library that much, so I might be wrong, but my guess is that it is using timeouts extensively and it caused the testing frameworks to wait indefinitely for them to finish.

If anyone finds the exact reason, leave it in the comments.

1
votes

Increase jasmine default timeout interval in protractor conf.js

exports.config = {
   defaultTimeoutInterval: 2000000,
}
0
votes

You didn't consider that getText() returns a promise. expect() won't unwrap it for you and gets stuck. So you're supposed to go one step further in order to reach your goal.

describe('angular App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display welcome message', async () => {
    page.navigateTo();

    page.getParagraphText().then(text => {
      expect(text).toEqual('Welcome to app!');
    });

  }, 100000);
});

That should do.