The Selenium Library
/* @provengo summon selenium */
The Selenium library is used for browser automation. Under the covers, it uses the Selenium project to perform the automation.
This library is build around a "Session" concept. Client code first initializes a Selenium session, and then interacts with it.
// @provengo summon selenium (1)
const session = new SeleniumSession("dave"); (2)
bthread( "automator", function(){
session.start("https://test.hal.com"); (3)
session.click("//a[contains(text(),'Sign In')]"); (4)
session.writeText("//input[@id='username']", "dave"); (5)
session.writeText("//input[@id='password']", "dave-pass");
session.click("//button[@id='Open pod bay doors']")
session.waitForVisibility("//div[contains(text(),'I am sorry, Dave')]"); (6)
session.close(); (7)
});
| 1 | Bring in the Selenium library into scope. |
| 2 | Starts a new session (no browser window opened yet). |
| 3 | Opens a browser window at the passed URL. |
| 4 | Clicks an <a> element whose text is "Sign In". |
| 5 | writes dave in the username input. |
| 6 | Waits for a div with the text "I am sorry, Dave" to appear. |
| 7 | Closes the browser window. |
Locators
Selenium uses locators to detect web page components to inspect or interact with. To make automation more robust, Provengo supports two types of locators (CSS and XPATH), and allows specifying multiple locators for each command. This way, you can specify fallback locators in case different versions of the SUT use different page structure or component naming scheme. The run reports list which locator was used to perform the automation. Additionally, Provengo supports locator healing.
For convenience, Provengo auto-detects locator type where possible (see below), so in most cases you can just write the locator. To use a specific locator scheme with no expansion, prefix the locator with the scheme name and double-colon (e.g. css::#bigRedButton). If no prefix is used, Provengo defaults to XPATH. So writing xpath:://button[@id="bigRedButton"] is the same as writing //button[@id="bigRedButton"].
Use an explicit css:: prefix for CSS selectors containing combinators, attribute selectors, pseudo-classes, or other nontrivial syntax. Auto-detection intentionally recognizes only simple selectors. Without the prefix, an unrecognized selector is treated as XPath and may fail with an InvalidSelectorException.
|
| Input | Detected Locator Type | Automatically Expanded To |
|---|---|---|
|
CSS |
|
|
CSS |
|
|
CSS |
|
|
XPATH |
|
|
XPATH |
|
|
CSS |
|
Example
Clicking a big red button. An updated version had a proper ID on that button, but some older versions require a more fragile locator. The following code will support both.
// @provengo summon selenium
const session = new SeleniumSession("dave");
bthread(function(){
session.start("https://test.hal.com");
session.click(["css::#signIn", "//a[contains(text(),'Sign In')]"]); (1)
});
| 1 | Passing an array of locators to the click method. Provengo will to use the locator in order, and use the first one it finds on the page. |
All methods that accept a single locator, also accept an array of locators. So go ahead, make your automations more robust :-).
|
By default, Provengo scrolls to elements prior to interacting with them. This prevents the need to call session.scrollToElement(…) prior to calling, e.g. session.click(…). To turn this behavior off, set the selenium.auto-scroll configuration key to false.
|
Browser Command-Line Arguments
Use the selenium.browser-arguments configuration key to pass additional
command-line arguments when Provengo starts Chrome, Edge, or Firefox. Define
the arguments as a YAML list in config/provengo.yml:
version: 2
selenium:
browser: chrome
browser-arguments:
- --disable-notifications
- --window-position=0,0
Provengo appends these values to its automatic browser arguments. For example, when sessions are hidden, the custom arguments are used alongside Provengo’s headless arguments rather than replacing them. The same configured list is used for every Selenium session in the run.
|
Commandline arguments in Safari
Safari does not support command-line arguments, so this setting applies only to Chrome, Edge, and Firefox. When arguments are configured for a Safari run, Provengo logs a warning and ignores them. |
Locator Healing
Provengo has an optional locator healing mechanism. If an element that was successfully located in previous runs cannot be found in the current run, Provengo can attempt to find an element that most likely to corresponds to the original element. For this, Provengo records a "signature" for each element it locates during project runs. When an element cannot be found by its locators, Provengo uses its signature to to search for elements that are likely to be a replacement for that element. For example, if a button id attribute was changed, but its text and css classes remained the same, Provengo is likely to find it using healing.
Element signatures are stored in a .json file in the project’s products/internal directory.
Locator healing can be turned on or off using the selenium.locator-healing.enable configuration key.
Direct and Grid Automations
Selenium automation in Provengo can work in one of two ways: directly, or by sending commands to a Selenium Grid server. By default, Provengo users direct automation, which requires less installations and in most cases just works out of the box.
Selenium requires a specific driver for each browser being automated. By default, obtaining this driver is done automatically using Selenium Manager (default) or @bonigarcia's WebDriverManager.
|
Advanced WebDriver Management
In most situations, the driver managers just work, without any need for user intervention.
However, some controlled/managed systems might require further configuration.
To choose which manager is used, set the For more details on driver manager configuration, please visit respective manager sites at Selenium Manager or WebDriverManager. |
To use a Selenium Grid server, for example when you want to run the tests on a remote computer or on multiple machines, Provengo requires the server’s URL. That URL can be provided using the selenium.server configuration key, or by invoking Provengo with the --selenium-server <URL> switch.
If Selenium reports that the browser process exited before a session was created, first run that browser directly from the same terminal. On Linux, also inspect LD_LIBRARY_PATH: development environments may prepend incompatible native libraries. Temporarily clearing that variable for the Provengo process can confirm the cause. Preserve it when your browser or other tooling genuinely requires it.
|
|
Automating Edge Browser on Windows
When running tests on Microsoft Windows™ using Microsoft Edge™, the user must be a local admin in order to install the correct driver (see here). If this is an issue, we recommend disabling Edge’s auto-updates, or switching to FireFox or Chrome for test automation. |
Classes
SeleniumSession(sessionName, browserType)
Constructs a new SeleniumSession in browserType. Both parameters are optional.
browserType must be one of the following: chrome, firefox, edge, safari. If not specified, browserType defaults to the browser defined by the --selenium-browser parameter (chrome if not specified).
| Different sessions must have different names. Sessions with the same name will be considered identical. |
Safari browsers do not support headless mode - they must run with a visible window. Thus, when using a Safari browser, the controlled windows are shown regardless of the --show-sessions switch.
|
Example
const admin = new SeleniumSession("admin", "firefox");
SeleniumSession Methods
acceptAlert(promptText, timeout)
promptText-
Optionl String. User input to the dialog. If omitted, Provengo will just accept the prompt/alert.
timeout-
Optional number. The command fails if the alert does not appear within
timeoutmilliseconds. Defaults to1000(1 second).
Example
session.acceptAlert("Delete", 2000);
assertDomProperty(locators, propertyName, expected, modifiers)
Assert that the value of the DOM property of the element pointed by locators matches the expected value.
locators-
Points to the element whose content will be asserted ("target element").
propertyName-
Name of the element’s DOM property whose value is being asserted.
expected-
The value expected to be in the target element.
modifiers-
An array of parameters affecting how the comparison between the actual content of the target element and the expected value. This list can be empty. Possible list values:
TextAssertions.modifiers.Negate-
Negates the condition.
TextAssertions.modifiers.Regex-
Considers the expected be a regular expression against which the actual string is matched.
TextAssertions.modifiers.Trim-
Trims trailing and leading white spaces from the actual value.
TextAssertions.modifiers.IgnoreWhiteSpace-
Deletes all white spaces before comparison.
TextAssertions.modifiers.IgnoreCase-
converts both the actual and the expected strings to lowercase before comparison.
TextAssertions.modifiers.Contains-
Checks if the expected string is contained in the actual string.
Example
session.assertDomProperty("#email", "value", "user@example.com", [
TextAssertions.modifiers.IgnoreCase
]);
assertNotEditable(locators)
Assert that the element pointed by locators is not editable.
For text-entry elements, this succeeds when the element is disabled or has the HTML readonly attribute. Elements that are not text-entry controls are considered non-editable unless they have contenteditable="true".
Example
session.assertNotEditable("#account-id");
assertText(locators, expected, modifiers)
Assert that the text in the element pointed by locators matches text.
locators-
Points to the element whose content will be asserted ("target element").
expected-
The value expected to be in the target element.
modifiers-
An array of parameters affecting how the comparison between the actual content of the target element and the expected value. This list can be empty. Possible list values:
TextAssertions.modifiers.Negate-
Negates the condition.
TextAssertions.modifiers.Regex-
Considers the expected be a regular expression against which the actual string is matched.
TextAssertions.modifiers.Trim-
Trims trailing and leading white spaces from the actual value.
TextAssertions.modifiers.IgnoreWhiteSpace-
Deletes all white spaces before comparison.
TextAssertions.modifiers.IgnoreCase-
converts both the actual and the expected strings to lowercase before comparison.
TextAssertions.modifiers.Contains-
Checks if the expected string is contained in the actual string.
Example
Checking that a status label contains the text "done", in a case-insensitive way. So "Done" also works. Also "donE" (which is a bit weird, true, but we’re not judgemental around here).
bthread( "taskStatusCheck", function(){
waitFor(TASK_COMPLETE); (1)
SESSION.assertText( (2)
`${TASK_PAGE.taskElement}/.status`, (3)
"done", (4)
[TextAssertions.modifiers.Contains,
TextAssertions.modifiers.IgnoreCase]); (5)
});
| 1 | Waiting for another bthread to signal that the task is complete (assume TASK_COMPLETE is an event defined somewhere else in the model). |
| 2 | Asserting an element’s texts. |
| 3 | Specifying the element - here it’s an element with a status class in the task’s element. Assume TASK_PAGE is a page elements object and taskElement is one of its fields, containing a proper locator. |
| 4 | The text we expect. |
| 5 | Specifying that it is enough for the status label to contain the text (i.e. is can contain more text) and that the comparison should be done in a case-insensitive way (e.g. "a"==="A"). |
assertUrl(expectedUrl, modifiers…)
Assert that the current session url matches certain criteria.
expectedUrl-
Expected url of the current page in selenium session.
modifiers-
An array of parameters affecting the comparison between the session’s current url and
expectedUrl. This list can be empty. Possible list values:TextAssertions.modifiers.Negate-
Negates the condition.
TextAssertions.modifiers.Regex-
Considers the expected be a regular expression against which the actual string is matched.
TextAssertions.modifiers.Trim-
Trims trailing and leading white spaces from the actual value.
TextAssertions.modifiers.IgnoreWhiteSpace-
Deletes all white spaces before comparison.
TextAssertions.modifiers.IgnoreCase-
converts both the actual and the expected strings to lowercase before comparison.
TextAssertions.modifiers.Contains-
Checks if the expected string is contained in the actual string.
Example
session.assertUrl("/orders/", [TextAssertions.modifiers.Contains]);
click(locators, timeout)
Click the element pointed by locators.
timeout-
optional number. Milliseconds to wait for the element to become clickable. Defaults to the value specified by the
selenium.implicit-waitconfiguration key (normally 500 msec).
Example
session.click(["#submit-order", "//button[.='Submit']"], 3000);
clear(locators)
Clear the content of the element pointed by locators.
Example
session.clear("#search-query");
contextClick(locators)
Perform a context click at the middle of the element pointed by locators.
Example
session.contextClick("#document-row");
dismissAlert(timeout)
Dismiss an alert. The command fails if the alert does not appear within timeout millisecond. If timeout is omitted, a default value of 1,000 will be used.
Example
session.dismissAlert(2000);
doubleClick(locators, timeout)
Perform a double-click on the element pointed by locators.
optional: timeout milliseconds to wait for the element to become clickable. Defaults to the value specified by the selenium.implicit-wait configuration key (normally 500 msec).
Example
session.doubleClick("#editable-title", 2000);
fileUpload(locators, files)
Upload files to the element pointed by locators. Absolute paths are used as-is; relative paths are resolved from the project’s root directory.
Keep upload fixtures inside the project (for example, data/invoice.pdf) so the same model works from any current working directory and in CI.
|
Example
session.fileUpload("#attachments", ["data/invoice.pdf", "data/photo.png"]);
moveToElement(locators) Deprecated
Scroll the element pointed by locators into view, and move the mouse to its center. Deprecated. Use `scrollToElement(locators)`
Example
session.moveToElement("#checkout"); // Deprecated
pressShiftTabKey(locators)
Press the Shift and Tab keys.
locators-
Points to the element which will be focused while the key press is happening.
Example
session.pressShiftTabKey("#password");
putPropertyInDom(locators, property)
Takes the property named property of the selected element, and copies its value to a new dom attribute of that element.
Example
session.putPropertyInDom("#total", "value");
runCode([params],aFunction)
Runs a function in the browser. The function can report back and write to the runtime log through pvg, an object made available to it during execution. The paramsObj is used for passing parameters to the executed function.
This method is useful for validating variable data whose structure is not known while creating the model. For example, checking that the sum of cells at a given table column matches a certain value, while the number of rows at said table is unknown at modeling time. Because the number of rows is unknown, the model developer cannot create a loop for going over table rows at the model. However, using sn.runCode, model developers can iterate over the rows at execution time, and validate their sum.
params-
Optional. Any Value. Allows passing data to
aFunction, where it can be accessed usingpvg.params. aFunction-
Function. A function that runs in the browser and reports back to
provengo. Does not take any parameters. To pass data to it, use theparamsparameter.aFunctioncan be either an inline/anonymous function, or a name of a function defined elsewhere in the model.aFunctionreports back toprovengousingpvgcallback service object (see below), available as a global variable.
aFunction is sent to the browser and executed there - not at the provengo engine. This means it cannot directly access variables from the model. If such values need to tag along with aFunction, wrap them in an object and pass that as the params parameter.
|
Prefer a named, top-level function for longer browser scripts. It is easier to read and debug, while inline functions are convenient for short checks. In both forms, pass model values through params; variables from the model are not available in the browser.
|
pvg Callback Service Object
This object allows the function sent to the browser to interact with provengo environment - report test results, read and write runtime variables, and print to the log. The object is made available to the function via a global variable, named pvg.
Methods
pvg.params-
The
paramsobject passed to therunCodeas a parameter. pvg.success(aMessage)-
Marks the test step as a success. Terminates the function’s execution.
pvg.fail(aMessage)-
Marks the test step as a failure. Terminates the function’s execution.
pvg.error(aMessage)-
Marks that the test step has encountered an error. Terminates the function’s execution.
pvg.log(aMessage)-
Writes the passed message to provengo's log. Useful for writing intermediate values, e.g. for debugging.
pvg.rtv.set(key, value)-
Sets the value of the
keyruntime variable tovalue. Note: This call takes effect only afterrunCodefinishes execution.
Example
A fully-functional project showing various runCode is available at Provengo’s TechDemos repository.
|
Here we use runCode to count the number of <li> elements in two lists. The ids of the lists are passed via the params object.
/**
* Defined at the program global scope, runs in the browser.
*/
function countLiElements(){
let listOneId = pvg.params.id1; (1)
let listOneItemCount = document.querySelectorAll(`#${listOneId} li`).length;
let listTwoId = pvg.params.id2;
let listTwoItemCount = document.querySelectorAll(`#${listTwoId} li`).length;
pvg.log(`Item count on 2nd list: ${listTwoItemCount}`); (2)
if ( listOneItemCount === listTwoItemCount ){
pvg.success("Lists identical length"); (3)
} else {
pvg.fail(`List lengths differ. List 1: ${listOneItemCount}, List 2: ${listTwoItemCount}`);
}
}
const session = new SeleniumSession("main");
bthread("runCodeExample", function(){
let listNameSet = waitFor(...); // waiting for an event that will have the list names
session.runCode({
id1: listNameSet.data.list1,
id2: listNameSet.data.list2
},
countLiElements
);
});
-
Using the
paramsto read the list id passed from the model. -
Logging intermediate data using
pvg.log -
Great success!!
screenshot()
Take a screenshot of the session’s window. The screenshot will be shown in the run report.
Example
session.screenshot();
scrollByAmount(deltaX, deltaY)
Scroll browser window by a given amount.
deltaX-
Amount to scroll in the right direction. Negative values mean "scroll left".
deltaY-
Amount to scroll in the down direction. Negative values mean "scroll up".
Example
session.scrollByAmount(0, 500);
scrollFromOrigin(origin, deltaX, deltaY, offsetX, offsetY)
Scrolls by provided amount based on a provided origin, which can be either 'viewport' or an xpath of an element. If the scroll origin is 'viewport', then the upper left of the viewport is used as the origin. If the scroll origin is an element, then the origin is either the center of the element.
offsetX and offsetY define how much to offset the origin in the right and down directions.
Similarly, deltaX and deltaY define how much to scroll in the right and down directions.
Negative values represent left and up, respectively.
Example
session.scrollFromOrigin("viewport", 0, 400, 20, 20);
session.scrollFromOrigin("#results", 0, 250);
scrollToElement(locators)
Scroll page to an element, represented by a given locators.
Regardless of whether the element is above or below the current viewscreen, the viewport will be scrolled so the bottom of the element is at the bottom of the screen.
Example
session.scrollToElement("#checkout");
selectByValue(locators, value)
Select an option whose value is value in the select element pointed by locators.
Example
session.selectByValue("#country", "IL");
selectByVisibleText(locators, text)
Select an option whose visible text is text in the select element pointed by locators.
Example
session.selectByVisibleText("#country", "Israel");
setWindowSize(sizeSpec)
Sets the window size for the session.
sizeSpec-
The desired size of the window. Can be a string in the form of
"1050x480"(that’swidth x height), or an object containing fieldssize, orwidthandheight.
You can set a default initial size using the selenium.window-size configuration key.
|
Example
Setting window size based on select().from() result.
const session = new SeleniumSession(...)
function countLiElements(){
...
switch ( select("device")
.from("mobile", "mobile-landscape", "tablet", "laptop") ) {
case "mobile":
session.setWindowSize({
width: 400,
height: 1000
});
break;
case "mobile-landscape":
session.setWindowSize({
width: 1000,
height: 400
});
break;
case "tablet":
session.setWindowSize({
size: "900*1200"
});
break;
case "laptop":
session.setWindowSize("1920x1080");
break;
}
}
sleep(millis) Deprecated
Pause the program for the given duration (in milliseconds).
This method is deprecated, use Ctrl.doSleep(millis) instead.
|
Example
session.sleep(500); // Deprecated
start(url)
Opens a new browser window at the passed url.
Example
session.start("https://example.com");
store(locators, rtvVariableName)
Stores the text contents of the element pointed by locators to the runtime variable rtvVariableName. See Runtime Variables.
Example
session.store("#order-number", "orderNumber");
switchFrame(frame)
Switch to the frame pointed by frame. Pass "Main Frame" to return to the top-level document.
Frame locators follow the same CSS/XPath rules as other Selenium commands. After switching into a frame, all subsequent locators are resolved inside it until session.switchFrame("Main Frame") is called.
Example
session.switchFrame("css::#payment-frame");
switchTab(tabIndex, timeout)
Switch to the tab whose index is tabIndex. The optional timeout is the maximum wait in milliseconds and defaults to 5000.
Tab indices are zero-based. After closing the active tab, explicitly switch to a remaining tab before issuing more page commands.
Example
session.switchTab(1, 3000);
waitForClickability(locators, millis)
Wait up to millis milliseconds for the element pointed by locators to become clickable.
If millis is omitted, a default value of 5,000 will be used.
Example
session.waitForClickability("#submit", 3000);
waitForInvisibility(locators, millis)
Wait up to millis milliseconds for the element pointed by locators to become invisible.
If millis is omitted, a default value of 5,000 will be used.
Example
session.waitForInvisibility("#loading-spinner", 10000);
checkNonExistence(locators, millis)
Wait up to millis milliseconds for the element pointed by locators to be absent from the DOM or invisible.
If millis is omitted, a default value of 5,000 will be used.
Example
session.checkNonExistence("#deleted-row", 5000);
waitForVisibility(locators, millis)
Wait up to millis milliseconds for the element pointed by locators to become visible.
If millis is omitted, a default value of 5,000 will be used.
Example
session.waitForVisibility("#confirmation", 5000);
writeText(locators, text, clearBeforeWrite)
Write the text into the element pointed by locators.
locators-
Points to the element into which the text will be written
text-
The text to write
clearBeforeWrite-
When
true, clear the content of the destination element before writing to it.
Example
session.writeText("#email", "user@example.com", true);