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 functions#
Following functions can be used for running js from a test:
executeScript(stringScript, ...args)
executeAsyncScript(stringScript, ...args)The provided
jsscript 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)executeScriptruns the script synchronously on the page which means it will block page execution until completed. The script can have areturnstatement to return a value. Test resumes only once the script has completed execution.executeAsyncScriptrun 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
executeAsyncScriptand 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 arguments#
You can supply any supported type in ZWL as arguments such as
string,listormap.listandmapare internally converted to be accessed asarrayandobjectrespectively injsscript.To pass an
element, just use theelementIdreturned byfindElementfunctions. ZWL internally convertselementIdto real element before passing to script. You may then access theelementin script as if it was retrieved using one of the element retrieval method such asdocument.getElementById(ID). If some of yourelementIds are kept in alistormap, 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 script#
Whatever 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 timeout#
A 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')