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

Commit 9c2274d

Browse files
authored
fix(restart): preserve properties like browser.baseUrl upon restart (#4037)
I also fixed a minor issue where `internalRootEl` wasn't being set when blocking proxy was being used. I also just cleaned up our internal uses of `this.rootEl`. Closes #4032
1 parent bb535d3 commit 9c2274d

File tree

2 files changed

+98
-65
lines changed

2 files changed

+98
-65
lines changed

lib/browser.ts

+41-32
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ function buildElementHelper(browser: ProtractorBrowser): ElementHelper {
104104
* @extends {webdriver_extensions.ExtendedWebDriver}
105105
* @param {webdriver.WebDriver} webdriver
106106
* @param {string=} opt_baseUrl A base URL to run get requests against.
107-
* @param {string=} opt_rootElement Selector element that has an ng-app in
108-
* scope.
107+
* @param {string|webdriver.promise.Promise<string>=} opt_rootElement Selector element that has an
108+
* ng-app in scope.
109109
* @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should
110110
* stop tracking outstanding $timeouts.
111111
*/
@@ -192,17 +192,19 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
192192
* this method is called use the new app root. Pass nothing to get a promise that
193193
* resolves to the value of the selector.
194194
*
195-
* @param {string} The new selector.
195+
* @param {string|webdriver.promise.Promise<string>} value The new selector.
196196
* @returns A promise that resolves with the value of the selector.
197197
*/
198-
angularAppRoot(value: string = null): wdpromise.Promise<string> {
198+
angularAppRoot(value: string|wdpromise.Promise<string> = null): wdpromise.Promise<string> {
199199
return this.driver.controlFlow().execute(() => {
200200
if (value != null) {
201-
if (this.bpClient) {
202-
return this.bpClient.setWaitParams(value).then(() => this.internalRootEl);
203-
}
204-
this.internalRootEl = value;
205-
return this.internalRootEl;
201+
return wdpromise.when(value).then((value: string) => {
202+
this.internalRootEl = value;
203+
if (this.bpClient) {
204+
return this.bpClient.setWaitParams(value).then(() => this.internalRootEl);
205+
}
206+
return this.internalRootEl;
207+
});
206208
}
207209
}, `Set angular root selector to ${value}`);
208210
}
@@ -316,8 +318,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
316318
[key: string]: any;
317319

318320
constructor(
319-
webdriverInstance: WebDriver, opt_baseUrl?: string, opt_rootElement?: string,
320-
opt_untrackOutstandingTimeouts?: boolean, opt_blockingProxyUrl?: string) {
321+
webdriverInstance: WebDriver, opt_baseUrl?: string,
322+
opt_rootElement?: string|wdpromise.Promise<string>, opt_untrackOutstandingTimeouts?: boolean,
323+
opt_blockingProxyUrl?: string) {
321324
super();
322325
// These functions should delegate to the webdriver instance, but should
323326
// wait for Angular to sync up before performing the action. This does not
@@ -352,7 +355,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
352355
this.$ = build$(this.element, By);
353356
this.$$ = build$$(this.element, By);
354357
this.baseUrl = opt_baseUrl || '';
355-
this.rootEl = opt_rootElement || '';
358+
this.angularAppRoot(opt_rootElement || '');
356359
this.ignoreSynchronization = false;
357360
this.getPageTimeout = DEFAULT_GET_PAGE_TIMEOUT;
358361
this.params = {};
@@ -454,13 +457,14 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
454457
* var forked = await browser.forkNewDriverInstance().ready;
455458
* await forked.get('page1'); // 'page1' gotten by forked browser
456459
*
457-
* @param {boolean} opt_useSameUrl Whether to navigate to current url on
458-
* creation
459-
* @param {boolean} opt_copyMockModules Whether to apply same mock modules on
460-
* creation
461-
* @returns {Browser} A browser instance.
460+
* @param {boolean=} useSameUrl Whether to navigate to current url on creation
461+
* @param {boolean=} copyMockModules Whether to apply same mock modules on creation
462+
* @param {boolean=} copyConfigUpdates Whether to copy over changes to `baseUrl` and similar
463+
* properties initialized to values in the the config. Defaults to `true`
464+
*
465+
* @returns {ProtractorBrowser} A browser instance.
462466
*/
463-
forkNewDriverInstance(opt_useSameUrl?: boolean, opt_copyMockModules?: boolean):
467+
forkNewDriverInstance(useSameUrl?: boolean, copyMockModules?: boolean, copyConfigUpdates = true):
464468
ProtractorBrowser {
465469
return null;
466470
}
@@ -556,7 +560,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
556560
useAllAngular2AppRoots() {
557561
// The empty string is an invalid css selector, so we use it to easily
558562
// signal to scripts to not find a root element.
559-
this.rootEl = '';
563+
this.angularAppRoot('');
560564
}
561565

562566
/**
@@ -698,7 +702,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
698702
let pendingHttpsPromise = this.executeScriptWithDescription(
699703
clientSideScripts.getPendingHttpRequests,
700704
'Protractor.waitForAngular() - getting pending https' + description,
701-
this.rootEl);
705+
this.internalRootEl);
702706

703707
return wdpromise.all([pendingTimeoutsPromise, pendingHttpsPromise])
704708
.then(
@@ -1035,15 +1039,18 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
10351039
* page has been changed.
10361040
*/
10371041
setLocation(url: string): wdpromise.Promise<any> {
1038-
return this.waitForAngular().then(
1039-
() => this.executeScriptWithDescription(
1040-
clientSideScripts.setLocation, 'Protractor.setLocation()', this.rootEl, url)
1041-
.then((browserErr: Error) => {
1042-
if (browserErr) {
1043-
throw 'Error while navigating to \'' + url + '\' : ' +
1044-
JSON.stringify(browserErr);
1045-
}
1046-
}));
1042+
return this.waitForAngular()
1043+
.then(() => this.angularAppRoot())
1044+
.then(
1045+
(rootEl) =>
1046+
this.executeScriptWithDescription(
1047+
clientSideScripts.setLocation, 'Protractor.setLocation()', rootEl, url)
1048+
.then((browserErr: Error) => {
1049+
if (browserErr) {
1050+
throw 'Error while navigating to \'' + url + '\' : ' +
1051+
JSON.stringify(browserErr);
1052+
}
1053+
}));
10471054
}
10481055

10491056
/**
@@ -1064,9 +1071,11 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
10641071
getLocationAbsUrl(): wdpromise.Promise<any> {
10651072
logger.warn(
10661073
'`browser.getLocationAbsUrl()` is deprecated, please use `browser.getCurrentUrl` instead.');
1067-
return this.waitForAngular().then(
1068-
() => this.executeScriptWithDescription(
1069-
clientSideScripts.getLocationAbsUrl, 'Protractor.getLocationAbsUrl()', this.rootEl));
1074+
return this.waitForAngular()
1075+
.then(() => this.angularAppRoot())
1076+
.then(
1077+
(rootEl) => this.executeScriptWithDescription(
1078+
clientSideScripts.getLocationAbsUrl, 'Protractor.getLocationAbsUrl()', rootEl));
10701079
}
10711080

10721081
/**

lib/runner.ts

+57-33
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,13 @@ export class Runner extends EventEmitter {
214214
* This is used to set up the initial protractor instances and any
215215
* future ones.
216216
*
217-
* @param {?Plugin} The plugin functions
217+
* @param {Plugin} plugins The plugin functions
218+
* @param {ProtractorBrowser=} parentBrowser The browser which spawned this one
218219
*
219220
* @return {Protractor} a protractor instance.
220221
* @public
221222
*/
222-
createBrowser(plugins: any): any {
223+
createBrowser(plugins: any, parentBrowser?: ProtractorBrowser): any {
223224
let config = this.config_;
224225
let driver = this.driverprovider_.getNewDriver();
225226

@@ -228,31 +229,53 @@ export class Runner extends EventEmitter {
228229
blockingProxyUrl = this.driverprovider_.getBPUrl();
229230
}
230231

232+
let initProperties = {
233+
baseUrl: config.baseUrl,
234+
rootElement: config.rootElement as string | wdpromise.Promise<string>,
235+
untrackOutstandingTimeouts: config.untrackOutstandingTimeouts,
236+
params: config.params,
237+
getPageTimeout: config.getPageTimeout,
238+
allScriptsTimeout: config.allScriptsTimeout,
239+
debuggerServerPort: config.debuggerServerPort,
240+
ng12Hybrid: config.ng12Hybrid
241+
};
242+
243+
if (parentBrowser) {
244+
initProperties.baseUrl = parentBrowser.baseUrl;
245+
initProperties.rootElement = parentBrowser.angularAppRoot();
246+
initProperties.untrackOutstandingTimeouts = !parentBrowser.trackOutstandingTimeouts_;
247+
initProperties.params = parentBrowser.params;
248+
initProperties.getPageTimeout = parentBrowser.getPageTimeout;
249+
initProperties.allScriptsTimeout = parentBrowser.allScriptsTimeout;
250+
initProperties.debuggerServerPort = parentBrowser.debuggerServerPort;
251+
initProperties.ng12Hybrid = parentBrowser.ng12Hybrid;
252+
}
253+
231254
let browser_ = new ProtractorBrowser(
232-
driver, config.baseUrl, config.rootElement, config.untrackOutstandingTimeouts,
233-
blockingProxyUrl);
255+
driver, initProperties.baseUrl, initProperties.rootElement,
256+
initProperties.untrackOutstandingTimeouts, blockingProxyUrl);
234257

235-
browser_.params = config.params;
258+
browser_.params = initProperties.params;
236259
if (plugins) {
237260
browser_.plugins_ = plugins;
238261
}
239-
if (config.getPageTimeout) {
240-
browser_.getPageTimeout = config.getPageTimeout;
262+
if (initProperties.getPageTimeout) {
263+
browser_.getPageTimeout = initProperties.getPageTimeout;
241264
}
242-
if (config.allScriptsTimeout) {
243-
browser_.allScriptsTimeout = config.allScriptsTimeout;
265+
if (initProperties.allScriptsTimeout) {
266+
browser_.allScriptsTimeout = initProperties.allScriptsTimeout;
244267
}
245-
if (config.debuggerServerPort) {
246-
browser_.debuggerServerPort = config.debuggerServerPort;
268+
if (initProperties.debuggerServerPort) {
269+
browser_.debuggerServerPort = initProperties.debuggerServerPort;
247270
}
248-
if (config.ng12Hybrid) {
249-
browser_.ng12Hybrid = config.ng12Hybrid;
271+
if (initProperties.ng12Hybrid) {
272+
browser_.ng12Hybrid = initProperties.ng12Hybrid;
250273
}
251274

252275
browser_.ready =
253276
browser_.ready
254277
.then(() => {
255-
return driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout);
278+
return driver.manage().timeouts().setScriptTimeout(initProperties.allScriptsTimeout);
256279
})
257280
.then(() => {
258281
return browser_;
@@ -262,25 +285,26 @@ export class Runner extends EventEmitter {
262285
return wdpromise.when(config);
263286
};
264287

265-
browser_.forkNewDriverInstance = (opt_useSameUrl: boolean, opt_copyMockModules: boolean) => {
266-
let newBrowser = this.createBrowser(plugins);
267-
if (opt_copyMockModules) {
268-
newBrowser.mockModules_ = browser_.mockModules_;
269-
}
270-
if (opt_useSameUrl) {
271-
newBrowser.ready = newBrowser.ready
272-
.then(() => {
273-
return browser_.driver.getCurrentUrl();
274-
})
275-
.then((url: string) => {
276-
return newBrowser.get(url);
277-
})
278-
.then(() => {
279-
return newBrowser;
280-
});
281-
}
282-
return newBrowser;
283-
};
288+
browser_.forkNewDriverInstance =
289+
(useSameUrl: boolean, copyMockModules: boolean, copyConfigUpdates = true) => {
290+
let newBrowser = this.createBrowser(plugins);
291+
if (copyMockModules) {
292+
newBrowser.mockModules_ = browser_.mockModules_;
293+
}
294+
if (useSameUrl) {
295+
newBrowser.ready = newBrowser.ready
296+
.then(() => {
297+
return browser_.driver.getCurrentUrl();
298+
})
299+
.then((url: string) => {
300+
return newBrowser.get(url);
301+
})
302+
.then(() => {
303+
return newBrowser;
304+
});
305+
}
306+
return newBrowser;
307+
};
284308

285309
let replaceBrowser = () => {
286310
let newBrowser = browser_.forkNewDriverInstance(false, true);

0 commit comments

Comments
 (0)