Closed gologox closed 8 years ago
Oh, that's weird. Your script seems to be calling waitForAngular
on a non-angular page (or on an angular page but before angular has loaded). Could you let us see your test script?
describe('My Account - Address Update', function() {
//Set window size
var width = 1600;
var height = 875;
browser.driver.manage().window().setSize(width, height);
it('should resolve my account landing page', function(done) {
browser.driver.get(url, globalTimeout).then( function() {
browser.getTitle().then(function(title) {
if (title == 'Madison Reed - Healthy, Professional-Grade Hair Color and Care') {
done();
} else {
done(new Error('Could not resolve MR address.'));
}
});
});
});
it('should create new account', function(done) {
element.all(by.css('.sign_in')).last().click();
element(by.cssContainingText('a', 'Create Account')).click();
input = element(by.css('#create_account_email'));
input.sendKeys(userData.email);
input = element(by.css('#create_account_password'));
input.sendKeys(userData.pass);
element(by.cssContainingText('.mr-btn', 'sign up')).click().then(function() {
if (browser.browserName == 'safari') {
browser.driver.get(url + '/account');
} else {
element(by.cssContainingText('.nav-item.hide-mobile', 'My Account')).click();
element.all(by.css('[href="/account"]')).last().click();
}
browser.getTitle().then( function(title) {
if (title != 'My Account' && title != 'Madison Reed') {
done(new Error('Could not create a new account.'));
} else {
done();
}
});
});
});
it('should navigate to the Shipping/Billing tab and click on Add a New Address', function(done) {
element(by.css('a[href="/account/shipping-billing"]')).click();
element(by.cssContainingText('.button', 'add a new address')).click();
done();
});
it('should fill out the address input fields', function(done) {
var input = element(by.model('shipAddress.first_name'));
input.sendKeys(userData.first);
input = element(by.model('shipAddress.last_name'));
input.sendKeys(userData.last);
input = element(by.model('shipAddress.street_1'));
input.sendKeys(userData.address_1);
input = element(by.model('shipAddress.street_2'));
input.sendKeys(userData.address_2);
input = element(by.model('shipAddress.post_code'));
input.sendKeys(userData.zip);
input = element(by.model('shipAddress.phone'));
input.sendKeys(userData.phone);
done();
});
it('should save all the input information', function(done) {
element.all(by.cssContainingText('.mr-button.save-button', 'Save')).first().click();
done();
});
it('should validate the address', function(done) {
//Construct validation array with local values
var scriptData = [];
scriptData.push(userData.first + ' ' + userData.last);
scriptData.push((userData.address_1 + ' ' + userData.address_2).toUpperCase());
scriptData.push((userData.city + ', ' + userData.state + ' ' + userData.zip).toUpperCase());
//sub-mask formatting for phone number
var num = userData.phone.split('');
num.splice(0, 0, '(');
num.splice(4, 0, ') ');
num.splice(8, 0, '-');
scriptData.push(num.join(''));
num = 0;
element.all(by.css('.address.ng-scope div')).each(function(field) {
field.getText().then(function(text) {
if (num <= 3) {
expect(text).toBe(scriptData[num]);
num++;
}
});
}).then(function() {
done();
});
});
it('should validate the checkboxes', function(done) {
element(by.model('address.is_default_shipping')).isSelected().then(function(selected) {
expect(selected).toBe(true);
done();
});
});
it('should send session data to Sauce, if not already', function(done) {
if (typeof(process.env['SauceOnDemandSessionID']) == 'undefined') {
browser.getSession().then(function(session) {
process.env['SauceOnDemandSessionID'] = session.getId();
done();
});
} else {
done();
}
});
});
Do you have a stack trace for the angular could not be found on the window
error message? In particular, it'd be great to know which line in the test code is executing the waitForAngular
I blacked it out in the screenshot, but the command that was sent to Sauce before it timed out was:
browser.driver.get(url, globalTimeout).then( function() {
\\
});
The stack trace is not helpful at all:
[chrome 41.0 Windows 7 #4] Failures:
[chrome 41.0 Windows 7 #4] 1) My Account - Address Update should resolve my account landing page
[chrome 41.0 Windows 7 #4] Message:
[chrome 41.0 Windows 7 #4] Failed: Error while waiting for Protractor to sync with the page: "root element (body) has no injector. this may mean it is not inside ng-app."
[chrome 41.0 Windows 7 #4] Stack:
[chrome 41.0 Windows 7 #4] Error: Failed: Error while waiting for Protractor to sync with the page: "root element (body) has no injector. this may mean it is not inside ng-app."
[chrome 41.0 Windows 7 #4] at Array.forEach (native)
[chrome 41.0 Windows 7 #4] at runMicrotasksCallback (node.js:337:7)
[chrome 41.0 Windows 7 #4] at process._tickCallback (node.js:355:11)
The page is indeed Angular as I have tested this script hundreds of times locally.
My concern is the timeouts, it does not seem to be waiting 30000ms for Angular to load.
Well, it probably is actually waiting 30000ms for Angular to load. browser.get()
is the function which waits for Angular to load, but the error message you're getting is from waitForAngular
. waitForAngular
waits for angular to have no outstanding asynchronous commands, but it assumes angular is already loaded on the page. So what appears to be going on is that somehow waitForAngular
is getting called before Angular has been loaded.
In other words, the error message isn't saying "We waited 30000ms for Angular to load and nothing showed up". It's saying "Angular was already supposed to have been loaded by this point in the execution and it hasn't been"
Here is the production version of the page the script is trying to render: https://www.madison-reed.com/
The only differences I can think of that I have made in my current setup from when I was working with 1.6.1 is:
The error messages I'm seeing seem to indicate that you're having these problems because you're using a non-angular page. Are you sure sync is off at all the times it needs to be?
Also, can you generate these failures locally or only on sauce?
I was able to reproduce these errors locally when our sandboxed server is slow. When the server is very responsive, the scripts pass 100% of the time. I included the URL(https://www.madison-reed.com/) to the page above, as you can see in the source, Angular is present. And yes, one of my script turns off sync well into the script, not at the beginning when all the scripts are performing a browser.driver.get()
I found something that may be related to the problem. The way Protractor is handling page redirects is very fragile.
e.g script:
var url = 'https://www.madison-reed.com/product/root-touch-up/';
describe("Render product page", function() {
it('should retrieve web page title', function(done) {
browser.driver.get(url).then(function() {
browser.getTitle().then(function(title) {
expect(title).toBe('Madison Reed');
done();
});
});
});
});
When it tries to load 'https://www.madison-reed.com/product/root-touch-up/', our routing in express redirects them to a landing page at 'https://www.madison-reed.com/welcome/1', so initially waitForAngular returns true and then when the redirect occurs, in which Angular being present is no longer the case, but it's on the sync phase.
I am not sure how Protractor is supposed to handle these situations.
To test this, I have updated my tests to access the landing pages themselves, that have no redirects and it has improved my results.
Oh, that would be a problem. It waits for angular in browser.get()
, but after that point it just assumes Angular will stay loaded until the next browser.get()
.
So if you remove all the redirects you can't reproduce the problem then?
I could not. But then I downgraded to 2.0.0 and put framework: "jasmine", in my config to solve this issue: #1095
Now this is happening: http://screencast.com/t/wEGq1nCFb
As you can see, I have a 30000ms timeout and yet it wasn't able to find Angular in a 10000ms window. Which goes back to my initial concern.
Ok, so I guess I haven't been clear, but the fact that your timeout is 30000ms is actually irrelevant because that error message doesn't mean what you think it means.
What's going on is this:
browser.get()
to a pageA longer wait wouldn't help, because Protractor is actually finding Angular back in step 3, but for the wrong page.
@juliemr Do you have any thoughts on what to do with this sort of client-side navigation?
In my latest screenshot, there is no redirect, I am getting a 200 from the server for http://localhost:3000/product/varese-blonde, equivalent to https://www.madison-reed.com/product/varese-blonde
I will continue to investigate. Thanks.
Oh, sorry, I misunderstood your previous comment
If changing config option 'jasmine2' to 'jasmine' helped to @gologox, it might be related to issue described in a comment https://github.com/angular/protractor/issues/1095#issuecomment-107103042.
Hi guys, I am having the same redirect issue that would cause the angular not found issue via cucumber-js. Have anyone encountered the issue via cucubmer.js?
I've tried to reproduce and can't - I think this issue is just stale. Please open a new one if there is still a reproducible problem. Thanks!
Protractor 2.1.0 I've added the following to my conf:
The reason for this is because Sauce instances take like 1,000 years to load.
But Protractor begins to check for Angular ~10000ms into the test: http://screencast.com/t/Wai11lzcLliZ