Running Javascript
In some use cases, it is useful to be able to run a piece of js
code in the browser from within a test. For instance, accessing window
object to perform actions like window.focus()
, retrieving viewport dimensions using window.innerHeight
/window.innerWidth
, running a plugin in form of js
snippet at the beginning of a test to see how the site function with that plugin installed.
In some lesser used cases, you may want to run custom js
code that take arguments from the test, do some process using the arguments and return some data to the test for validation. For example, setting a timeout to hide an element from page (whose reference was supplied from test) and return some data back to the test for validation. Doing these js tricks may not be required if your tests only purely validate actions that an end user can perform but still there may be some use cases depending on what you're trying to accomplish.
#
Script execution functionsFollowing functions can be used for running js
from a test:
executeScript(stringScript, ...args)
executeAsyncScript(stringScript, ...args)
The provided
js
script is injected into the page and executed as the body of an anonymous function. It's execution context will be the current browsing context.The arguments passed to a function can be accessed in the script using arguments object. See below:
button = findElement('Submit', by.text)executeScript('arguments[0].style.display = "none"', button)
executeScript
runs the script synchronously on the page which means it will block page execution until completed. The script can have areturn
statement to return a value. Test resumes only once the script has completed execution.executeAsyncScript
run the script asynchronously on the page and doesn't block page execution. If you're accessing network or need to run script with a delay, use this function. Note that even though it runs the script asynchronously on page, the test will block until the execution has finished.Being asynchronous, the test can't know about the completion on it's own. It's your responsibility to invoke a provided callback to inform the completion. The callback is injected as the last argument to
executeAsyncScript
and is used to return a value as well. See below:noteId = 150data = executeAsyncScript(` const callback = arguments[arguments.length - 1]; fetch('https://some-app.com/notes/' + arguments[0]) .then(data => callback(data)) .catch(error => callback(error));`, noteId)noteDescription = data.desc
We now know how to use the functions, access arguments and use callback. Let's understand what can be passed as arguments, how values returned from the script are resolved and few other things like adjusting timeout value.
#
Script function argumentsYou can supply any supported type in ZWL as arguments such as
string
,list
ormap
.list
andmap
are internally converted to be accessed asarray
andobject
respectively injs
script.To pass an
element
, just use theelementId
returned byfindElement
functions. ZWL internally convertselementId
to real element before passing to script. You may then access theelement
in script as if it was retrieved using one of the element retrieval method such asdocument.getElementById(ID)
. If some of yourelementId
s are kept in alist
ormap
, those are also converted recursively into a real elements before passing to script. You can assume that ZWL's elementIds are the real elements.
#
Returned values from scriptWhatever values you returned from script are converted back into ZWL supported types. For instance, if you return a js object
it will be converted to a map
, if array
it will be converted to a list
, if it's an element it will be converted into an elementId
.
Anything kept in js array
or object
will be recursively converted into ZWL types too so that you can use the returned values as you'd use any other value in a ZWL test.
#
Customizing script timeoutA script is allowed to run for a limited time before a timeout error occurs to prevent forever running scripts. If you think your scripts may take more time than the default timeout, you can check options to customize it.
#
Examples# Get window's viewport widthviewportHeight = executeScript('window.innerWidth')