This repository was archived by the owner on Jul 29, 2024. It is now read-only.
This repository was archived by the owner on Jul 29, 2024. It is now read-only.
Create pass-through version of protractor.browser
#3884
Closed
Description
There are two main issues with the way we handle protractor.browser
(i.e. global.browser
):
- We call
setupGlobals_
again inbrowser.restart
, overwriting the old reference. This could cause problems if anyone saves a reference to the oldbrowser
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 tobrowser
, 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 inRunner.run()
, so this only matters whenbrowser.forkNewDriverInstance
orbrowser.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
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
juliemr commentedon Dec 27, 2016
Another thing we could do would be to have
restart
andforkNewDriverInstance
return promises that resolve when it's ready, so your code withasync/await
would look more like:sjelin commentedon Dec 28, 2016
We will have to return a promise from
browser.restart
either way. But how would this interact withrestartBrowserBetweenTests
? 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'tawait
it (as that would break the control flow), so they'd have tothen
it, which would be different from all the other protractor commands (and a breaking change).sjelin commentedon Dec 28, 2016
That also doesn't really do anything to resolve the stale reference problem
sjelin commentedon Dec 28, 2016
If we replace the
.ready
property with awaitFor()
API, we could probably wrap/unwrap the functions on the protractor instance as needed.sjelin commentedon 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.global.browser
,global.$
, etc., pass through toprotractor.browser
etc #3883