Search code examples
angularjstestingprotractorautomated-testsend-to-end

Why do I need to use waitForAngular(false) & browser.sleep(3000)?


We have a website that is built 100% from Angular and I was asked to use Protractor to write an end to end testing. Now encountered a problem that if I do not use waitForAngular(false) and browser.sleep(3000) then my test fails even I used the ExpectedCondition.

So here is my Scenario:

In the login page, I can find all elements, send keys to the input box and login. But after login, it fails. It cannot find any element, click any element at all.

My Code looks like this.

describe("/profile", () => {
  let page: Profile;

  beforeAll(async () => {
    page = await login(Profile, user, login);
    await browser.wait(ExpectedConditions.presenceOf(page.element));
    await navigate(path.profile)
  })

  afterAll(async () => {
    logout();
  })

  it("should have navigate to the page", async () => {
    expect(await browser.getCurrentUrl()).toContain("/profile");
  });

  it("should have correct page markup", async () => { 
// this test fails without waitForAngular(false)
// or browser.sleep(3000) in the navigation or OnPrepare in the config
    expect(await page.headerTitle.isDisplayed()).toBe(true);
    expect(await page.headerTitle.getText()).toContain("Profile")
  })
})

What am I doing wrong?


Solution

  • First of all, browser.wait() takes three parameters - function condition, timeout, message on failure. Only last one is optional. You forgot to specify timeout time in milliseconds, likely it causes your problem

    Second, waitForAngular takes optional string as a description. Idk why you pass false to it

    P.S. I think you misunderstand major concepts about how to handle waiting in protractor

    browser.sleep(ms) - is explicit wait, stops execution for number of ms specified as a parameter

    browser.wait() - waits until the function passed to it returns true, or for the number of ms passed as a parameter. It's not an explicit wait. Also, its not going to wait indefinitely. You pass timeout time as argument, or it takes jasmineNodeOpts.defaultTimeoutInterval from your protractor.conf.js or default 30 seconds

    Your browser.sleep(ms) causing performance issue of your tests. Avoid it in your tests

    browser.waitForAngular() - very useful, it waits until your angular app completes all tasks behind scene, but it's included in each actions by default. So no usually no affects if you use 2,3 or 4 times. IMPORTANT, some apps are poorly built and always load something in a background, so your tests are either slow or unresponsive at all. This is why I always run tests with browser.waitForAngularEnabled(false), but it's super difficult to handle wait. As an advantage you get fast and reliable tests. And don't pass false to waitForAngular, it has no effect.

    With that said, forget about browser.sleep() instead learn how to use browser.wait

    if you're using browser.sleep(3000) you make your tests stop for 3 sec, but what if your next element is ready to be interacted with in 500ms?? so just say wait until element is present(visible(intractable(or whatever you want))), but no longer than 3 sec, and you end up having faster tests

    Hope that answers your question