I'm using protractor and when I run my tests on browserstack I receive the following error
StaleElementReferenceError: stale element reference: element is not attached to the page document
or depending on what I do in the beforeAll
Error: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By.cssSelector ...
Here is the code snippet causing the error:
describe('...', () => {
it('...', () => {
expect(element.all(by.css(...)).count()).toBe(9);
expect(element.all(by.css('.items').get(0).isDisplayed()).toBeTruthy();
});
}
describe('', () => {
beforeAll((/* done */) => {
element(by.css('.go-home').click(); // .then(done);
//browser.driver.get('/');//.then(done);
});
...
});
For some reason the beforeAll
continues and changes the url, while the previous it
is still running (I guess based on the error).
Now, I managed to hack this such that is works. I've added the done
to the it
as follows
describe('...', () => {
it('...', (done) => {
expect(element.all(by.css(...).count()).toBe(9);
element.all(by.css(...)).get(0).isDisplayed().then((state) => {
expect(state).toBeTruthy();
done();
});
});
}
describe('', () => {
beforeAll(() => {
element(by.css('.go-home').click(); // works
//browser.driver.get('/'); // still fails
});
...
});
Now it works. However if I use browser.driver.get('/')
it fails again.
Normally I don't have to add done
to my it
s so my question is: What is going wrong here ? Any help would be appreciated
UPDATE: protractor.config.js:
exports.config = {
chromeDriver: '../node_modules/protra...medriver_2.25',
seleniumServerJar: '../node_...-server-standalone-2.53.1.jar',
exclude: [],
specs: [
'../test/e2e/**/*.js'
],
multiCapabilities: [
{
build: 'test',
project: 'ABC',
browserName: 'firefox',
//browserName: 'chrome',
os: 'Windows',
os_version: '10',
directConnect: true
}],
debug: true,
maxSessions: 1,
framework: 'jasmine2',
onPrepare: function () {
browser.driver.manage().window().setSize(1024, 768);
// Register helpers
require('../test/framework/jasmine2');
var disableNgAnimate = function () {
angular
.module('disableNgAnimate', [])
.run(['$animate', function ($animate) {
$animate.enabled(false);
}]);
};
var disableCssAnimate = function () {
angular
.module('disableCssAnimate', [])
.run(function () {
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
'-webkit-transition: none !important;' +
'-moz-transition: none !important' +
'-o-transition: none !important' +
'-ms-transition: none !important' +
'transition: none !important' +
'}';
document.getElementsByTagName('head')[0].appendChild(style);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);
browser.addMockModule('disableCssAnimate', disableCssAnimate);
}
};
The way I understand the
then()
-functionality, it starts an async task. Therefore any line of code outside thethen()
-function will be continued as soon asthen()
is entered. Read more about here, here and here.Further exist several challenges around
browser.get()
andbrowser.driver.get()
in terms of promise-resolving, as it's not clear, whether the page to load can be synchronized with the ControlFlow. Therefore abrowser.driver.get()
isn't always forcing Protractor to wait. Read more about here and hereYour test now combines these two issues in a way.
I suggest to try
browser.waitForAngular();
in your solution to trigger protractor to actually wait until all promises are resolved: