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

Commit f42e0b3

Browse files
authored
fix(globals): Resolve exported globals dynamically. (#3716)
fixes #3677 Because globals are set in the runner, they may be undefined at import time. Also, the browser global object will change if browser.reset() is called. By making these globals exported as properties, they will be resolved dynamically. This also fixes issues importing protractor in config files written in typescript, since the globals are resolved at call time instead of at import time. Note that until the Runner calls setupGlobals_, these exports will be undefined. That's just the nature of these objects, though, and the global objects have the same behavior.
1 parent a1c8a23 commit f42e0b3

File tree

4 files changed

+44
-19
lines changed

4 files changed

+44
-19
lines changed

lib/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ export interface Config {
526526
/**
527527
* Set the randomization seed if randomization is turned on
528528
*/
529-
seed?: string,
529+
seed?: string,
530530
};
531531

532532
/**

lib/index.ts

+28-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export let utils = {
2323
firefox: require('selenium-webdriver/firefox'),
2424
http: require('selenium-webdriver/http'),
2525
remote: require('selenium-webdriver/remote')
26-
}
26+
};
2727

2828
export let Command = require('selenium-webdriver/lib/command').Command;
2929
export let CommandName = require('selenium-webdriver/lib/command').Name;
@@ -32,12 +32,30 @@ export let CommandName = require('selenium-webdriver/lib/command').Name;
3232
// We base this on NodeJS `global` because we do not want to mask
3333
// with a different instance of Protractor if the module is
3434
// installed both globally and locally.
35-
export let protractor: Ptor = (global as any)['protractor'];
36-
export let browser: ProtractorBrowser = protractor ? protractor.browser : undefined;
37-
export let $: (search: string) => ElementFinder = protractor ? protractor.$ : undefined;
38-
export let $$: (search: string) => ElementArrayFinder = protractor ? protractor.$$ : undefined;
39-
export let element: ElementHelper = protractor ? protractor.element : undefined;
40-
export let By: ProtractorBy = protractor ? protractor.By : undefined;
41-
export let by: ProtractorBy = protractor ? protractor.by : undefined;
42-
export let ExpectedConditions: ProtractorExpectedConditions =
43-
protractor ? protractor.ExpectedConditions : undefined;
35+
36+
// Because these properties are set dynamically by the runner in setupGlobals_, they are not
37+
// guaranteed to be created at import time. Also, the browser object can change if browser.reset()
38+
// is called. Thus, we export these as properties so they will be resolved dynamically.
39+
export declare let protractor: Ptor;
40+
Object.defineProperty(exports, 'protractor', {get: () => (global as any)['protractor']});
41+
42+
function registerGlobal(name: string) {
43+
Object.defineProperty(
44+
exports, name, {get: () => exports.protractor ? exports.protractor[name] : undefined});
45+
}
46+
47+
export declare let browser: ProtractorBrowser;
48+
export declare let $: (search: string) => ElementFinder;
49+
export declare let $$: (search: string) => ElementArrayFinder;
50+
export declare let element: ElementHelper;
51+
export declare let By: ProtractorBy;
52+
export declare let by: ProtractorBy;
53+
export declare let ExpectedConditions: ProtractorExpectedConditions;
54+
55+
registerGlobal('browser');
56+
registerGlobal('$');
57+
registerGlobal('$$');
58+
registerGlobal('element');
59+
registerGlobal('By');
60+
registerGlobal('by');
61+
registerGlobal('ExpectedConditions');

lib/runner.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,7 @@ export class Runner extends EventEmitter {
254254
// Note: because tests are not paused at this point, any async
255255
// calls here are not guaranteed to complete before the tests resume.
256256
this.driverprovider_.quitDriver(browser_.driver);
257-
// Copy mock modules, but do not navigate to previous URL.
258-
let forkBrowser = browser_.forkNewDriverInstance(false, true);
259-
260-
// Replace the items in browser_ but do not create a new object
261-
// since this will break typescript imports
262-
for (let item in forkBrowser) {
263-
browser_[item] = forkBrowser[item];
264-
}
257+
browser_ = browser_.forkNewDriverInstance(false, true);
265258
this.setupGlobals_(browser_);
266259
};
267260

spec/basic/restart_spec.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
describe('browser.restart', function() {
2+
it('doesn\'t break ignoreSynchronization', function() {
3+
browser.get('index.html#/polling');
4+
browser.restart();
5+
6+
browser.ignoreSynchronization = true;
7+
// Get a non-angular page. It shouldn't fail if ignoreSynchronization is on.
8+
browser.get('https://google.com/');
9+
});
10+
11+
afterAll(() => {
12+
browser.ignoreSynchronization = false;
13+
});
14+
});

0 commit comments

Comments
 (0)