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

Commit 4672265

Browse files
committed
chore(browser): remove timing issues with restart and fork (#5085)
- remove .ready since forking should automatically return a browser - getNewDriver should return a promised WebDriver that can be awaited - fix interaction tests and local driver tests - update unit tests for async await due to getNewDriver fix closes #5031
1 parent b4dbcc2 commit 4672265

17 files changed

+288
-280
lines changed

lib/browser.ts

+6-21
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
238238
* Resolved when the browser is ready for use. Resolves to the browser, so
239239
* you can do:
240240
*
241-
* forkedBrowser = await browser.forkNewDriverInstance().ready;
241+
* forkedBrowser = await browser.forkNewDriverInstance();
242242
*
243243
* Set by the runner.
244244
*
@@ -359,22 +359,6 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
359359
ng12Hybrid_ = ng12Hybrid;
360360
}
361361
});
362-
this.ready = this.angularAppRoot(opt_rootElement || '')
363-
.then(() => {
364-
return this.driver.getSession();
365-
})
366-
.then((session: Session) => {
367-
// Internet Explorer does not accept data URLs, which are the default
368-
// reset URL for Protractor.
369-
// Safari accepts data urls, but SafariDriver fails after one is used.
370-
// PhantomJS produces a "Detected a page unload event" if we use data urls
371-
let browserName = session.getCapabilities().get('browserName');
372-
if (browserName === 'internet explorer' || browserName === 'safari' ||
373-
browserName === 'phantomjs' || browserName === 'MicrosoftEdge') {
374-
this.resetUrl = 'about:blank';
375-
}
376-
return this;
377-
});
378362

