Custom commands
Loadero provides several predefined custom commands you can use in your test scripts which extend the built-in commands of the frameworks themselves. These commands provide additional functionality for various scenarios.
There are also packages available to support local script development by providing equivalent commands to the ones described on this page. However, not all of these commands will work the exact same way as they would on Loadero (e.g., the "Update Network" command is implemented as a no-op locally, so that using the command does not fail the test, if the script is copied over from Loadero). Make sure to check the documentation of the package. A link to the local development package for each language is provided below:
Set File
This custom command allows uploading a file to a file upload element.
Loadero sets up every participant's browser so that there are five files already prepared for use. These are intended for cases where the file content itself is not of importance and the actual objective is to simply check whether uploading a file of that size works at all or to evaluate how long it takes.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.setFile(selector: string, fileName: string);
The selector parameter specifies the selector of the input element, e.g.
input[type="file"], input#file-upload.
The fileName parameter specifies the name of the file you would like to
upload. To use files names more safely in code it's recommended to use the
predefined constants.
| Sample file | Constant | String value |
|---|---|---|
| 100 KB (PNG) | png100KB | "loaderoSample100KB.png" |
| 1 MB (PNG) | png1MB | "loaderoSample1MB.png" |
| 5 MB (PNG) | png5MB | "loaderoSample5MB.png" |
| 30 MB (PNG) | png30MB | "loaderoSample30MB.png" |
| 100 MB (TXT) | txt100MB | "loaderoSample100MB.txt" |
In case there is a need for other file format or size, feel free to contact us.
client => {
// Example of uploading a sample file into a file input field
client
// Open the DemoQA upload/download page
.url("https://demoqa.com/upload-download")
// Wait for up to 10s for the "Choose file" button to be visible
.waitForElementVisible("#uploadFile", 10 * 1000)
// Upload a Loadero sample image
// Approach #1: by using constants
.setFile("#uploadFile", loaderoConstants.sampleFiles.png100KB)
// Approach #2: by using a string value
.setFile("#uploadFile", "loaderoSample100KB.png")
.saveScreenshot("file_set.png");
}
Nightwatch.js has its own file upload method - uploadFile(), which relies on
access to the file system. Participants do not have access to the file system of
the server on which they are executing the test - they only have access to their
specific browser's context. The prepared files mentioned above and any files
downloaded during the test will be accessible within the browser's context, but
these files will only be accessible via the custom setFile() command.
setFile(By selector, String fileName);
The selector parameter specifies the selector of the input element, e.g.
input[type="file"], input#file-upload.
The fileName parameter specifies the name of the file you would like to
upload. To use files names more safely in code it's recommended to use the
getters.
| Sample file | Getter | String value |
|---|---|---|
| 100 KB (PNG) | getPNG100KB() | "loaderoSample100KB.png" |
| 1 MB (PNG) | getPNG1MB() | "loaderoSample1MB.png" |
| 5 MB (PNG) | getPNG5MB() | "loaderoSample5MB.png" |
| 30 MB (PNG) | getPNG30MB() | "loaderoSample30MB.png" |
| 100 MB (TXT) | getTXT100MB() | "loaderoSample100MB.txt" |
In case there is a need for other file format or size, feel free to contact us.
public void testUIWithLoadero() {
// Example of uploading a sample file into a file input field
// Open the DemoQA upload/download page
open("https://demoqa.com/upload-download");
E(byCssSelector("#uploadFile")).waitFor(10).untilIsVisible();
// Upload a Loadero sample image
// Approach #1: by using getters
setFile(
byCssSelector("#uploadFile"),
loaderoConstants.getSampleFiles().getPNG100KB()
);
// Approach #2: by using a string value
setFile(
byCssSelector("#uploadFile"),
"loaderoSample100KB.png"
);
E(byCssSelector("#app")).saveScreenshot("file_set.png");
}
def set_file(driver: TestUIDriver, element: Elements, file_name: str) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The element parameter specifies the input element. Note that this must be an
element, not its selector. E.g., input#file-upload will not work, but
E(driver, "css", "input#file-upload") will.
The file_name parameter specifies the name of the file you would like to
upload. To use files names more safely in code it's recommended to use the
predefined constants.
| Sample file | Constant | String value |
|---|---|---|
| 100 KB (PNG) | png_100KB | "loaderoSample100KB.png" |
| 1 MB (PNG) | png_1MB | "loaderoSample1MB.png" |
| 5 MB (PNG) | png_5MB | "loaderoSample5MB.png" |
| 30 MB (PNG) | png_30MB | "loaderoSample30MB.png" |
| 100 MB (TXT) | txt_100MB | "loaderoSample100MB.txt" |
In case there is a need for other file format or size, feel free to contact us.
def test(driver: TestUIDriver):
# Example of uploading a sample file into a file input field
# Open the DemoQA upload/download page
driver.navigate_to("https://demoqa.com/upload-download")
file_input_element = e(
driver, "css", "#uploadFile"
)
file_input_element.wait_until_visible()
# Upload a Loadero sample image
# Approach 1: by using constants
set_file(
driver, file_input_element, LOADERO_CONSTANTS.sample_files.png_100KB
)
# Approach 2: by using the string value
set_file(
driver, file_input_element, "loaderoSample100KB.png"
)
driver.save_screenshot("file_set.png")
Uploading a custom file
You can also host your own custom file somewhere that is accessible on the web,
navigate to that URL in the test and download the file from there. You will then
have that file accessible in the browser's downloads and be able to upload it
elsewhere (e.g., a mock ID photo), as long as you predict what that file's name
will be and reference it with the Downloads/ path prefix.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client => {
client
// Download an externally hosted file, in this example, an image from Wikimedia
.url("https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Dance_of_the_Village_Spirits.png/1024px-Dance_of_the_Village_Spirits.png?20250104134334=&download=")
.waitForDownloadFinished(
"1024px-Dance_of_the_Village_Spirits.png",
30 * 1000
)
// Navigate to the URL where you wish to upload the file
.url("https://demoqa.com/upload-download")
// Wait for up to 10s for the "Choose file" button to be visible
.waitForElementVisible("#uploadFile", 10 * 1000)
// Upload the previously downloaded file
.setFile(
"#uploadFile",
"Downloads/1024px-Dance_of_the_Village_Spirits.png"
)
.saveScreenshot("file_set.png");
}
public void testUIWithLoadero() {
// Download an externally hosted file, in this example, an image from Wikimedia
open("https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Dance_of_the_Village_Spirits.png/1024px-Dance_of_the_Village_Spirits.png?20250104134334=&download=");
waitForDownloadFinished(
"1024px-Dance_of_the_Village_Spirits.png",
30 * 1000
);
// Navigate to the URL where you wish to upload the file
open("https://demoqa.com/upload-download");
// Wait for up to 10s for the appropriate input element to be visible
E(byCssSelector("#uploadFile")).waitFor(10).untilIsVisible();
// Upload the previously downloaded file
setFile(
byCssSelector("#uploadFile"),
"Downloads/1024px-Dance_of_the_Village_Spirits.png"
);
E(byCssSelector("#app")).saveScreenshot("file_set.png");
}
def test(driver: TestUIDriver):
# Download an externally hosted file, in this example, an image from Wikimedia
driver.navigate_to("https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Dance_of_the_Village_Spirits.png/1024px-Dance_of_the_Village_Spirits.png?20250104134334=&download=")
wait_for_download_finished(
driver,
"1024px-Dance_of_the_Village_Spirits.png",
30 * 1000
)
# Navigate to the URL where you wish to upload the file
driver.navigate_to("https://demoqa.com/upload-download")
file_input_element = e(
driver, "css", "#uploadFile"
)
file_input_element.wait_until_visible()
# Upload the previously downloaded file
set_file(
driver,
file_input_element,
"Downloads/1024px-Dance_of_the_Village_Spirits.png"
)
driver.save_screenshot("file_set.png")
Set User Agent
This command changes the
User-Agent header
for outgoing requests and
navigator.userAgent.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.setUserAgent(userAgent: string);
The only parameter of this function is a string value that you want to have your user agent changed to.
To reset User-Agent to its default value, pass null as the new value.
Setting User-Agent to an empty string will actually update the User-Agent to
empty string.
client => {
// Example of setting custom user-agent
client
// Open page and create screenshot with default User-Agent
.url("https://www.bing.com/")
.waitForElementVisible("[type=search]", 10 * 1000)
.saveScreenshot("default_user_agent.png")
// Set custom User-Agent value
.setUserAgent("Custom User Agent")
// Refresh the page
.refresh()
// Wait for the page to load and create screenshot with changed User-Agent
.waitForElementVisible("[type=search]", 10 * 1000)
.saveScreenshot("custom_user_agent.png")
// Set User-Agent to empty string value
.setUserAgent("")
// Refresh the page
.refresh()
// Wait for the page to load and create screenshot with empty User-Agent
.waitForElementVisible("[type=search]", 10 * 1000)
.saveScreenshot("empty_user_agent.png")
// Reset User-Agent to original value
.setUserAgent(null)
// Refresh the page
.refresh()
// Wait for the page to load and create screenshot with reset User-Agent
.waitForElementVisible("[type=search]", 10 * 1000)
.saveScreenshot("reverted_user_agent.png");
}
setUserAgent(String userAgent);
The only parameter of this function is a string value that you want to have your user agent changed to.
To reset User-Agent to its default value, pass null as the new value.
Setting User-Agent to an empty string will actually update the User-Agent to
empty string.
public void testUIWithLoadero() {
// Example of setting custom user-agent
// Open page and create screenshot with default User-Agent
open("https://www.bing.com");
E(byCssSelector("[type=search]")).waitFor(10).untilIsVisible()
.saveScreenshot("default_user_agent.png");
// Set custom User-Agent value
setUserAgent("Custom User Agent");
// Refresh the page
getSelenideDriver().navigate().refresh();
// Wait for the page to load and create screenshot with changed User-Agent
E(byCssSelector("[type=search]")).waitFor(10).untilIsVisible()
.saveScreenshot("custom_user_agent.png");
// Set User-Agent to empty string value
setUserAgent("");
// Refresh the page
getSelenideDriver().navigate().refresh();
// Wait for the page to load and create screenshot with empty User-Agent
E(byCssSelector("[type=search]")).waitFor(10).untilIsVisible()
.saveScreenshot("empty_user_agent.png");
// Reset User-Agent to original value
setUserAgent(null);
// Refresh the page
getSelenideDriver().navigate().refresh();
// Wait for the page to load and create screenshot with reset User-Agent
E(byCssSelector("[type=search]")).waitFor(10).untilIsVisible()
.saveScreenshot("reset_user_agent.png");
}
def set_user_agent(driver: TestUIDriver, value: str or None = None) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The value parameter is a string value that you want to have your user agent
changed to.
To reset User-Agent to its default value, pass None as the new value.
Setting User-Agent to an empty string will actually update the User-Agent to
empty string.
def test(driver: TestUIDriver):
# Example of setting custom user-agent
# Open page and create screenshot with default User-Agent
driver.navigate_to("https://www.bing.com")
e(driver, "css", "[type=search]").wait_until_visible()
driver.save_screenshot("default_user_agent.png")
# Set custom User-Agent value and reload browser
set_user_agent(driver, "Custom User Agent")
driver.get_driver().refresh()
e(driver, "css", "[type=search]").wait_until_visible()
# Take screenshot with custom User Agent
driver.save_screenshot("custom_user_agent.png")
# Set empty user agent header
set_user_agent(driver, "")
# Wait for page to load and create screenshot
driver.get_driver().refresh()
e(driver, "css", "[type=search]").wait_until_visible()
driver.save_screenshot("empty_user_agent.png")
# Reset user agent header
set_user_agent(driver, None)
# Wait for page to load and create screenshot
driver.get_driver().refresh()
e(driver, "css", "[type=search]").wait_until_visible()
driver.save_screenshot("reset_user_agent.png")
User-Agent will revert to its original value in browser built-in pages and the WebRTC dump.
Update Network
This command allows updating network conditions dynamically during the test.
Predefined network condition usage
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.updateNetwork(networkMode: string);
The networkMode parameter specifies the network conditions that you would like
to switch to. Available network configurations and their associated
networkMode parameter values can be found
here. These network configurations can be
provided as a string value or as a constant. Constants pertaining to this
command can be accessed under loaderoConstants.network. Refer to the table below
for a full reference of the available constants.
| Network mode | Constant | String value |
|---|---|---|
| Default | default | "default" |
| 4G | mobile_4g | "4g" |
| 3.5G/HSPDA | mobile_hsdpa | "hsdpa" |
| 3G | mobile_3g | "3g" |
| GPRS | mobile_gprs | "gprs" |
| Edge | mobile_edge | "edge" |
| High jitter | jitter | "jitter" |
| High latency | latency | "latency" |
| Asymmetric | asymmetric | "asymmetric" |
| Satellite phone | satellite | "satellite" |
| 5% packetloss | packetloss5 | "5packet" |
| 10% packetloss | packetloss10 | "10packet" |
| 20% packetloss | packetloss20 | "20packet" |
| 50% packetloss | packetloss50 | "50packet" |
| 100% packetloss | packetloss100 | "100packet" |
| Custom | custom | "custom" |
client => {
// Example of updating network conditions via constant
client
.url("https://www.bing.com")
.waitForElementVisible("[type=search]", 10000)
.updateNetwork(loaderoConstants.network.mobile_3g);
}
client => {
// Example of updating network conditions via string value
client
.url("https://www.bing.com")
.waitForElementVisible("[type=search]", 10000)
.updateNetwork("3g");
}
updateNetwork(String networkMode);
The networkMode parameter specifies the network conditions that you would like
to switch to. Available network configurations and their associated
networkMode values can be found here or
they can be accessed using getters. Getters pertaining to this command can be
accessed under loaderoConstants.getNetwork(). Refer to the table below for a
full reference of the available constants.
| Network mode | Getter | String value |
|---|---|---|
| Default | getDefault() | "default" |
| 4G | getMobile4G() | "4g" |
| 3.5G/HSPDA | getMobileHSDPA() | "hsdpa" |
| 3G | getMobile3G() | "3g" |
| GPRS | getMobileGPRS() | "gprs" |
| Edge | getMobileEdge() | "edge" |
| High jitter | getJitter() | "jitter" |
| High latency | getLatency() | "latency" |
| Asymmetric | getAsymmetric() | "asymmetric" |
| Satellite phone | getSatellite() | "satellite" |
| 5% packetloss | getPacketLoss5() | "5packet" |
| 10% packetloss | getPacketLoss10() | "10packet" |
| 20% packetloss | getPacketLoss20() | "20packet" |
| 50% packetloss | getPacketLoss50() | "50packet" |
| 100% packetloss | getPacketLoss100() | "100packet" |
| Custom | getCustom() | "custom" |
public void testUIWithLoadero() {
// Example of updating network conditions using a getter
open("https://www.bing.com");
E(byCssSelector("[type=search]"))
.waitFor(10).untilIsVisible();
// Update network conditions to mobile 4G settings
updateNetwork(loaderoConstants.getNetwork().getMobile4G());
}
public void testUIWithLoadero() {
// Example of updating network conditions via string value
open("https://www.bing.com");
E(byCssSelector("[type=search]"))
.waitFor(10).untilIsVisible();
// Update network conditions to mobile 4G settings
updateNetwork("4g");
}
def update_network(
driver: TestUIDriver,
network_mode: str
) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The network_mode parameter specifies what network conditions you would like to
switch to. Available network configurations and their associated network_mode
values can be found here. These network
configurations can be provided as a string value or as a constant. Constants
pertaining to this command can be accessed via LOADERO_CONSTANTS.network.
Refer to the table below for a full reference of the available constants.
| Network mode | Constant | String value |
|---|---|---|
| Default | default | "default" |
| 4G | mobile_4g | "4g" |
| 3.5G/HSPDA | mobile_hsdpa | "hsdpa" |
| 3G | mobile_3g | "3g" |
| GPRS | mobile_gprs | "gprs" |
| Edge | mobile_edge | "edge" |
| High jitter | jitter | "jitter" |
| High latency | latency | "latency" |
| Asymmetric | asymmetric | "asymmetric" |
| Satellite phone | satellite | "satellite" |
| 5% packetloss | packetloss5 | "5packet" |
| 10% packetloss | packetloss10 | "10packet" |
| 20% packetloss | packetloss20 | "20packet" |
| 50% packetloss | packetloss50 | "50packet" |
| 100% packetloss | packetloss100 | "100packet" |
| Custom | custom | "custom" |
def test(driver: TestUIDriver):
# Example of updating network conditions via constant
driver.navigate_to("https://www.bing.com")
e(driver, "css", "[type=search]").wait_until_visible(seconds=10)
update_network(driver, LOADERO_CONSTANTS.network.mobile_3g)
def test(driver: TestUIDriver):
# Example of updating network conditions via string value
driver.navigate_to("https://www.bing.com")
e(driver, "css", "[type=search]").wait_until_visible(seconds=10)
update_network(driver, "3g")
Custom network condition usage
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
It is possible to also supply the command with a configuration object that
explicitly defines various aspects of network quality. This object is considered
only if the provided networkMode value is "custom", otherwise it will be
ignored.
client.updateNetwork(networkMode: string, config: object);
The config object is effectively a map between configuration fields and the
values you want to set for them. The table below lists the fields you can
configure, where the JSON key column refers to the name of the field.
It is possible to also supply the command with a configuration object that explicitly defines various aspects of network quality, instead of using one of the presets.
updateNetwork(Conditioner config);
The custom configuration can be defined by creating a Conditioner variable and
then using its setters to set specific fields.
Conditioner config = new Conditioner();
config.setLatencyUp(10);
The table below lists all available fields that can be configured via the
conditioner. You can infer setter names through the JSON key, e.g., the setter
for rate_up is setRateUp().
It is possible to also supply the command with a configuration object that
explicitly defines various aspects of network quality. This object is considered
only if the provided network_mode value is "custom", otherwise it will be
ignored.
def update_network(
driver: TestUIDriver,
network_mode: str,
network_config: dict or None = None
) -> None
The network_config parameter is a dictionary consisting of explicitly defined
network conditioner field values. The available fields to configure are listed
in the table below, where the JSON key column refers to the names of these
fields.
| Network parameter | Traffic direction | JSON key | Unit of measure | Min value | Max value |
|---|---|---|---|---|---|
| Bandwidth | Outgoing | rate_up | mbit | 0 | |
| Incoming | rate_down | mbit | 0 | ||
| Latency | Outgoing | latency_up | ms | 0 | |
| Incoming | latency_down | ms | 0 | ||
| Jitter | Outgoing | jitter_up | ms | 0 | |
| Incoming | jitter_down | ms | 0 | ||
| Packet loss | Outgoing | loss_up | % | 0 | 100 |
| Incoming | loss_down | % | 0 | 100 |
For custom network configuration jitter parameters must be defined together with latency. If jitter parameters are set without also defining latency parameters, then jitter configuration will not be applied.
The network parameters not defined in custom network configuration will be reset to their default values.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client => {
// Example of updating network conditions using custom values
let customNetworkConfig = {
latency_up: 100,
latency_down: 50,
jitter_up: 20,
jitter_down: 10,
rate_up: 50,
rate_down: 80,
loss_up: 5,
loss_down: 75,
};
client
.url("https://www.bing.com")
.waitForElementVisible("[type=search]", 10000)
.updateNetwork(loaderoConstants.network.custom, customNetworkConfig);
}
These are the available ConditionerBuilder methods to set up the Conditioner
object, which should then be finalized with a .buildConditioner() call:
.latency(up, down).latencyUp(up).latencyDown(down).jitter(up, down).jitterUp(up).jitterDown(down).rate(up, down).rateUp(up).rateDown(down).loss(up, down).lossUp(up).lossDown(down)
public void testUIWithLoadero() {
// Example of updating network conditions using custom network configuration
open("https://www.bing.com");
Conditioner config = new ConditionerBuilder()
.latency(10, 10)
.buildConditioner();
updateNetwork(config);
config.setRateUp(20);
updateNetwork(config);
}
def test(driver: TestUIDriver):
customNetworkConfig = {
"latency_up": 100,
"latency_down": 50,
"jitter_up": 20,
"jitter_down": 10,
"rate_up": 50,
"rate_down": 80,
"loss_up": 5,
"loss_down": 75
}
driver.navigate_to("https://www.bing.com")
e(driver, "css", "[type=search]").wait_until_visible(seconds=10)
update_network(
driver,
LOADERO_CONSTANTS.network.custom,
customNetworkConfig
)
Wait for Download Finished
This command checks if a file exists in the browser's Downloads directory, and if it does not exist, then the command will wait for the given amount of time. During this time period the command will check every 0.5s whether the file has appeared, and if it has, then the command will complete. If the file does not appear within the allotted time, then the command and test will both fail.
Since the download completion check is done every 0.5s, it can be used for crude download time measurement as well.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.waitForDownloadFinished(fileName: string, timeout = 1000: int);
The fileName parameter specifies the name of the file that should appear in
the browser's Downloads directory. This parameter cannot be null or empty,
otherwise an Error will be thrown.
The timeout parameter specifies time in milliseconds, how long to wait for
the file to appear. If no timeout parameter is provided, then a default value of
1000 ms is used. When the timeout is exceeded an Error is thrown.
client => {
// Example of waiting for a file to be downloaded
client
// Open the DemoQA upload/download page
.url('https://demoqa.com/upload-download')
// Download the file
.waitForElementVisible('#downloadButton', 10 * 1000)
.click('#downloadButton')
// Wait for the download to finish
.waitForDownloadFinished('sampleFile.jpeg', 30 * 1000)
.saveScreenshot('after_download.png');
}
waitForDownloadFinished(String fileName, long timeout);
The fileName parameter specifies the name of the file that should appear in
the browser's Downloads directory. This parameter cannot be null or empty,
otherwise an Error will be thrown.
The timeout parameter specifies time in milliseconds, how long to wait for
the file to appear. If no timeout parameter is provided, then a default value of
1000 ms is used. When the timeout is exceeded an Error is thrown.
public void testUIWithLoadero() {
// Example of waiting for a file to be downloaded
// Open the DemoQA upload / download page
open("https://demoqa.com/upload-download");
// Download the file
E(byCssSelector("#downloadButton")).waitFor(10).untilIsVisible().click();
// Wait for the download to finish
waitForDownloadFinished("sampleFile.jpeg", 30 * 1000);
E(byCssSelector("#app")).saveScreenshot("after_download.png");
}
def wait_for_download_finished(
driver: TestUIDriver,
file_name: str,
timeout: int = 1000
) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The file_name parameter specifies the name of the file that should appear in
the browser's Downloads directory. This parameter cannot be None or empty,
otherwise an Error will be thrown.
The timeout parameter specifies time in milliseconds, how long to wait for the
file to appear. If no timeout parameter is provided, then a default value 1000
ms is used. When the timeout is exceeded, a Py-TestUI error will be raised but
test execution will continue.
def test(driver: TestUIDriver):
# Example of waiting for a file to be downloaded
# Open the DemoQA upload/download page
driver.navigate_to("https://demoqa.com/upload-download")
# Download the file
download_element = e(driver, "css", "#downloadButton")
download_element.wait_until_visible().click()
# Wait for the download to finish
wait_for_download_finished(driver, "sampleFile.jpeg", 30 * 1000)
driver.save_screenshot("after_download.png")
Set Request Header
This function allows updating the header values for any requests that the browser sends out.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.setRequestHeader(headerName: string, headerValue: string);
The headerName parameter is the name of the request header to be changed. The
headerValue parameter is used to set a new value for the specified header.
To reset a request header to its default value, pass null as the new header
value.
Setting headerValue to an empty string will actually update the request header
value to an empty string.
client => {
// Example of setting custom request header value
client
// Open page and create screenshot with default request header
.url("https://myhttpheader.com/")
.waitForElementVisible("#ua_table", 10 * 1000)
.saveScreenshot("default_headers.png")
// Set custom request header, reload the page and create screenshot
.setRequestHeader("Accept-Language", "lv-LV")
.pause(1000)
.refresh()
.useXpath()
.waitForElementVisible(
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]",
10 * 1000
).saveScreenshot("custom_headers.png")
// Reset request header, reload the page and create screenshot
.setRequestHeader("Accept-Language", null)
.pause(1000)
.refresh()
.waitForElementNotPresent(
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]",
10 * 1000
).saveScreenshot("reset_headers.png")
}
setRequestHeader(String headerName, String headerValue);
The headerName parameter is the name of the request header to be changed.
The headerValue parameter is used to set a new value for the specified header.
To reset a request header to its default value, pass null as the new header
value.
Setting headerValue to an empty string will actually update the request header
value to an empty string.
public void testUIWithLoadero() {
// Example of setting custom request header value
// Open page and create screenshot with default request header
open("https://myhttpheader.com/");
E(byCssSelector("#ua_table")).waitFor(10).untilIsVisible();
E(byCssSelector("#ua_table")).saveScreenshot("default_headers.png");
// Set custom request header, reload the page and create screenshot
setRequestHeader("Accept-Language", "lv-LV");
sleep(1000);
getSelenideDriver().navigate().refresh();
E(byXpath(
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]"
)).waitFor(10).untilIsVisible();
E(byCssSelector("#ua_table")).saveScreenshot("custom_headers.png");
// Reset request header, reload the page and create screenshot
setRequestHeader("Accept-Language", null);
sleep(1000);
getSelenideDriver().navigate().refresh();
E(byXpath(
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]"
)).waitFor(10).untilNotVisible();
E(byCssSelector("#ua_table")).saveScreenshot("reset_headers.png");
}
def set_request_header(
driver: TestUIDriver,
header: str,
value: str or None = None
) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The header parameter is the name of the request header to be changed.
The value parameter is used to set a new value for the specified header.
To reset a request header to its default value, pass None as the new header
value.
Setting value to an empty string will actually update the request header
value to an empty string.
def test(driver: TestUIDriver):
# Example of setting custom request header value
# Open page and create screenshot with default request header
driver.navigate_to("https://myhttpheader.com/")
e(driver, "css", "#ua_table").wait_until_visible()
driver.save_screenshot("default_headers.png")
# Set custom request header, reload the page and create screenshot
set_request_header(driver, "Accept-Language", "lv-LV")
time.sleep(1)
driver.get_driver().refresh()
e(
driver,
"xpath",
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]"
).wait_until_visible()
driver.save_screenshot("custom_headers.png")
# Reset request header, reload the page and create screenshot
set_request_header(driver, "Accept-Language", None)
time.sleep(1)
driver.get_driver().refresh()
e(
driver,
"xpath",
"//div[contains(text(), 'Accept-Language:')]/following-sibling::div[contains(text(), 'lv-LV')]"
).no().wait_until_visible()
driver.save_screenshot("reset_headers.png")
The "Set User Agent" custom command is equivalent to using the "Set Request Header" command to set the value of the "User-Agent" header. Either approach may be used.
Ignore Alert
This command will dismiss an alert opened by alert(), prompt(), or
confirm() JavaScript functions. Calling this command when an alert is not
present will log an error but it will not fail the test.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.ignoreAlert();
This function does not require any parameters.
client => {
client
// Example of closing an alert before taking a screenshot
.url("https://www.bing.com")
.waitForElementVisible("[type=search]", 10000)
.execute(function () {
prompt("prompt!");
})
.ignoreAlert()
.saveScreenshot("screenshot.png");
}
ignoreAlert();
This function does not require any parameters.
public void testUIWithLoadero() {
// Example of closing an alert before taking a screenshot
open("http://www.bing.com");
E(byCssSelector("[type=search]")).waitFor(10).untilIsVisible();
executeJs("prompt('prompt!')");
ignoreAlert();
E(byCssSelector("[type=search]")).saveScreenshot("screenshot.png");
}
def ignore_alert(driver: TestUIDriver) -> None
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
def test(driver):
# Example of closing an alert before taking a screenshot
driver.navigate_to("https://www.bing.com/")
e(driver, "css", '[type=search]').wait_until_visible()
driver.execute_script("prompt('prompt!');", None)
ignore_alert(driver)
driver.save_screenshot("screenshot.png")
A typical use case, as shown in the example, is to close an alert if there is one before taking a screenshot.
Time Execution
This custom command measures and reports the execution time of the provided function. It allows timing the execution of some flow in a website, e.g., logging in, checking out in an e-commerce site, joining a WebRTC call, etc. Results from this command can be used in post-run analysis.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.timeExecution(name: string, timedCommand: Function, timeout?: number);
The name parameter defines the name that you would like to provide to the
associated execution time metric that will be generated as a result of this
function. E.g., providing the value openURL will cause the execution time
metric to be labeled as openURL in the run report. The name may only contain
alphanumeric characters, underscores and hyphens, otherwise the command and test
will fail. The name must not exceed 150 characters in length.
The timedCommand parameter is the function that will have its execution timed.
This can both be provided as the name of a declared function within the script
or as an anonymous function that is defined within the parameter itself.
Examples of both approaches are provided below. The provided function will be
executed as part of the
NightWatch command queue.
If name is left blank, then:
- if the name of a declared function is provided as the value of
timedCommand, the associated execution time metric will be labeled by using the name of the function; - if the value of
timedCommandis an anonymous function, then the metric will be labeled asanonymous.
timedCommand can have up to two parameters of its own which follow the exact
same pattern and logic as the
built-in .perform() command:
- no parameters - function runs and execution timing completes immediately at the end of the execution of the function;
- one parameter - allows for asynchronous execution within the function.
The parameter must be a
donecallback function that will indicate the completion of thetimedCommandfunction. Ifdonecallback is not invoked, function execution will last indefinitely. - two parameters - allows for asynchronous execution with the Nightwatch
APIobject passed in as the first argument, followed by thedonecallback.
timeout is an optional parameter which specifies the time in milliseconds,
how long to wait for the provided timedCommand to execute. The timeout value
must be positive. If the execution time exceeds the timeout value, then an
error will be thrown. If the timeout parameter is not provided, then no time
limit is placed on the execution time of timedCommand.
Usage of this custom command will generate an execution time metric in the run report. That metric will also be output to the Selenium log at the end of the command's execution. This log entry's structure is shown below.
[LOADERO] Execution time for '${NAME}': ${DURATION}ms (start: ${START}; end: ${END}).
${NAME}has the value that was supplied to thenameparameter.${DURATION}is the execution time in milliseconds of the function provided to thetimedCommandparameter${START},${END}are Unix timestamp values in milliseconds.
client => {
client
.url("https://www.ecosia.org")
.timeExecution("execute_search_query", () => {
client
.waitForElementVisible("[type=search]", 10 * 1000)
.setValue("[type=search]", ["QA Processes", client.Keys.ENTER])
.waitForElementVisible(
"[data-test-id='layout-content']",
10 * 1000
)
})
.saveScreenshot("search_results.png")
}
client => {
client
.url("https://www.ecosia.org")
.timeExecution(
"execute_search_query",
() => {
client
.waitForElementVisible("[type=search]", 10 * 1000)
.setValue("[type=search]", ["QA Processes", client.Keys.ENTER])
.waitForElementVisible(
"[data-test-id='layout-content']",
10 * 1000
)
},
10 * 1000
)
.saveScreenshot("search_results.png")
}
client => {
const executeSearchQuery = () => {
client
.waitForElementVisible("[type=search]", 10 * 1000)
.setValue("[type=search]", ["QA Processes", client.Keys.ENTER])
.waitForElementVisible("[data-test-id='layout-content']", 10 * 1000)
};
client
.url("https://ecosia.org/")
.timeExecution(
"execute_search_query",
executeSearchQuery,
10 * 1000
)
.saveScreenshot("search_results.png");
}
timeExecution(String name, Command command, int timeout);
timeExecution(String name, Command command);
The name parameter defines the name that you would like to provide to the
associated execution time metric that will be generated as a result of this
function. E.g., providing the value openURL will cause the execution time
metric to be labeled as openURL in the run report. The name may only contain
alphanumeric characters, underscores and hyphens, otherwise the command and test
will fail. The name must not exceed 150 characters in length.
If name is left blank, then the associated time execution metric will be
labeled as anonymous.
The command parameter is the function that will have its execution timed. It
must be provided in one of two ways:
- Anonymously as a lambda expression which is an implementation of the
functional interface
Command, shown below. - By declaring a separate function and then passing a reference to that function as the parameter.
@FunctionalInterface
public interface Command {
void execute();
}
Examples are given further below for both approaches.
timeout is an optional parameter which specifies the time in seconds, how long
to wait for the provided command to execute. The timeout value must not be
negative. If the execution time exceeds the timeout value, then an error will
be thrown. If the timeout parameter is not provided or set to be 0, then no
time limit is placed on the execution time of command.
Usage of this custom command will generate an execution time metric in the run report. That metric will also be output to the Selenium log at the end of the command's execution. This log entry's structure is shown below.
[LOADERO] Execution time for '${NAME}': ${DURATION}ms (start: ${START}; end: ${END}).
${NAME}has the value that was supplied to thenameparameter.${DURATION}is the execution time in milliseconds of the function provided to thecommandparameter.${START},${END}are Unix timestamp values in milliseconds.
public void testUIWithLoadero() {
open("https://www.ecosia.org");
timeExecution(
"execute_search_query",
() -> {
E(byCssSelector("[type=search]"))
.waitFor(10)
.untilIsVisible()
.sendKeys("QA Processes\n");
E(byCssSelector("[data-test-id='layout-content']"))
.waitFor(10)
.untilIsVisible();
}
);
E(byCssSelector("[data-test-id='layout-content']"))
.saveScreenshot("search_results.png");
}
public void testUIWithLoadero() {
open("https://www.ecosia.org");
timeExecution(
"execute_search_query",
() -> {
E(byCssSelector("[type=search]"))
.waitFor(10)
.untilIsVisible()
.sendKeys("QA Processes\n");
E(byCssSelector("[data-test-id='layout-content']"))
.waitFor(10)
.untilIsVisible();
},
10
);
E(byCssSelector("[data-test-id='layout-content']"))
.saveScreenshot("search_results.png");
}
public void testUIWithLoadero() {
open("https://www.ecosia.org");
timeExecution("execute_search_query", this::executeSearchQuery, 10);
E(byCssSelector("[data-test-id='layout-content']"))
.saveScreenshot("search_results.png");
}
public void executeSearchQuery() {
E(byCssSelector("[type=search]"))
.waitFor(10)
.untilIsVisible()
.sendKeys("QA Processes\n");
E(byCssSelector("[data-test-id='layout-content']"))
.waitFor(10)
.untilIsVisible();
}
def time_execution(name: str, command: Callable, timeout: int or None = None) -> None
The name parameter defines the name that you would like to provide to the
associated execution time metric that will be generated as a result of this
function. E.g., providing the value openURL will cause the execution time
metric to be labeled as openURL in the run report. The name may only contain
alphanumeric characters, underscores and hyphens, otherwise the command and test
will fail. The name must not exceed 150 characters in length.
The command parameter is a
Callable whose execution
will be timed. This can both be provided as the name of a declared function
within the script or as an anonymous lambda function. Examples of both
approaches are provided below.
If name is left blank, then:
- if a callable with a
__name__attribute is provided as the value ofcommand(e.g., a declared function), the associated execution time metric will be labeled by using this attribute's value; - if the value of
commandis an anonymous callable, then the metric will be labeled asanonymous.
timeout is an optional parameter which specifies the time in seconds, how long
to wait for the provided command to execute. The timeout value must be
positive. If the execution time exceeds this value, then an error will be
thrown. If the timeout parameter is not provided, then no time limit is placed
on the execution time of command.
Usage of this custom command will generate an execution time metric in the run report. That metric will also be output to the Selenium log at the end of the command's execution. The log message structure is shown below.
[LOADERO] Execution time for '${NAME}': ${DURATION}ms (start: ${START}; end: ${END}).
${NAME}has the value that was supplied to thenameparameter.${DURATION}is the execution time in milliseconds of the callable provided to thecommandparameter.${START},${END}are Unix timestamp values in milliseconds.
def test_on_loadero(driver: TestUIDriver):
def execute_search_query():
e(
driver, "css", "[type=search]"
).wait_until_visible().send_keys(["QA Processes", Keys.ENTER])
e(driver, "css", "[data-test-id='layout-content']").wait_until_visible()
driver.navigate_to("https://ecosia.org")
time_execution("execute_search_query", execute_search_query)
driver.save_screenshot("search_results.png")
def test_on_loadero(driver: TestUIDriver):
def execute_search_query():
e(
driver, "css", "[type=search]"
).wait_until_visible().send_keys(["QA Processes", Keys.ENTER])
e(driver, "css", "[data-test-id='layout-content']").wait_until_visible()
driver.navigate_to("https://ecosia.org")
time_execution("execute_search_query", execute_search_query, 10)
driver.save_screenshot("search_results.png")
def test_on_loadero(driver: TestUIDriver):
def execute_search_query():
e(
driver, "css", "[type=search]"
).wait_until_visible().send_keys(["QA Processes", Keys.ENTER])
e(driver, "css", "[data-test-id='layout-content']").wait_until_visible()
# Lambda functions lend themselves well for timing a single line of code
time_execution(
"open_url",
lambda: driver.navigate_to("https://ecosia.org"),
10
)
# Locating the element afterwards still requires multiple lines of code
# For timing the whole sequence, you will need to define a function for them
time_execution("execute_search_query", execute_search_query, 10)
driver.save_screenshot("search_results.png")
As you can see, if you want to make measurements in a Py-TestUI script, you will want to declare the sequence of steps you are measuring as a function most of the time. Providing a function anonymously is only viable for when that sequence is just one line of code long.
Generate Email Address
This custom command creates an email address which can then be used to receive emails, such as verifications emails in sign-up processes.
The generated email is generated based on a prefix string provided
as a parameter to the command, which will be added to the beginning of the
generated email address. The generated email address will have the format of
{prefix}-{runID}@{domain}, where "runID" and "domain" will be automatically
filled in by Loadero.
If you want to generate an email address for multiple participants in the test, then it is best to supply something that uniquely identifies the participant as the prefix, such as their global ID.
Manually formatting an email address from scratch to meet the
{prefix}-{runID}@{domain} format is not recommended, as it may lead to errors
in the test. Use this custom command instead.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.genEmail(prefix: string, callback: Function);
The prefix parameter specifies the value that you want to provide at the
beginning of the email, which the command will then append with the remaining
-{runID}@{domain} component.
The callback parameter contains a callback function (either by
passing a name of an existing function or defining it inline). The callback can
be supplied with an argument, whose value will be the generated email address.
Refer to the example below
client => {
client.genEmail("test", addr => {
console.log(`Generated email address: ${addr}`);
});
}
To save the generated email address for later use, you can use the following code snippet:
client => {
let email;
// Generate the email address and save it as a variable
client.genEmail("test", addr => {
email = addr;
});
// Alternatively, generate a unique email address for each participant
client.genEmail(`test${client.globals.participant.globalID}`, addr => {
email = addr;
});
// Use the email address here
client.perform(() => {
console.log(`Generated email address: ${email}`);
});
}
Keep in mind, that because of the asynchronous nature of Nightwatch, the email
address will not be available immediately after calling the genEmail()
function, so it's recommended to use the saved value within a perform()
command. Otherwise you may encounter an error that the email variable is
undefined.
String genEmail(String prefix);
The prefix parameter specifies the value that you want to provide at the
beginning of the email, which the command will then append with the remaining
-{runID}@{domain} component.
public void test() {
// Generate the email address and save it as a variable
String addr = genEmail("test");
// Alternatively, generate a unique email address for each participant
String uniquePrefix = String.format(
"test%s",
globalConfig.getParticipant().getGlobalId()
);
addr = genEmail(uniquePrefix);
// Use the email address here
System.out.println("Generated email address: " + addr);
}
def gen_email(prefix: str) -> str
The prefix parameter specifies the value that you want to provide at the
beginning of the email, which the command will then append with the remaining
-{runID}@{domain} component.
def test(driver: TestUIDriver):
# Generate the email address and save it as a variable
addr = gen_email("test")
# Alternatively, generate a unique email address for each participant
addr = gen_email(f"test{GLOBALS.participant.global_id}")
# Use the email address here
print("Generated email address:", addr)
Receive Email
This custom command will return a collection of email messages that have been received by the specified email address. To designate the email address that will receive these messages, you should use the Generate Email Address custom command. You can not use this command on your own personal email address, for example. It must be a testing email generated by Loadero itself.
The command itself will not wait for any email messages to arrive at the specified email adrress - if an email message has not yet arrived by the time this command is called, then the returned collection will not contain this email message. The returned data functions as a snapshot of all received email messages at that point in time in which the command was executed. As such, it is recommended to use the command within a loop that will wait for the email message to be visible within the collection.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.receiveEmail(address: string, callback: Function);
The address parameter specifies the email address whose received messages
you would like to inspect. The value provided to this parameter should be
generated by the "Generate Email Address" custom
command and should not be written out manually.
The callback parameter accepts a callback function (either by
passing a name of an existing function or defining it inline). The callback can
be supplied with an argument, whose value will be the array of email messages
that had been returned by the command, so that they can be further processed
within the callback.
The email messages within the array will have the following properties:
- from - The email address of the sender.
- subject - The subject of the email.
- headers - The headers of the email.
- text/plain - The plain text content of the email.
- text/html - The HTML content of the email.
The email message object is a JavaScript object, so it is possible to access
the properties using the dot notation, for example: email.from, but since
the property names contain special characters, it is not recommended. Instead,
it is recommended to access the properties using the array notation,
for example: email["from"], by doing this you will avoid any potential
issues with the special characters.
client => {
client.genEmail("test", addr => {
client.receiveEmail(addr, emails => {
console.log(`Amount of received emails: ${emails.length}`)
for (let email of emails) {
console.log(`From: ${email["from"]}`)
console.log(`Subject: ${email["subject"]}`)
console.log(`Plain text content: ${email["text/plain"]}`)
}
});
})
}
client => {
let email;
// Create the address to use first
client.genEmail("test", addr => {
email = addr;
});
/*
Some UI interactions that cause an email message to be sent
*/
// Loops work funny in Nightwatch.js due to the command queue
// A recursive approach instead helps things go a little more... synchronously
const retry = (retries, emailReceived) => {
// If the email has been received already, continue
// If retrying has already occurred 10 times, give up
// If a retry was called, wait 5 seconds before checking again
if (emailReceived) return
else if (retries >= 10) throw Error("Email did not arrive.")
else if (retries != 0) client.pause(5*1000);
client.perform(()=> {
console.log("Iteration No. ", retries);
client
.receiveEmail(email, messages => {
console.log(`Amount of received emails: ${messages.length}`);
for (let email of messages) {
console.log(`From: ${email["from"]}`);
console.log(`Subject: ${email["subject"]}`);
console.log(`Plain text content: ${email["text/plain"]}`);
//If the email has arrived, we can stop retrying
if (email["from"]=="expected@email.com") emailReceived = true;
}
})
retries++;
}).perform(()=> {
// Since this is encased in a .perform(),
// the function call will be inserted into the queue with updated parameter values
retry(retries, emailReceived);
});
}
// Wrapping the first call of the recursive function inside another function
// Calling a recursive function directly from the main body is uncommon
const waitForEmail = () => {
retry(0, false);
};
waitForEmail();
/*
Further actions after successfully retrieving the email
Such as navigating to a URL sent in the email, etc.
*/
}
EmailMessage[] receiveEmail(String address);
The address parameter specifies the email address whose received messages
you would like to inspect. The value provided to this parameter should be
generated by the "Generate Email Address" custom
command and should not be written out manually.
The email messages within the array returned by this command will have the following properties:
- from - The email address of the sender.
- subject - The subject of the email.
- headers - The headers of the email.
- text/plain - The plain text content of the email.
- text/html - The HTML content of the email.
Email messages are stored within EmailMessage objects, which have the
following methods to get the object's properties:
String getFrom()- Returns the email address of the sender.String getSubject()- Returns the subject of the email.Map<String, String> getHeaders()- Returns the headers of the email.String getTextPlain()- Returns the plain text content of the email.String getTextHtml()- Returns the HTML content of the email.
public void test() {
EmailMessage[] messages = receiveEmail(genEmail("test"));
System.out.println("Amount of received emails: " + messages.length);
for (EmailMessage email : messages) {
System.out.println("From: " + email.getFrom());
System.out.println("Subject: " + email.getSubject());
System.out.println("Plain text content: " + email.getTextPlain());
}
}
public void test() throws Exception {
String addr = genEmail("test");
Boolean emailReceived = false;
int retries;
/*
Some UI interactions that cause an email message to be sent
*/
for (retries = 0; retries < 10 && !emailReceived; retries++) {
// If the email has been received already, continue
// If retrying has already occurred 10 times, give up
// If a retry was called, wait 5 seconds before checking again
if (retries != 0) sleep(5*1000);
System.out.println("Iteration No. " + retries);
EmailMessage[] messages = receiveEmail(addr);
System.out.println("Amount of received emails: " + messages.length);
for (EmailMessage email : messages) {
System.out.println("From: " + email.getFrom());
System.out.println("Subject: " + email.getSubject());
System.out.println("Plain text content: " + email.getTextPlain());
//If the email has arrived, we can stop retrying
if (email.getFrom().equals("expected@email.com")) {
emailReceived = true;
}
}
}
if (retries >= 10) {
throw new Exception("Email did not arrive.");
}
/*
Further actions after successfully retrieving the email
Such as navigating to a URL sent in the email, etc.
*/
}
def receive_email(driver: TestUIDriver, address: str) -> []
The driver parameter corresponds to the TestUIDriver object being used
in the test script. You don't need to set this object up yourself as it will
already be set up by Loadero - you simply need to pass it to the function via
driver.
The address parameter specifies the email address whose received messages
you would like to inspect. The value provided to this parameter should be
generated by the "Generate Email Address" custom
command and should not be written out manually.
The email messages within the list returned by this command will have the following properties:
- from - The email address of the sender.
- subject - The subject of the email.
- headers - The headers of the email.
- text/plain - The plain text content of the email.
- text/html - The HTML content of the email.
def test(driver: TestUIDriver):
messages = receive_email(driver, gen_email("test"))
print("Amount of received emails:", len(messages))
for email in messages:
print("From:", email["from"])
print("Subject:", email["subject"])
print("Plain text content:", email["text/plain"])
def test_on_loadero(driver: TestUIDriver):
addr = gen_email("test")
emailReceived = False
retries = 0
'''
Some UI interactions that cause an email message to be sent
'''
for retries in range(10):
# If the email has been received already, continue
# If retrying hsa already occurred 10 times, give up
# If a retry was called, wait 5 seconds before checking again
if emailReceived:
break
if retries != 0:
time.sleep(5)
print(f"Iteration No. {retries}")
messages = receive_email(driver, addr)
print(f"Amount of received emails: {len(messages)}")
for email in messages:
print(f"From: {email['from']}")
print(f"Subject: {email['subject']}")
print(f"Plain text content: {email['text/plain']}")
# If the email has arrived, we can stop retrying
if email["from"] == 'expected@email.com':
emailReceived = True
if retries>=10:
raise Exception("Email did not arrive.")
'''
Further actions after successfully retrieving the email
Such as navigating to a URL sent in the email, etc.
'''
Perform Timed
This custom command is exclusive to Nightwatch.js, and there is no equivalent for the TestUI and Py-TestUI frameworks.
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
The built-in .perform() command in Nightwatch.js uses an asyncHookTimeout
value for the done
invocation timeout.
By default the asyncHookTimeout value is set to 10 seconds, but there may be
cases where this value should be customized in order to control the maximum
execution time of the callback. So to allow defining this value for each case
separately and avoid having to redefine asyncHookTimeout, the
.performTimed() command was created.
client.performTimed(callback: function, timeout: int);
The callback parameter defines the function that will be executed as part of
the command queue. This callback is defined the same way as in the built-in
.perform() command.
The callback signature can also have up to two parameters whose logic is also
the exact same as for the original .perform() command:
- no parameters - callback runs and perform completes immediately at the end of the execution of the callback.
- one parameter - allows for asynchronous execution within the callback.
The parameter must be a
donecallback function that will indicate the completion ofperformTimedcallback function. - two parameters - allows for asynchronous execution with the Nightwatch
APIobject passed in as the first argument, followed by thedonecallback.
The timeout parameter defines the done invocation timeout and is specified
in milliseconds.
The performTimed() command will be useful in cases where the done callback is
used within a custom callback function in order to notify the
Nightwatch command queue
about the end of the command's execution. Without the done callback invocation
performTimed() command behaves the same as the built-in perform() command
and completes immediately after the callback is executed.
client => {
let version = "";
client
// Get latest ChromeDriver version
.performTimed((done) => {
getLatestChromeDriverVersion(done);
}, 20000)
// Check whether the participant is using the same major version
.url("https://whatmyuseragent.com")
.waitForElementVisible("h5#ua", 10 * 1000)
.perform(()=> {
client.assert.textMatches("h5#ua", `Chrome/${version}.0`)
})
function sleepFor(sleepDuration) {
const now = new Date().getTime();
while (new Date().getTime() < now + sleepDuration) { }
}
function getLatestChromeDriverVersion(done) {
retry = 60;
request(
{
url: "https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json",
},
function (error, response, body) {
if (error) {
throw new Error(error);
}
if (response.statusCode != 200) {
sleepFor(1000);
retry--;
if (retry > 0) {
getLatestChromeDriverVersion(done, retry);
} else {
done();
}
} else {
jsonBody = JSON.parse(body)
fullVersion = jsonBody.channels.Stable.version
versionSeparator = fullVersion.indexOf(".")
version = fullVersion.substring(0, versionSeparator)
done();
}
}
);
}
}
This custom command is only available for Nightwatch.js.
This custom command is only available for Nightwatch.js.
Screenshot (deprecated)
Deprecation notice (October 31st, 2024): users are recommended to use the
built-in functionality of the frameworks for taking a screenshot
(saveScreenshot() for Nightwatch.js and TestUI; save_screenshot() for
Py-TestUI).
- JavaScript + Nightwatch.js
- Java + TestUI
- Python + Py-TestUI
client.takeScreenshot(filename: string, exitOnFail: boolean = false);
The filename parameter specifies the name that will be given to the saved file
containing the captured screenshot.
The exitOnFail parameter determines whether the participant should terminate
test execution if there was a problem taking the screenshot. This parameter can
be omitted and will default to false.
client => {
// Example of taking a browser screenshot
client
.url("https://www.bing.com")
.waitForElementVisible("[type=search]", 10000)
.takeScreenshot("screenshot.png");
}
Screenshot creation is impossible in some cases, for example, when an alert is open. If there are concerns that an alert might get in the way, then the Ignore Alert command can be used - this command will close an alert if it is open, and if there is no alert to close, it won't impact test execution.
This custom command is exclusive to Nightwatch.js. In TestUI you should use
the already built-in saveScreenshot() command instead.
This custom command is exclusive to Nightwatch.js. In Py-TestUI you should use
the already built-in save_screenshot() command instead.