Open dubzzz opened 6 years ago
Hi, @dubzzz ! I investigated this issue. Please take a look at my pull request https://github.com/dubzzz/protractor-move-async-await/pull/1/files. On my mind, tests became more stable. I'll investigate this deeper and then give you one more callback. Now for me it looks that problems are with usage of filter function.
@IgorSasovets indeed limiting the number of checkboxes makes it work but it was not my point.
My point is that control flow -based version took 27 seconds to run on my computer with no error at all.
While async/await -based timeouts quite immediately (4-5 s) with java.net.ConnectException: Connection refused: connect
.
By the way timeouts due to too long runs of protractor appear differently and refer to jasmine
.
It might be a port exhaustion issue: a lot of requests to Selenium server are sent in a short time, each one requesting a new port, the number of which is limited (to 65536 or something like that).
The difference might be that filter
sends all requests at once in the case of async /await promises whereas maybe the control flow version stacks them up and and then sends them one by one.
It's pretty easy to check using netstat
or whatever port analysis tool you like.
Just tried to run a netstat
command right after the run of the tests (either success or failure). I got barely the same number of lines TCP 127.0.0.1:4444 dev:49159 TIME_WAIT
for both promise manager and async/await (~2.2k lines like this).
You could override filter
function to force send requests sequential.
private makeFnSequential(func: any): any {
let promise: any = Promise.resolve();
return (...args) => {
promise = promise.then(() => {
return func(...args);
});
return promise;
};
}
}
use this method to wrap filterFn
.
Second option is to run your tests directly on chrome (add to config directConnect: true
). In that way selenium server will not use at all, so any java errors :)
It also works incorrectly with all functions which have concurrent requests. Such as map
, reduce
, each
, Promise.all
Handled this issue using selenium-server-standalone-3.4.0
webdriver-manager update --versions.standalone=3.4.0
@CrispusDH thanks a lot for your answer
Indeed there is the exact same issue when using Promise.all or other Promise.* methods able to run requests in parallel (when called with too many promises).
Nonetheless, I am a bit surprised that this problem did not occur when using the non async/await version of the code. It looks very strange and unintuitive that switching the flag SELENIUM_PROMISE_MANAGER for async/await reveals such issue.
For the moment, I moved to sequential implementations of Promise. and .filter in order to avoid such issue. I will have a look to directConnect
, it might be useful.
@avient Thanks for the information, I will give it a try ;)
@avient I still have the issue when forcing the use of 3.4.0 instead of my local version 3.11.0
Hi there,
With directConnect: true
the issue still persists - Error: ECONNREFUSED connect ECONNREFUSED
As @CrispusDH described all these functions could mess flaky connection with parallel requests. Even in async/await way .map
could hang up selenium easily.
As a workaround when you are working with an array of elements do sync loop
async getTextFromElements(): Promise<string[]> {
const arrayLocator: ElementArrayFinder = $$();
const array = new Array();
const allItems = await arrayLocator.asElementFinders_();
for (const elem of allItems) {
const elementText = await elem.getText();
array.push(elementText);
}
return array;
}
Dont forget to switch off SELENIUM_PROMISE_MANAGER
That is an issue in selenium-webdriver. Here is my patch to resolve it (only work in protractor/selenium-webdriver 3.6.0)
var fs = require('fs');
var httpIndexFile = 'node_modules/selenium-webdriver/http/index.js';
fs.readFile(httpIndexFile, 'utf8', function (err, data) {
if (err)
throw err;
var result = data.replace(/\(e.code === 'ECONNRESET'\)/g, "(e.code === 'ECONNRESET' || e.code === 'ECONNREFUSED')");
console.log(`Patching ${httpIndexFile}`)
fs.writeFileSync(httpIndexFile, result, 'utf8');
});
Also you can try my another patch for chromeDriver persistence connection issue. I don't have problem for a while after apply both patch
var chromeFile = 'node_modules/selenium-webdriver/chrome.js';
fs.readFile(chromeFile, 'utf8', function (err, data) {
if (err)
throw err;
var result = data.replace(/new http.HttpClient\(url\)/g, "new http.HttpClient(url, new (require('http').Agent)({ keepAlive: true }))");
console.log(`Patching ${chromeFile}`)
fs.writeFileSync(chromeFile, result, 'utf8');
});
@awarecan Thank you, I had been thinking of doing a similar monkey patch for the TCP connection persistence problem, and them thrilled to see this one line edit addresses both problems.
@awarecan Thanks, your work around is pretty easy and more important it does what is supposed to
@awarecan Has this workaround been integrated as a fix in any version of selenium webdriver? Or are there plans to do so?
@disophisis the 2nd patch just got merged few days ago. Don't know when it will be released. No update for the first patch.
@dubzzz
Hi,
I have the same issue as you. May I ask how you implement the sequential .map or .filter. I tried for-loop, but I am still testing if it works. I am not sure if I implemented it correctly. It is very tricky.
Thanks.
Any update?
@andredesousa no update and protractor is dying. My two patches worked very well in last few years.
You can copy my patches into a js file, for example, scripts/postinstall.js
, then add following code block to your package.json
"scripts": {
"postinstall": "node scripts/postinstall.js",
},
@awarecan Thank you. I had only used the last script, but both are required. My mistake.
Bug report
v8.5.0
5.1.0
1.6.7
Chrome 64.0.3282.140
Windows 7
While trying to move away from the promise manager of Selenium, I encountered new random failures which were not occurring before. After analyze it appeared that it might be linked to the
filter
function offered by Protractor.Here is an extract of the configuration and scripts I am using. All the code is available on https://github.com/dubzzz/protractor-move-async-await. The localhost:3000 exposes the todolist example of AngularJS official website with a list of a thousand entries.
Using the promise manager:
conf.js
todo-spec.js
Using async/await:
conf.js
todo-spec.js
The asynchronous version failed with the following error:
The full proof off concept is available on my personal Github at https://github.com/dubzzz/protractor-move-async-await
Is the bug coming from an issue in my configuration or is there a real issue?
Thanks in advance