379363
this.trackOutstandingTimeouts_ = !opt_untrackOutstandingTimeouts;
380364
this.mockModules_ = [];
@@ -423,7 +407,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
423407
* Fork another instance of browser for use in interactive tests.
424408
*
425409
* @example
426-
* var forked = await browser.forkNewDriverInstance().ready;
410+
* var forked = await browser.forkNewDriverInstance();
427411
* await forked.get('page1'); // 'page1' gotten by forked browser
428412
*
429413
* @param {boolean=} useSameUrl Whether to navigate to current url on creation
@@ -433,8 +417,9 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
433417
*
434418
* @returns {ProtractorBrowser} A browser instance.
435419
*/
436-
forkNewDriverInstance(useSameUrl?: boolean, copyMockModules?: boolean, copyConfigUpdates = true):
437-
ProtractorBrowser {
420+
async forkNewDriverInstance(
421+
useSameUrl?: boolean, copyMockModules?: boolean,
422+
copyConfigUpdates = true): Promise<ProtractorBrowser> {
438423
return null;
439424
}
440425

@@ -456,7 +441,7 @@ export class ProtractorBrowser extends AbstractExtendedWebDriver {
456441
* await browser.get('page2'); // 'page2' gotten by restarted browser
457442
*
458443
* // Running against forked browsers
459-
* var forked = await browser.forkNewDriverInstance().ready;
444+
* var forked = await browser.forkNewDriverInstance();
460445
* await fork.get('page1');
461446
* fork = await fork.restart();
462447
* await fork.get('page2'); // 'page2' gotten by restarted fork

lib/driverProviders/attachSession.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ export class AttachSession extends DriverProvider {
3535
* @public
3636
* @return {WebDriver} webdriver instance
3737
*/
38-
getNewDriver(): WebDriver {
38+
async getNewDriver(): Promise<WebDriver> {
3939
const httpClient = new http.HttpClient(this.config_.seleniumAddress);
4040
const executor = new http.Executor(httpClient);
41-
const newDriver = WebDriver.attachToSession(executor, this.config_.seleniumSessionId, null);
41+
const newDriver =
42+
await WebDriver.attachToSession(executor, this.config_.seleniumSessionId, null);
4243
this.drivers_.push(newDriver);
4344
return newDriver;
4445
}

lib/driverProviders/direct.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Direct extends DriverProvider {
4949
* @override
5050
* @return webdriver instance
5151
*/
52-
getNewDriver(): WebDriver {
52+
async getNewDriver(): Promise<WebDriver> {
5353
let driver: WebDriver;
5454

5555
switch (this.config_.capabilities.browserName) {
@@ -74,7 +74,7 @@ export class Direct extends DriverProvider {
7474
}
7575

7676
let chromeService = new ChromeServiceBuilder(chromeDriverFile).build();
77-
driver = DriverForChrome.createSession(
77+
driver = await DriverForChrome.createSession(
7878
new Capabilities(this.config_.capabilities), chromeService);
7979
break;
8080
case 'firefox':
@@ -98,7 +98,7 @@ export class Direct extends DriverProvider {
9898
}
9999

100100
let firefoxService = new FirefoxServiceBuilder(geckoDriverFile).build();
101-
driver = DriverForFirefox.createSession(
101+
driver = await DriverForFirefox.createSession(
102102
new Capabilities(this.config_.capabilities), firefoxService);
103103
break;
104104
default:

lib/driverProviders/driverProvider.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import {Builder, WebDriver} from 'selenium-webdriver';
77

88
import {BlockingProxyRunner} from '../bpRunner';
99
import {Config} from '../config';
10+
import {BrowserError} from '../exitCodes';
11+
import {Logger} from '../logger';
1012

13+
let logger = new Logger('driverProvider');
1114
export abstract class DriverProvider {
1215
drivers_: WebDriver[];
1316
config_: Config;
@@ -42,7 +45,7 @@ export abstract class DriverProvider {
4245
* @public
4346
* @return webdriver instance
4447
*/
45-
getNewDriver() {
48+
async getNewDriver() {
4649
let builder: Builder;
4750
if (this.config_.useBlockingProxy) {
4851
builder =
@@ -56,7 +59,12 @@ export abstract class DriverProvider {
5659
if (this.config_.disableEnvironmentOverrides === true) {
5760
builder.disableEnvironmentOverrides();
5861
}
59-
let newDriver = builder.build() as WebDriver;
62+
let newDriver: WebDriver;
63+
try {
64+
newDriver = await builder.build();
65+
} catch (e) {
66+
throw new BrowserError(logger, (e as Error).message);
67+
}
6068
this.drivers_.push(newDriver);
6169
return newDriver;
6270
}
@@ -72,6 +80,7 @@ export abstract class DriverProvider {
7280
if (driverIndex >= 0) {
7381
this.drivers_.splice(driverIndex, 1);
7482
try {
83+
await driver.close();
7584
await driver.quit();
7685
} catch (err) {
7786
// This happens when Protractor keeps track of all the webdrivers

lib/driverProviders/mock.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Mock extends DriverProvider {
3838
* @override
3939
* @return webdriver instance
4040
*/
41-
getNewDriver(): WebDriver {
41+
async getNewDriver(): Promise<WebDriver> {
4242
let mockSession = new Session('test_session_id', {});
4343
let newDriver = new WebDriver(mockSession, new MockExecutor());
4444
this.drivers_.push(newDriver);

lib/runner.ts

+28-52
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {EventEmitter} from 'events';
22
// TODO(cnishina): remove when selenium webdriver is upgraded.
3-
import {promise as wdpromise} from 'selenium-webdriver';
3+
import {promise as wdpromise, WebDriver} from 'selenium-webdriver';
44
import * as util from 'util';
55

66
import {ProtractorBrowser} from './browser';
@@ -54,9 +54,6 @@ export class Runner extends EventEmitter {
5454
nodedebug.on('exit', () => {
5555
process.exit(1);
5656
});
57-
this.ready_ = new Promise(resolve => {
58-
setTimeout(resolve, 1000);
59-
});
6057
}
6158

6259
if (config.capabilities && config.capabilities.seleniumAddress) {
@@ -206,9 +203,9 @@ export class Runner extends EventEmitter {
206203
* @return {Protractor} a protractor instance.
207204
* @public
208205
*/
209-
createBrowser(plugins: any, parentBrowser?: ProtractorBrowser): any {
206+
async createBrowser(plugins: any, parentBrowser?: ProtractorBrowser): Promise<any> {
210207
let config = this.config_;
211-
let driver = this.driverprovider_.getNewDriver();
208+
let driver = await this.driverprovider_.getNewDriver();
212209

213210
let blockingProxyUrl: string;
214211
if (config.useBlockingProxy) {
@@ -258,58 +255,40 @@ export class Runner extends EventEmitter {
258255
browser_.ng12Hybrid = initProperties.ng12Hybrid;
259256
}
260257

261-
browser_.ready =
262-
browser_.ready
263-
.then(() => {
264-
return browser_.waitForAngularEnabled(initProperties.waitForAngularEnabled);
265-
})
266-
.then(() => {
267-
return driver.manage().timeouts().setScriptTimeout(
268-
initProperties.allScriptsTimeout || 0);
269-
})
270-
.then(() => {
271-
return browser_;
272-
});
258+
await browser_.waitForAngularEnabled(initProperties.waitForAngularEnabled);
259+
await driver.manage().timeouts().setScriptTimeout(initProperties.allScriptsTimeout || 0);
273260

274261
browser_.getProcessedConfig = () => {
275262
return Promise.resolve(config);
276263
};
277264

278-
browser_.forkNewDriverInstance =
279-
(useSameUrl: boolean, copyMockModules: boolean, copyConfigUpdates = true) => {
280-
let newBrowser = this.createBrowser(plugins);
281-
if (copyMockModules) {
282-
newBrowser.mockModules_ = browser_.mockModules_;
283-
}
284-
if (useSameUrl) {
285-
newBrowser.ready = newBrowser.ready
286-
.then(() => {
287-
return browser_.driver.getCurrentUrl();
288-
})
289-
.then((url: string) => {
290-
return newBrowser.get(url);
291-
})
292-
.then(() => {
293-
return newBrowser;
294-
});
295-
}
296-
return newBrowser;
297-
};
298-
299-
let replaceBrowser = () => {
300-
let newBrowser = browser_.forkNewDriverInstance(false, true);
265+
browser_.forkNewDriverInstance = async(
266+
useSameUrl: boolean, copyMockModules: boolean, copyConfigUpdates = true): Promise<any> => {
267+
let newBrowser = await this.createBrowser(plugins);
268+
if (copyMockModules) {
269+
newBrowser.mockModules_ = browser_.mockModules_;
270+
}
271+
if (useSameUrl) {
272+
const currentUrl = await browser_.driver.getCurrentUrl();
273+
await newBrowser.get(currentUrl);
274+
}
275+
return newBrowser;
276+
};
277+
278+
let replaceBrowser = async () => {
279+
let newBrowser = await browser_.forkNewDriverInstance(false, true);
301280
if (browser_ === protractor.browser) {
302281
this.setupGlobals_(newBrowser);
303282
}
304283
return newBrowser;
305284
};
306285

307-
browser_.restart = () => {
286+
browser_.restart = async () => {
308287
// Note: because tests are not paused at this point, any async
309288
// calls here are not guaranteed to complete before the tests resume.
310-
return this.driverprovider_.quitDriver(browser_.driver)
311-
.then(replaceBrowser)
312-
.then(newBrowser => newBrowser.ready);
289+
const restartedBrowser = await replaceBrowser();
290+
await this.driverprovider_.quitDriver(browser_.driver);
291+
return restartedBrowser;
313292
};
314293

315294
return browser_;
@@ -352,18 +331,15 @@ export class Runner extends EventEmitter {
352331
this.config_.useBlockingProxy = true;
353332
}
354333

355-
// 0) Wait for debugger
356-
await Promise.resolve(this.ready_);
357-
358334
// 1) Setup environment
359335
// noinspection JSValidateTypes
360336
await this.driverprovider_.setupEnv();
361337

362338
// 2) Create a browser and setup globals
363-
browser_ = this.createBrowser(plugins);
339+
browser_ = await this.createBrowser(plugins);
364340
this.setupGlobals_(browser_);
365341
try {
366-
const session = await browser_.ready.then(browser_.getSession);
342+
const session = await browser_.getSession();
367343
logger.debug(
368344
'WebDriver session successfully started with capabilities ' +
369345
util.inspect(session.getCapabilities()));
@@ -403,9 +379,9 @@ export class Runner extends EventEmitter {
403379

404380
if (this.config_.restartBrowserBetweenTests) {
405381
// TODO(sjelin): replace with warnings once `afterEach` support is required
406-
let restartDriver = () => {
382+
let restartDriver = async () => {
407383
if (!this.frameworkUsesAfterEach) {
408-
this.restartPromise = Promise.resolve(browser_.restart());
384+
this.restartPromise = await browser_.restart();
409385
}
410386
};
411387
this.on('testPass', restartDriver);

0 commit comments

Comments
 (0)