Justin Dearing
Justin Dearing

Reputation: 14928

Why does browser.wait(ExpectedConditions.presenceOf()) cause my method chain to return Promise<Promise<boolean?>>

I'm writing some protractor tests like this:

import { browser, element, by, ExpectedConditions } from 'protractor';

export class SomePage {
  private elements: any = {};

  navigateToUpdate(name: string) {
    return browser.get(`/policies/${name}`)
      .then(() => browser.waitForAngular())
      .then(() => browser.wait(this.statusIsPresent))
      .then(() => this.initElements());
  }

  private initElements(): Promise<void> {
      // Do stuff here
      return Promise.resolve();
  }

  private get statusIsPresent(): Function {
    return ExpectedConditions.presenceOf(element(by.id('status')));
  }  
}

Because of the wait() navigateToUpdate() returns Promise<Promise<void>>. I don't understand why, and I don't understand if this is a potential problem creating bugs I don't understand.

Regardless of what browser.wait() returns shouldn't Promise.resolve().then(() =>browser.wait()).then(() => something()) return whatever something() returns, and not a Promise of whatever something() returns?

Upvotes: 1

Views: 592

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249536

Protractor uses it's own promise library (actually they are implemented in the selenium module but it does not matter much), and the definitions for it do not unwrap default promises (the build-in ones) correctly. If you use protractor promises the result is as expected:

private initElements(): promise.Promise<void> {
    // Do stuff here
    return promise.fullyResolved(null)
}
navigateToUpdate(name: string) { // return type is inferred to promise.Promise<void>
    return browser.get(`/policies/${name}`)
    .then(() => browser.waitForAngular())
    .then(() => browser.wait(this.statusIsPresent))
    .then(() => this.initElements());
}

It also works correctly with async/await

async navigateToUpdate(name: string) {// return type is inferred to promise.Promise<void>
    await browser.get(`/policies/${name}`);
    await browser.waitForAngular();
    await browser.wait(this.statusIsPresent);
    await this.initElements();
}

This will cause errors if anyone tries to read the promise return type, because the implementation will unwrap the promise, while the type system is unaware of this and it will tell you that the result of a promise is a promise when it will in fact not be.

Upvotes: 2

Related Questions