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

Commit 21b176e

Browse files
committed
feat(ngUpgrade): Auto detect ngUpgrade apps and make the ng12Hybrid flag unnecessary for most users
1 parent c9fad62 commit 21b176e

File tree

4 files changed

+80
-44
lines changed

4 files changed

+80
-44
lines changed

lib/browser.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,25 @@ export class ProtractorBrowser extends Webdriver {
302302
this.ready = null;
303303
this.plugins_ = new Plugins({});
304304
this.resetUrl = DEFAULT_RESET_URL;
305-
this.ng12Hybrid = false;
306305
this.debugHelper = new DebugHelper(this);
307306

307+
var ng12Hybrid_ = false;
308+
Object.defineProperty(this, 'ng12Hybrid', {
309+
get: function() {
310+
return ng12Hybrid_;
311+
},
312+
set: function(ng12Hybrid) {
313+
if (ng12Hybrid) {
314+
logger.warn(
315+
'You have set ng12Hybrid. As of Protractor 4.1.0, ' +
316+
'Protractor can automatically infer if you are using an ' +
317+
'ngUpgrade app (as long as ng1 is loaded before you call ' +
318+
'platformBrowserDynamic()), and this flag is no longer needed ' +
319+
'for most users');
320+
}
321+
ng12Hybrid_ = ng12Hybrid;
322+
}
323+
});
308324
this.driver.getCapabilities().then((caps: Capabilities) => {
309325
// Internet Explorer does not accept data URLs, which are the default
310326
// reset URL for Protractor.
@@ -450,7 +466,7 @@ export class ProtractorBrowser extends Webdriver {
450466
} else if (this.rootEl) {
451467
return this.executeAsyncScript_(
452468
clientSideScripts.waitForAngular, 'Protractor.waitForAngular()' + description,
453-
this.rootEl, this.ng12Hybrid);
469+
this.rootEl);
454470
} else {
455471
return this.executeAsyncScript_(
456472
clientSideScripts.waitForAllAngular2, 'Protractor.waitForAngular()' + description);

lib/clientsidescripts.js

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,37 @@ function wrapWithHelpers(fun) {
4444
* Asynchronous.
4545
*
4646
* @param {string} rootSelector The selector housing an ng-app
47-
* @param {boolean} ng12Hybrid Flag set if app is a hybrid of angular 1 and 2
4847
* @param {function(string)} callback callback. If a failure occurs, it will
4948
* be passed as a parameter.
5049
*/
51-
functions.waitForAngular = function(rootSelector, ng12Hybrid, callback) {
50+
functions.waitForAngular = function(rootSelector, callback) {
5251
var el = document.querySelector(rootSelector);
5352

5453
try {
55-
if (!ng12Hybrid && window.getAngularTestability) {
54+
if (window.angular && !(window.angular.version &&
55+
window.angular.version.major > 1)) {
56+
if (angular.getTestability) {
57+
angular.getTestability(el).whenStable(callback);
58+
} else if (angular.element(el).injector()) {
59+
angular.element(el).injector().get('$browser').
60+
notifyWhenNoOutstandingRequests(callback);
61+
} else {
62+
throw new Error('root element (' + rootSelector + ') has no injector.' +
63+
' this may mean it is not inside ng-app.');
64+
}
65+
} else if (window.getAngularTestability) {
5666
window.getAngularTestability(el).whenStable(callback);
57-
return;
58-
}
59-
if (!window.angular) {
67+
} else if (!window.angular) {
6068
throw new Error('window.angular is undefined. This could be either ' +
6169
'because this is a non-angular page or because your test involves ' +
6270
'client-side navigation, which can interfere with Protractor\'s ' +
6371
'bootstrapping. See http://git.io/v4gXM for details');
64-
}
65-
if (angular.getTestability) {
66-
angular.getTestability(el).whenStable(callback);
72+
} else if (window.angular.version == 2) {
73+
throw new Error('You appear to be using angular2, but window.' +
74+
'getAngularTestability was never set. This is all very strange.');
6775
} else {
68-
if (!angular.element(el).injector()) {
69-
throw new Error('root element (' + rootSelector + ') has no injector.' +
70-
' this may mean it is not inside ng-app.');
71-
}
72-
angular.element(el).injector().get('$browser').
73-
notifyWhenNoOutstandingRequests(callback);
76+
throw new Error('Cannot get testability API for unknown angular ' +
77+
'version "' + window.angular.version + '"');
7478
}
7579
} catch (err) {
7680
callback(err.message);
@@ -599,15 +603,36 @@ functions.testForAngular = function(attempts, ng12Hybrid, asyncCallback) {
599603
asyncCallback(args);
600604
}, 0);
601605
};
606+
var definitelyNg1 = !!ng12Hybrid;
607+
var definitelyNg2 = false;
602608
var check = function(n) {
603609
try {
604-
if (!ng12Hybrid && window.getAllAngularTestabilities) {
605-
callback({ver: 2});
606-
} else if (window.angular && window.angular.resumeBootstrap) {
607-
callback({ver: 1});
608-
} else if (n < 1) {
609-
if (window.angular) {
610+
// Figure out which version of angular we're waiting on
611+
if(!definitelyNg1 && !definitelyNg2) {
612+
if (window.angular && !(window.angular.version && window.angular.version.major > 1)) {
613+
definitelyNg1 = true;
614+
} else if (window.getAllAngularTestabilities) {
615+
definitelyNg2 = true;
616+
}
617+
}
618+
// See if our version of angular is ready
619+
if (definitelyNg1) {
620+
if (window.angular && window.angular.resumeBootstrap) {
621+
return callback({ver: 1});
622+
}
623+
} else if (definitelyNg2) {
624+
if (true /** ng2 has no resumeBootstrap() **/) {
625+
return callback({ver: 2});
626+
}
627+
}
628+
// Try again (or fail)
629+
if (n < 1) {
630+
if (definitelyNg1 && window.angular) {
610631
callback({message: 'angular never provided resumeBootstrap'});
632+
} else if (ng12Hybrid && !window.angular) {
633+
callback({message: 'angular 1 never loaded' +
634+
window.getAllAngularTestabilities ? ' (are you sure this app ' +
635+
'uses ngUpgrade? Try un-setting ng12Hybrid)' : ''});
611636
} else {
612637
callback({message: 'retries looking for angular exceeded'});
613638
}

spec/hybrid/async_spec.js

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
describe('async angular1/2 hybrid using ngUpgrade application', function() {
22
describe('@angular/upgrade/static', function() {
3-
beforeEach(function() {
3+
it('should be able to click buttons and wait for $timeout', function() {
44
browser.get('/upgrade');
5-
});
6-
7-
it('should set browser flag via config', function() {
8-
expect(browser.ng12Hybrid).toBe(true);
9-
});
105

11-
it('should be able to click buttons and wait for $timeout', function() {
126
var rootBtn = $$('my-app button').first();
137
expect(rootBtn.getText()).toEqual('Click Count: 0');
148
rootBtn.click();
@@ -25,23 +19,26 @@ describe('async angular1/2 hybrid using ngUpgrade application', function() {
2519
expect(ng1Btn.getText()).toEqual('Click Count: 1');
2620
});
2721

28-
it('should use the flag on the browser object', function() {
29-
browser.ng12Hybrid = false;
30-
browser.get('/ng2'); // will time out if Protractor expects hybrid
31-
browser.ng12Hybrid = true;
22+
it('should be able to automatically infer ng1/ng2/ngUpgrade', function() {
23+
browser.get('/upgrade');
24+
expect($('h1').getText()).toBe('My App');
25+
browser.get('/ng1');
26+
expect($$('h4').first().getText()).toBe('Bindings');
27+
browser.get('/upgrade');
28+
expect($('h1').getText()).toBe('My App');
29+
browser.useAllAngular2AppRoots();
30+
browser.get('/ng2');
31+
expect($('h1').getText()).toBe('Test App for Angular 2');
32+
browser.rootEl = 'body';
33+
browser.get('/upgrade');
34+
expect($('h1').getText()).toBe('My App');
3235
});
3336
});
3437

3538
describe('@angular/upgrade (not static)', function() {
36-
beforeEach(function() {
39+
it('should be able to click buttons and wait for $timeout', function() {
3740
browser.get('/upgrade?no_static');
38-
});
3941

40-
it('should set browser flag via config', function() {
41-
expect(browser.ng12Hybrid).toBe(true);
42-
});
43-
44-
it('should be able to click buttons and wait for $timeout', function() {
4542
var rootBtn = $$('my-app button').first();
4643
expect(rootBtn.getText()).toEqual('Click Count: 0');
4744
rootBtn.click();

spec/hybridConf.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,5 @@ exports.config = {
1414

1515
baseUrl: env.baseUrl,
1616

17-
rootElement: 'body',
18-
19-
ng12Hybrid: true
17+
rootElement: 'body'
2018
};

0 commit comments

Comments
 (0)