We have several tests that make use of executeAsyncScript. When we started running the tests on Firefox, we noticed that they failed with the error message
Expected async operation, instead received: {}
After a little bit of digging, it seems to be an issue Firefox and how ExecuteAsyncScript checks for whether an object is a promise.
I could create a simple Maven project that illustrates the cause of the error
Unpack the file, cd into the directory, make sure you have Chrome and Firefox installed on your system, then run mvn test. This runs the same 2 tests, once with Firefox and once with Chrome. Note that it fails with Firefox.
For reference, on my system I've got Chrome Version 99.0.4844.74 (Official Build) (64-bit) and Firefox 98.0.2 (64-bit) Tested with Ubuntu and Windows, so doesn't seem to be OS-specific.
To summarize what happens, as far as I understand it, is as follows:
The ExecuteAsyncScript command uses Promise.resolve(p) === p to check whether an object is a promise.
When you have an HTML page with something like window.getPromise = () => Promise, then use the WebDriver to execute JavaScriptExecutor#executeAsyncScript("arguments[0](Promise === window.getPromise())"), you get false. The promise constructor from the HTML page and the Promise constructor from the script we run via WebDriver appear to be different.
Similarly, Promise.resolve(p) === p fails when p is a Promise that was obtained from a function in a script block in the HTML page.
It seems that FF uses two different realms for the script in the HTML page and for the script executed via WebDriver?
So it seems like we might need another way to check for whether an object is a Promise, though I'm not sure how that check could look like.
This single-line NPM module checks whether a value is truthy, an object or a function, and that is has a then property which is a function.
Angular has a utility method that just checks for truthiness and a then property which is a function.
A comment on this stackoverflow answer also warns about using Promise.resolve(p) === p as it wouldn't work for different realms (which I suspect is the issue here).
We have several tests that make use of executeAsyncScript. When we started running the tests on Firefox, we noticed that they failed with the error message
After a little bit of digging, it seems to be an issue Firefox and how ExecuteAsyncScript checks for whether an object is a promise.
I could create a simple Maven project that illustrates the cause of the error
selenese-java-exec-async-ff.zip
Unpack the file, cd into the directory, make sure you have Chrome and Firefox installed on your system, then run
mvn test
. This runs the same 2 tests, once with Firefox and once with Chrome. Note that it fails with Firefox.For reference, on my system I've got Chrome
Version 99.0.4844.74 (Official Build) (64-bit)
and Firefox98.0.2 (64-bit)
Tested with Ubuntu and Windows, so doesn't seem to be OS-specific.To summarize what happens, as far as I understand it, is as follows:
window.getPromise = () => Promise
, then use the WebDriver to executeJavaScriptExecutor#executeAsyncScript("arguments[0](Promise === window.getPromise())")
, you getfalse
. The promise constructor from the HTML page and the Promise constructor from the script we run via WebDriver appear to be different.Promise.resolve(p) === p
fails whenp
is a Promise that was obtained from a function in a script block in the HTML page.So it seems like we might need another way to check for whether an object is a Promise, though I'm not sure how that check could look like.
then
property which is a function.then
property which is a function.Promise.resolve(p) === p
as it wouldn't work for different realms (which I suspect is the issue here).