Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Create pass-through version of protractor.browser #3884

Closed
sjelin opened this issue Dec 27, 2016 · 5 comments
Closed

Create pass-through version of protractor.browser #3884

sjelin opened this issue Dec 27, 2016 · 5 comments

Comments

@sjelin
Copy link
Contributor

sjelin commented Dec 27, 2016

There are two main issues with the way we handle protractor.browser (i.e. global.browser):

  • We call setupGlobals_ again in browser.restart, overwriting the old reference. This could cause problems if anyone saves a reference to the old browser object. For instance, in When using ExpectedConditions after browser.restart(), getting "Driver does not have valid session ID" error #3881, a test is saving a reference to ExpectedConditions, which in turn has a reference to browser, causing a problem.
  • We don't really integrate .ready deeply into protractor commands. Currently this is not a problem because .ready for three reasons:
    • .ready() is only used to make sure timeouts are set correctly, and it's not a big deal if we don't wait for it properly
    • .ready() is a webdriver promise, and is waited on by the control flow
    • .ready() is waited on in Runner.run(), so this only matters when browser.forkNewDriverInstance or browser.restart() are used

#3881 is an incorrect usage, but it was a reasonable mistake. .ready() isn't a big deal at the moment, but we're going to use it more as reduce out reliance on the webdriver control flow.

I propose we make a class ShallowBrowser, which basically implements all methods/properties something like this:

class ShallowBrowser implements iProtractorBrowser {
  //  -- declare properties for ProtractorBrowser
  ...
  //  -- end property declaration

  private browserInstance_: ProtractorBrowser;
  constructor(browserInstance: ProtractorBrowser) {
    this.browserInstance_ = browserInstance;
    // Use Object.defineProperty for properties
    Object.defineProperty(this, driver, {
      get: () => {return this.browserInstance_.driver;},
      set: (driver: WebDriver) => {this.browserInstance_.driver = driver;}
    });
    ...
  }

  // Functions check `.ready()` and then pass through
  get = function() {
    this.browserInstance_.ready().then(() => {
      return this.browserInstance_.get.apply(this, arguments);
    });
  };
  ...
}

Then in restart we would set browser_.browserInstance_, instead of overwriting browser_ and the global variables.


To be clear, I think this is an extremely ugly solution which I hate. If you have a better idea please let me know.

@juliemr @cnishina @mgiambalvo feedback would be appreciated

@juliemr
Copy link
Member

juliemr commented Dec 27, 2016

Another thing we could do would be to have restart and forkNewDriverInstance return promises that resolve when it's ready, so your code with async/await would look more like:

await browser.restart();
await browser.get(...);

@sjelin
Copy link
Contributor Author

sjelin commented Dec 28, 2016

We will have to return a promise from browser.restart either way. But how would this interact with restartBrowserBetweenTests? Jasmine doesn't provide the functionality we need to wait on the returned promise.

Also, returning a promise from forkNewDriverInstance would be pretty annoying for people currently relying on the control flow, since they can't await it (as that would break the control flow), so they'd have to then it, which would be different from all the other protractor commands (and a breaking change).

@sjelin
Copy link
Contributor Author

sjelin commented Dec 28, 2016

That also doesn't really do anything to resolve the stale reference problem

@sjelin
Copy link
Contributor Author

sjelin commented Dec 28, 2016

If we replace the .ready property with a waitFor() API, we could probably wrap/unwrap the functions on the protractor instance as needed.

@sjelin
Copy link
Contributor Author

sjelin commented Dec 30, 2016

Closing in favor of #3892, #3895, #3896, and #3897. This won't solve the problem of stale references to the global browser object, but it will solve everything else.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants