Skip to main content

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.

Set File

client.setFile(selector: string, fileName: string);

The selector parameter specifies input field element selector, e.g. input[type="file"], input#file-upload.


The fileName parameter specifies chosen file name. Choose desired file from the table below.


Sample fileConstantString 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 sample file into file input field using constants
client
// Open DemoQA upload/download page
.url("https://demoqa.com/upload-download")

// Wait for up to 10s for "Choose file" button to be visible
.waitForElementVisible("#uploadFile", 10 * 1000)

// Upload Loadero sample image
.setFile("#uploadFile", loaderoConstants.sampleFiles.png100KB)
.takeScreenshot("file_set.png");
};

Set User Agent

This command changes User-Agent header for outgoing requests and navigator.userAgent.

client.setUserAgent(userAgent: string);
info

To reset User-Agent to its default value, pass null as the new value.

info

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)
.takeScreenshot("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)
.takeScreenshot("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)
.takeScreenshot("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)
.takeScreenshot("reverted_user_agent.png");
};
danger

User-Agent will revert to original value in browser built-in pages and WebRTC dump.

Update Network

This command updates network conditions for participant while the test is running.

Predefined network condition usage

client.updateNetwork(networkMode: string);

The networkMode parameter specifies what network conditions should be used. Available network configurations and networkMode parameter values can be found here or they can be accessed using constants. Constants pertaining to this command can be accessed via loaderoConstants.network. Refer to the table below for a full reference of the available constants.


Network modeConstantString value
Defaultdefault"default"
4Gmobile_4g"4g"
3.5G/HSPDAmobile_hsdpa"hsdpa"
3Gmobile_3g"3g"
GPRSmobile_gprs"gprs"
Edgemobile_edge"edge"
High jitterjitter"jitter"
High latencylatency"latency"
Asymmetricasymmetric"asymmetric"
Satellite phonesatellite"satellite"
5% packetlosspacketloss5"5packet"
10% packetlosspacketloss10"10packet"
20% packetlosspacketloss20"20packet"
50% packetlosspacketloss50"50packet"
100% packetlosspacketloss100"100packet"
Customcustom"custom"
client => {
// Example of updating network conditions
client
.url('https://www.bing.com')
.waitForElementVisible('[type=search]', 10000)
.updateNetwork(loaderoConstants.network.mobile_3g);
}

Custom network condition usage

client.updateNetwork(networkMode: string, config: object);

The config parameter that specifies exact network conditioner field values.


caution

Custom network configuration is taken into effect only if provided networkMode is "custom".

Currently available custom network configuration metrics are:

Network parameterTraffic directionJSON keyUnit of measureMin valueMax value
BandwidthOutgoingrate_upmbit0
Incomingrate_downmbit0
LatencyOutgoinglatency_upms0
Incominglatency_downms0
JitterOutgoingjitter_upms0
Incomingjitter_downms0
Packet lossOutgoingloss_up%0100
Incomingloss_down%0100
info

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.

info

The network parameters not defined in custom network configuration will be reset to their default values.

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);
}

Wait for Download Finished

This command waits until file download is completed or timeout is exceeded. This function is useful if download has to be completed before the end of the test. Download completion check is done every 500 ms, so it can be used for crude download time measurement as well.

client.waitForDownloadFinished(fileName: string, timeout = 1000: int);

The fileName parameter specifies file name to wait for in downloads directory. This parameter can not be empty, otherwise an Error will be thrown.


The timeout parameter specifies time in ms, how long to wait for file download to be completed. If no timeout parameter is provided, default value 1000 ms is used. When timeout is exceeded an Error is thrown.


client => {
// Example of waiting for file to be downloaded
client
// Open DemoQA upload/donwload page
.url('https://demoqa.com/upload-download')
.waitForElementVisible('#app', 1000)

// Start download
.waitForElementVisible('#downloadButton', 10 * 1000)
.click('#downloadButton')

// Wait for download to finish
.waitForDownloadFinished('sampleFile.jpeg', 5 * 60 * 1000)
.takeScreenshot('after_download.png')
}

Set Request Header

This function allows updating the header values for any requests that browser sends out.

client.setRequestHeader(headerName: string, headerValue: string);

The parameter headerName is the name of the request header to be changed. The parameter headerValue is used to set a new value for the specified header.


info

To reset request header to its default value, pass null as the new header value.

info

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://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending')
.waitForElementVisible('#content-base', 10 * 1000)
.takeScreenshot('default_headers.png')

// Set custom request header, reload the page and create screenshot
.setRequestHeader('Accept-Language', 'lv-LV')
.refresh()
.waitForElementVisible('#content-base', 10 * 1000)
.takeScreenshot('custom_headers.png')

// Reset request header, reload the page and create screenshot
.setRequestHeader('Accept-Language', null)
.refresh()
.waitForElementVisible('#content-base', 2000)
.takeScreenshot('reset_headers.png');
}

Ignore Alert

Command will close alert opened by alert(), prompt() or confirm() JavaScript functions.

client => {
client
// Example of closing alert before taking a screenshot
.url('https://www.bing.com')
.waitForElementVisible('[type=search]', 10000)
.execute(function () {
prompt('prompt!');
})
.ignoreAlert()
.takeScreenshot('screenshot.png');
}
info

Calling command on a non-existent alert will log an error but not fail the test.

tip

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 execution time of some 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. Results from this command can be used in post-run analysis.

client.timeExecution(name: string, timedCommand: Function, timeout?: number);

name - identifying name for the timedCommand function. If name is an empty string, then timedCommand.name attribute value will be used if it is available, otherwise name will default to "anonymous". If name is provided then the maximum length for this argument is 150 characters and can only contain alphanumeric characters, underscores and hyphens.


timedCommand - function whose execution will be timed. timedCommand will be executed as part of the NightWatch command queue. timedCommand can have up to two parameters:


  • 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 done callback function that will indicate the completion of timedCommand function. If done callback is not invoked, function execution will last indefinitely.
  • two parameters - allows for asynchronous execution with the Nightwatch API object passed in as the first argument, followed by the done callback.

timeout - specifies the time in milliseconds, how long to wait for the timedCommand to execute. Timeout value must be positive. If the execution time exceeds the timeout value, then an error will be thrown. If timeout parameter is omitted then no limit is placed on the execution time of timedCommand.


Use of the timeExecution custom command will produce a log that contains timing information of the timedCommand. 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 timeExecution name parameter.
  • ${DURATION} is the execution time in milliseconds of the timedCommand function
  • ${START}, ${END} are unix timestamp values in milliseconds.
client => {
const reallyLongPause = 5 * 60 * 1000; // 5 minutes

client
// Example of timing execution without specifying a timeout.
.url("https://duckduckgo.com/")
.timeExecution("locate_search_bar", () => {
client
.waitForElementVisible("#searchbox_input", 10 * 1000)
.sendKeys("#searchbox_input", "QA Processes")
.click("[aria-label='Search']")
.waitForElementVisible("#r1-0 > div > h2", 10 * 1000)
.pause(reallyLongPause);
})
.takeScreenshot("screenshot.png");
}
client => {
client
// Example of timing execution with a timeout.
.url("https://duckduckgo.com/")
.timeExecution(
"locate_search_bar",
() => {
client
.waitForElementVisible(
"#searchbox_input",
10 * 1000
)
.sendKeys("#searchbox_input", "QA Processes")
.click("[aria-label='Search']")
.waitForElementVisible("#r1-0 > div > h2", 10 * 1000);
},
10 * 1000
)
.takeScreenshot("screenshot.png");
}

Generate Email Address

This custom command creates an email address based on a prefix string, which will be added to the beginning of the email address. The prefix is used to identify a specific participant within the test, such as their name or ID. The generated email address will have the format of {prefix}-{runID}@{domain}. The "runID" and "domain" parts of the email address will be automatically filled in.

caution

Manually formatting email address in this format is not recommended, as it may lead to errors in the test. Use this custom command instead.

client.genEmail(prefix: string, callback: Function);

The custom command will pass the generated email address to the callback function provided as its first argument. The email address will be accessible within the callback function as a string, allowing you to use it for further processing.


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 on email variable
client.genEmail("test", addr => {
email = addr;
});

// Use the email address here
client.perform(() => {
console.log(`Generated email address: ${email}`);
});
}

Keep in mind, that taking into consideration the asynchronous nature of the 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.

Receive Email

This custom command will return an array of email messages that were sent to the specified email address during test execution. To generate the email address, you should use the Generate Email Address custom command.

client.receiveEmail(address: string, callback: Function);

The command itself will not wait for any messages to arrive, so it's recommended to use it within a loop that will wait for the email to be visible within the the array.


The emails will be available within the provided callback function as an array. The email message object 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.
info

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"]}`)
}
});
})
}

Perform Timed

This custom command is exclusive to Nightwatch.js, and there is no equivalent for the TestUI and Py-TestUI frameworks.

Built-in .perform() command uses asyncHookTimeout value for the done invocation timeout. By default asyncHookTimeout value is set to 10 seconds, but there may be cases where this value should be customized in order to control callback maximum execution time. So to allow to define this value for each case separately and avoid asyncHookTimeout redefining .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. Same as built-in .perform() command the callback signature can have up to two parameters:

  • 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 done callback function that will indicate the completion of performTimed callback function.
  • two parameters - allows for asynchronous execution with the Nightwatch API object passed in as the first argument, followed by the done callback.

The timeout parameter specifies the time in milliseconds, that describes the done invocation timeout.


tip

The performTimed() command will be useful in cases where done callback is used within the custom callback function in order to notify the Nightwatch command queue about the end of command execution. Without the done callback invocation performTimed() command behaves the same as built-in perform() command and completes immediately after the callback is run.

client => {
let version = "";

client
.url("https://www.bing.com")
.performTimed((done) => {
// Get latest ChromeDriver version
getChromeDriverVersion(done);
}, 20000)

// Insert Bing search query for ChromeDriver version
.perform(() => {
client.setValue("[type=search]", [`chromedriver ${version}`, client.Keys.ENTER])
})

// Wait up to 10 seconds until search results are visible
.waitForElementVisible("[aria-label='Search Results']", 10 * 1000);

function sleepFor(sleepDuration) {
const now = new Date().getTime();
while (new Date().getTime() < now + sleepDuration) { }
}

function getChromeDriverVersion(done) {
retry = 60;
request(
{
url: `https://chromedriver.storage.googleapis.com/LATEST_RELEASE`,
},
function (error, response, body) {
if (error) {
throw new Error(error);
}

if (response.statusCode != 200) {
sleepFor(1000);

retry--;
if (retry > 0) {
getChromeDriverVersion(done, retry);
} else {
done();
}
} else {
version = body;

done();
}
}
);
}
}

Screenshot

While screenshots are possible in all 3 languages, this custom implementation for taking a screenshot is exclusive to Nightwatch.js. TestUI and Py-TestUI already have built-in commands (saveScreenshot() and save_screenshot(), respectively) - you can freely use these commands to capture screenshots.

Nightwatch.js also has a built-in .saveScreenshot() function, however, it conflicts with how Loadero is implemented, which is why this custom command exists - to work around that limitation. If you wish to take a screenshot in a Loadero test when using Nightwatch.js, you will have to use the custom command instead.

caution

Since these screenshots are uploaded only after Selenium script has fully exited, screenshots could be lost if test was aborted early or has failed.

client.takeScreenshot(filename: string, exitOnFail: boolean = false);

The filename parameter specifies name of the file when it will be saved.


The exitOnFail parameter lets participant terminate test execution if there was a problem taking screenshot. This parameter can be omitted and will default to false.


client => {
// Example of taking browser screenshot
client
.url('https://www.bing.com')
.waitForElementVisible('[type=search]', 10000)
.takeScreenshot('screenshot.png');
}
danger

Screenshot creation is impossible in some cases, for example, when an alert is open. Ignore alert can be used to close an alert if it is open, this command will not impact the execution if an alert is not open.