BiDirectional functionality Selenium is working with browser vendors to create the
WebDriver BiDirectional Protocol
as a means to provide a stable, cross-browser API that uses the bidirectional
functionality useful for both browser automation generally and testing specifically.
Before now, users seeking this functionality have had to rely on CDP (Chrome DevTools Protocol)
with all of its frustrations and limitations.
The traditional WebDriver model of strict request/response commands will be supplemented
with the ability to stream events from the user agent to the controlling software via WebSockets,
better matching the evented nature of the browser DOM.
As it is not a good idea to tie your tests to a specific version of any browser, the
Selenium project recommends using WebDriver BiDi wherever possible.
While the specification is in works, the browser vendors are parallely implementing
the WebDriver BiDirectional Protocol .
Refer web-platform-tests dashboard
to see how far along the browser vendors are.
Selenium is trying to keep up with the browser vendors and has started implementing W3C BiDi APIs.
The goal is to ensure APIs are W3C compliant and uniform among the different language bindings.
However, until the specification and corresponding Selenium implementation is complete there are many useful things that
CDP offers. Selenium offers some useful helper classes that use CDP.
1 - Chrome DevTools Many browsers provide “DevTools” – a set of tools that are integrated with the browser that
developers can use to debug web apps and explore the performance of their pages. Google Chrome’s
DevTools make use of a protocol called the Chrome DevTools Protocol (or “CDP” for short).
As the name suggests, this is not designed for testing, nor to have a stable API, so functionality
is highly dependent on the version of the browser.
The WebDriver BiDirectional Protocol is the next generation of the
W3C WebDriver protocol and aims to provide a stable API implemented by all browsers, but it’s not yet complete.
Until it is, Selenium provides access to
the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and
Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can
do with it are given below.
There are three different ways to access Chrome DevTools in Selenium. If you look for other examples online,
you will likely see each of these mixed and matched.
The CDP Endpoint was the first option available to users.
It only works for the most simple things (setting state, getting basic information), and you
have to know the “magic strings” for the domain and methods and key value pairs.
For basic requirements, this might be simpler than the other options. These methods are only temporarily supported. The CDP API is an improvement on just using the endpoint because you can set
do things asynchronously. Instead of a String and a Map, you can access the supported classes,
methods and parameters in the code. These methods are also only temporarily supported. The BiDi API option should be used whenever possible because it
abstracts away the implementation details entirely and will work with either CDP or WebDriver-BiDi
when Selenium moves away from CDP. Examples With Limited Value There are a number of commonly cited examples for using CDP that are of limited practical value.
Geo Location — almost all sites use the IP address to determine physical location,
so setting an emulated geolocation rarely has the desired effect.Overriding Device Metrics — Chrome provides a great API for setting Mobile Emulation
in the Options classes, which is generally superior to attempting to do this with CDP.Check out the examples in these documents for ways to do additional useful things:
1.1 - Chrome DevTools Protocol Endpoint Google provides a /cdp/execute
endpoint that can be accessed directly. Each Selenium binding provides a method that allows you to pass the CDP domain as a String, and the required parameters as a simple Map.
These methods will eventually be removed. It is recommended to use the WebDriver-BiDi or WebDriver Bidi APIs
methods where possible to ensure future compatibility.
Usage Generally you should prefer the use of the CDP API over this approach,
but sometimes the syntax is cleaner or significantly more simple.
Limitations include:
It only works for use cases that are limited to setting or getting information;
any actual asynchronous interactions require another implementation You have to know the exactly correct “magic strings” for domains and keys It is possible that an update to Chrome will change the required parameters Examples Set Cookie An alternate implementation can be found at CDP API Set Cookie
Java
Python
CSharp
Ruby
JavaScript
Kotlin Map < String , Object > cookie = new HashMap <>();
cookie . put ( "name" , "cheese" );
cookie . put ( "value" , "gouda" );
cookie . put ( "domain" , "www.selenium.dev" );
cookie . put ( "secure" , true );
(( HasCdp ) driver ). executeCdpCommand ( "Network.setCookie" , cookie );
cookie = { 'name' : 'cheese' ,
'value' : 'gouda' ,
'domain' : 'www.selenium.dev' ,
'secure' : True }
driver . execute_cdp_cmd ( 'Network.setCookie' , cookie )
var cookie = new Dictionary < string , object >
{
{ "name" , "cheese" },
{ "value" , "gouda" },
{ "domain" , "www.selenium.dev" },
{ "secure" , true }
};
(( ChromeDriver ) driver ). ExecuteCdpCommand ( "Network.setCookie" , cookie );
The CDP API Set Cookie implementation should be preferred
cookie = { name : 'cheese' ,
value : 'gouda' ,
domain : 'www.selenium.dev' ,
secure : true }
driver . execute_cdp ( 'Network.setCookie' , ** cookie )
An alternate implementation can be found at CDP API Performance Metrics
Java
Python
CSharp
Ruby
JavaScript
Kotlin The CDP API Performance Metrics implementation should be preferred
(( HasCdp ) driver ). executeCdpCommand ( "Performance.enable" , new HashMap <>());
Map < String , Object > response =
(( HasCdp ) driver ). executeCdpCommand ( "Performance.getMetrics" , new HashMap <>());
driver . execute_cdp_cmd ( 'Performance.enable' , {})
metric_list = driver . execute_cdp_cmd ( 'Performance.getMetrics' , {})[ "metrics" ]
(( ChromeDriver ) driver ). ExecuteCdpCommand ( "Performance.enable" , emptyDictionary );
Dictionary < string , object > response = ( Dictionary < string , object >)(( ChromeDriver ) driver )
. ExecuteCdpCommand ( "Performance.getMetrics" , emptyDictionary );
The CDP API Performance Metrics implementation should be preferred
driver . execute_cdp ( 'Performance.enable' )
metric_list = driver . execute_cdp ( 'Performance.getMetrics' ) [ 'metrics' ]
Basic authentication Alternate implementations can be found at CDP API Basic Authentication
and BiDi API Basic Authentication
Java
Python
CSharp
Ruby
JavaScript
Kotlin The BiDi API Basic Authentication implementation should be preferred
(( HasCdp ) driver ). executeCdpCommand ( "Network.enable" , new HashMap <>());
String encodedAuth = Base64 . getEncoder (). encodeToString ( "admin:admin" . getBytes ());
Map < String , Object > headers =
ImmutableMap . of ( "headers" , ImmutableMap . of ( "authorization" , "Basic " + encodedAuth ));
(( HasCdp ) driver ). executeCdpCommand ( "Network.setExtraHTTPHeaders" , headers );
driver . execute_cdp_cmd ( "Network.enable" , {})
credentials = base64 . b64encode ( "admin:admin" . encode ()) . decode ()
headers = { 'headers' : { 'authorization' : 'Basic ' + credentials }}
driver . execute_cdp_cmd ( 'Network.setExtraHTTPHeaders' , headers )
(( ChromeDriver ) driver ). ExecuteCdpCommand ( "Network.enable" , emptyDictionary );
string encodedAuth = Convert . ToBase64String ( Encoding . Default . GetBytes ( "admin:admin" ));
var headers = new Dictionary < string , object >
{
{ "headers" , new Dictionary < string , string > { { "authorization" , "Basic " + encodedAuth } } }
};
(( ChromeDriver ) driver ). ExecuteCdpCommand ( "Network.setExtraHTTPHeaders" , headers );
The BiDi API Basic Authentication implementation should be preferred
driver . execute_cdp ( 'Network.enable' )
credentials = Base64 . strict_encode64 ( 'admin:admin' )
headers = { authorization : "Basic #{ credentials } " }
driver . execute_cdp ( 'Network.setExtraHTTPHeaders' , headers : headers )
1.2 - Chrome DevTools Protocol API Each of the Selenium bindings dynamically generates classes and methods for the various CDP domains and features; these are tied to specific versions of Chrome.
While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), these
methods will eventually be removed. It is recommended to use the WebDriver Bidi APIs
methods where possible to ensure future compatibility.
Usage If your use case has been implemented by WebDriver Bidi or
the BiDi API , you should use those implementations instead of this one.
Generally you should prefer this approach over executing with the CDP Endpoint ,
especially in Ruby.
Examples Set Cookie An alternate implementation can be found at CDP Endpoint Set Cookie
Java
Python
CSharp
Ruby
JavaScript
Kotlin Because Java requires using all the parameters example, the Map approach used in
CDP Endpoint Set Cookie might be more simple.
devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send (
Network . setCookie (
"cheese" ,
"gouda" ,
Optional . empty (),
Optional . of ( "www.selenium.dev" ),
Optional . empty (),
Optional . of ( true ),
Optional . empty (),
Optional . empty (),
Optional . empty (),
Optional . empty (),
Optional . empty (),
Optional . empty (),
Optional . empty (),
Optional . empty ()));
Because Python requires using async methods for this example, the synchronous approach found in
CDP Endpoint Set Cookie might be easier.
async with driver . bidi_connection () as connection :
execution = connection . devtools . network . set_cookie (
name = "cheese" ,
value = "gouda" ,
domain = "www.selenium.dev" ,
secure = True
)
await connection . session . execute ( execution )
Due to the added complexity in .NET of obtaining the domains and executing with awaits, the
CDP Endpoint Set Cookie might be easier.
var session = (( IDevTools ) driver ). GetDevToolsSession ();
var domains = session . GetVersionSpecificDomains < OpenQA . Selenium . DevTools . V121 . DevToolsSessionDomains >();
await domains . Network . Enable ( new OpenQA . Selenium . DevTools . V121 . Network . EnableCommandSettings ());
var cookieCommandSettings = new SetCookieCommandSettings
{
Name = "cheese" ,
Value = "gouda" ,
Domain = "www.selenium.dev" ,
Secure = true
};
await domains . Network . SetCookie ( cookieCommandSettings );
driver . devtools . network . set_cookie ( name : 'cheese' ,
value : 'gouda' ,
domain : 'www.selenium.dev' ,
secure : true )
An alternate implementation can be found at CDP Endpoint Performance Metrics
Java
Python
CSharp
Ruby
JavaScript
Kotlin devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send ( Performance . enable ( Optional . empty ()));
List < Metric > metricList = devTools . send ( Performance . getMetrics ());
Because Python requires using async methods for this example, the synchronous approach found in
CDP Endpoint Performance Metrics might be easier.
async with driver . bidi_connection () as connection :
await connection . session . execute ( connection . devtools . performance . enable ())
metric_list = await connection . session . execute ( connection . devtools . performance . get_metrics ())
Due to the added complexity in .NET of obtaining the domains and executing with awaits, the
CDP Endpoint Performance Metrics might be easier.
var session = (( IDevTools ) driver ). GetDevToolsSession ();
var domains = session . GetVersionSpecificDomains < OpenQA . Selenium . DevTools . V121 . DevToolsSessionDomains >();
await domains . Performance . Enable ( new OpenQA . Selenium . DevTools . V121 . Performance . EnableCommandSettings ());
var metricsResponse =
await session . SendCommand < GetMetricsCommandSettings , GetMetricsCommandResponse >(
new GetMetricsCommandSettings ()
);
driver . devtools . performance . enable
metric_list = driver . devtools . performance . get_metrics . dig ( 'result' , 'metrics' )
Basic authentication Alternate implementations can be found at
CDP Endpoint Basic Authentication
and BiDi API Basic Authentication
Java
Python
CSharp
Ruby
JavaScript
Kotlin The BiDi API Basic Authentication implementation should be preferred
devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send ( Network . enable ( Optional . of ( 100000 ), Optional . of ( 100000 ), Optional . of ( 100000 )));
String encodedAuth = Base64 . getEncoder (). encodeToString ( "admin:admin" . getBytes ());
Map < String , Object > headers = ImmutableMap . of ( "Authorization" , "Basic " + encodedAuth );
devTools . send ( Network . setExtraHTTPHeaders ( new Headers ( headers )));
Because Python requires using async methods for this example, the synchronous approach found in
CDP Endpoint Basic Authentication might be easier.
async with driver . bidi_connection () as connection :
await connection . session . execute ( connection . devtools . network . enable ())
credentials = base64 . b64encode ( "admin:admin" . encode ()) . decode ()
auth = { 'authorization' : 'Basic ' + credentials }
await connection . session . execute ( connection . devtools . network . set_extra_http_headers ( Headers ( auth )))
Due to the added complexity in .NET of obtaining the domains and executing with awaits, the
CDP Endpoint Basic Authentication might be easier.
var session = (( IDevTools ) driver ). GetDevToolsSession ();
var domains = session . GetVersionSpecificDomains < OpenQA . Selenium . DevTools . V121 . DevToolsSessionDomains >();
await domains . Network . Enable ( new OpenQA . Selenium . DevTools . V121 . Network . EnableCommandSettings ());
var encodedAuth = Convert . ToBase64String ( Encoding . Default . GetBytes ( "admin:admin" ));
var headerSettings = new SetExtraHTTPHeadersCommandSettings
{
Headers = new Headers ()
{
{ "authorization" , "Basic " + encodedAuth }
}
};
await domains . Network . SetExtraHTTPHeaders ( headerSettings );
The BiDi API Basic Authentication implementation should be preferred
driver . devtools . network . enable
credentials = Base64 . strict_encode64 ( 'admin:admin' )
driver . devtools . network . set_extra_http_headers ( headers : { authorization : "Basic #{ credentials } " })
Console logs Because reading console logs requires setting an event listener,
this cannot be done with a CDP Endpoint implementation
Alternate implementations can be found at
BiDi API Console logs and errors
and WebDriver BiDi Console logs
Java
Python
CSharp
Ruby
JavaScript
Kotlin Use the WebDriver BiDi Console logs implementation
DevTools devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send ( Runtime . enable ());
CopyOnWriteArrayList < String > logs = new CopyOnWriteArrayList <>();
devTools . addListener (
Runtime . consoleAPICalled (),
event -> logs . add (( String ) event . getArgs (). get ( 0 ). getValue (). orElse ( "" )));
The BiDi API Console logs and errors implementation should be preferred
driver . devtools . runtime . enable
logs = []
driver . devtools . runtime . on ( :console_api_called ) do | params |
logs << params [ 'args' ]. first [ 'value' ]
end
JavaScript exceptions Similar to console logs, but this listens for actual javascript exceptions not just logged errors
Alternate implementations can be found at
BiDi API JavaScript exceptions
and WebDriver BiDi JavaScript exceptions
Java
Python
CSharp
Ruby
JavaScript
Kotlin Use the WebDriver BiDi JavaScript exceptions implementation
DevTools devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send ( Runtime . enable ());
CopyOnWriteArrayList < JavascriptException > errors = new CopyOnWriteArrayList <>();
devTools . getDomains (). events (). addJavascriptExceptionListener ( errors :: add );
Download complete Wait for a download to finish before continuing.
Because getting download status requires setting a listener, this cannot be done with a CDP Endpoint implementation.
Java
Python
CSharp
Ruby
JavaScript
Kotlin devTools = (( HasDevTools ) driver ). getDevTools ();
devTools . createSession ();
devTools . send (
Browser . setDownloadBehavior (
Browser . SetDownloadBehaviorBehavior . ALLOWANDNAME ,
Optional . empty (),
Optional . of ( "" ),
Optional . of ( true )));
AtomicBoolean completed = new AtomicBoolean ( false );
devTools . addListener (
Browser . downloadProgress (),
e -> completed . set ( Objects . equals ( e . getState (). toString (), "completed" )));
driver . devtools . browser . set_download_behavior ( behavior : 'allow' ,
download_path : '' ,
events_enabled : true )
driver . devtools . browser . on ( :download_progress ) do | progress |
@completed = progress [ 'state' ] == 'completed'
end
1.3 - Chrome Devtools Protocol with BiDi API These examples are currently implemented with CDP, but the same code should work when the functionality is re-implemented with WebDriver-BiDi.
Usage The following list of APIs will be growing as the Selenium
project works through supporting real world use cases. If there
is additional functionality you’d like to see, please raise a
feature request .
As these examples are re-implemented with the WebDriver-Bidi protocol, they will
be moved to the WebDriver Bidi pages.
Examples Basic authentication Some applications make use of browser authentication to secure pages.
It used to be common to handle them in the URL, but browser stopped supporting this.
With BiDi, you can now provide the credentials when necessary
Alternate implementations can be found at
CDP Endpoint Basic Authentication
and CDP API Basic Authentication
Java
Python
CSharp
Ruby
JavaScript
Kotlin Predicate < URI > uriPredicate = uri -> uri . toString (). contains ( "herokuapp.com" );
Supplier < Credentials > authentication = UsernameAndPassword . of ( "admin" , "admin" );
(( HasAuthentication ) driver ). register ( uriPredicate , authentication );
var handler = new NetworkAuthenticationHandler ()
{
UriMatcher = uri => uri . AbsoluteUri . Contains ( "herokuapp" ),
Credentials = new PasswordCredentials ( "admin" , "admin" )
};
var networkInterceptor = driver . Manage (). Network ;
networkInterceptor . AddAuthenticationHandler ( handler );
await networkInterceptor . StartMonitoring ();
driver . register ( username : 'admin' ,
password : 'admin' ,
uri : /herokuapp/ )
Move Code
const { Builder } = require ( 'selenium-webdriver' );
( async function example () {
try {
let driver = await new Builder ()
. forBrowser ( 'chrome' )
. build ();
const pageCdpConnection = await driver . createCDPConnection ( 'page' );
await driver . register ( 'username' , 'password' , pageCdpConnection );
await driver . get ( 'https://the-internet.herokuapp.com/basic_auth' );
await driver . quit ();
} catch ( e ){
console . log ( e )
}
}())
Move Code
val uriPredicate = Predicate { uri : URI ->
uri . host . contains ( "your-domain.com" )
}
( driver as HasAuthentication ). register ( uriPredicate , UsernameAndPassword . of ( "admin" , "password" ))
driver . get ( "https://your-domain.com/login" )
Pin scripts This can be especially useful when executing on a remote server. For example,
whenever you check the visibility of an element, or whenever you use
the classic get attribute method, Selenium is sending the contents of a js file
to the script execution endpoint. These files are each about 50kB, which adds up.
Java
Python
CSharp
Ruby
JavaScript
Kotlin var key = await new JavaScriptEngine ( driver ). PinScript ( "return arguments;" );
var arguments = (( WebDriver ) driver ). ExecuteScript ( key , 1 , true , element );
key = driver . pin_script ( 'return arguments;' )
arguments = driver . execute_script ( key , 1 , true , element )
Mutation observation Mutation Observation is the ability to capture events via
WebDriver BiDi when there are DOM mutations on a specific
element in the DOM.
Java
Python
CSharp
Ruby
JavaScript
Kotlin CopyOnWriteArrayList < WebElement > mutations = new CopyOnWriteArrayList <>();
(( HasLogEvents ) driver ). onLogEvent ( domMutation ( e -> mutations . add ( e . getElement ())));
async with driver . bidi_connection () as session :
log = Log ( driver , session )
var mutations = new List < IWebElement >();
using IJavaScriptEngine monitor = new JavaScriptEngine ( driver );
monitor . DomMutated += ( _ , e ) =>
{
var locator = By . CssSelector ( $"*[data-__webdriver_id='{e.AttributeData.TargetId}']" );
mutations . Add ( driver . FindElement ( locator ));
};
await monitor . StartEventMonitoring ();
await monitor . EnableDomMutationMonitoring ();
mutations = []
driver . on_log_event ( :mutation ) { | mutation | mutations << mutation . element }
Move Code
const { Builder , until } = require ( 'selenium-webdriver' );
const assert = require ( "assert" );
( async function example () {
try {
let driver = await new Builder ()
. forBrowser ( 'chrome' )
. build ();
const cdpConnection = await driver . createCDPConnection ( 'page' );
await driver . logMutationEvents ( cdpConnection , event => {
assert . deepStrictEqual ( event [ 'attribute_name' ], 'style' );
assert . deepStrictEqual ( event [ 'current_value' ], "" );
assert . deepStrictEqual ( event [ 'old_value' ], "display:none;" );
});
await driver . get ( 'dynamic.html' );
await driver . findElement ({ id : 'reveal' }). click ();
let revealed = driver . findElement ({ id : 'revealed' });
await driver . wait ( until . elementIsVisible ( revealed ), 5000 );
await driver . quit ();
} catch ( e ){
console . log ( e )
}
}())
Console logs and errors Listen to the console.log
events and register callbacks to process the event.
CDP API Console logs
and WebDriver BiDi Console logs
Java
Python
CSharp
Ruby
JavaScript
Kotlin Use the WebDriver BiDi Console logs implementation. HasLogEvents
will likely end up deprecated because it does not implement Closeable
.
CopyOnWriteArrayList < String > messages = new CopyOnWriteArrayList <>();
(( HasLogEvents ) driver ). onLogEvent ( consoleEvent ( e -> messages . add ( e . getMessages (). get ( 0 ))));
async with driver . bidi_connection () as session :
log = Log ( driver , session )
async with log . add_listener ( Console . ALL ) as messages :
using IJavaScriptEngine monitor = new JavaScriptEngine ( driver );
var messages = new List < string >();
monitor . JavaScriptConsoleApiCalled += ( _ , e ) =>
{
messages . Add ( e . MessageContent );
};
await monitor . StartEventMonitoring ();
logs = []
driver . on_log_event ( :console ) { | log | logs << log . args . first }
Move Code
const { Builder } = require ( 'selenium-webdriver' );
( async () => {
try {
let driver = new Builder ()
. forBrowser ( 'chrome' )
. build ();
const cdpConnection = await driver . createCDPConnection ( 'page' );
await driver . onLogEvent ( cdpConnection , function ( event ) {
console . log ( event [ 'args' ][ 0 ][ 'value' ]);
});
await driver . executeScript ( 'console.log("here")' );
await driver . quit ();
} catch ( e ){
console . log ( e );
}
})()
Move Code
fun kotlinConsoleLogExample () {
val driver = ChromeDriver ()
val devTools = driver . devTools
devTools . createSession ()
val logConsole = { c : ConsoleEvent -> print ( "Console log message is: " + c . messages )}
devTools . domains . events (). addConsoleListener ( logConsole )
driver . get ( "https://www.google.com" )
val executor = driver as JavascriptExecutor
executor . executeScript ( "console.log('Hello World')" )
val input = driver . findElement ( By . name ( "q" ))
input . sendKeys ( "Selenium 4" )
input . sendKeys ( Keys . RETURN )
driver . quit ()
}
JavaScript exceptions Listen to the JS Exceptions
and register callbacks to process the exception details.
Java
Python
CSharp
Ruby
JavaScript
Kotlin async with driver . bidi_connection () as session :
log = Log ( driver , session )
async with log . add_js_error_listener () as messages :
using IJavaScriptEngine monitor = new JavaScriptEngine ( driver );
var messages = new List < string >();
monitor . JavaScriptExceptionThrown += ( _ , e ) =>
{
messages . Add ( e . Message );
};
await monitor . StartEventMonitoring ();
exceptions = []
driver . on_log_event ( :exception ) { | exception | exceptions << exception }
Network Interception Both requests and responses can be recorded or transformed.
Java
Python
CSharp
Ruby
JavaScript
Kotlin CopyOnWriteArrayList < String > contentType = new CopyOnWriteArrayList <>();
try ( NetworkInterceptor ignored =
new NetworkInterceptor (
driver ,
( Filter )
next ->
req -> {
HttpResponse res = next . execute ( req );
contentType . add ( res . getHeader ( "Content-Type" ));
return res ;
})) {
var contentType = new List < string >();
INetwork networkInterceptor = driver . Manage (). Network ;
networkInterceptor . NetworkResponseReceived += ( _ , e ) =>
{
contentType . Add ( e . ResponseHeaders [ "content-type" ]);
};
await networkInterceptor . StartMonitoring ();
content_type = []
driver . intercept do | request , & continue |
continue . call ( request ) do | response |
content_type << response . headers [ 'content-type' ]
end
end
Java
Python
CSharp
Ruby
JavaScript
Kotlin try ( NetworkInterceptor ignored =
new NetworkInterceptor (
driver ,
Route . matching ( req -> true )
. to (
() ->
req ->
new HttpResponse ()
. setStatus ( 200 )
. addHeader ( "Content-Type" , MediaType . HTML_UTF_8 . toString ())
. setContent ( Contents . utf8String ( "Creamy, delicious cheese!" ))))) {
var handler = new NetworkResponseHandler ()
{
ResponseMatcher = _ => true ,
ResponseTransformer = _ => new HttpResponseData
{
StatusCode = 200 ,
Body = "Creamy, delicious cheese!"
}
};
INetwork networkInterceptor = driver . Manage (). Network ;
networkInterceptor . AddResponseHandler ( handler );
await networkInterceptor . StartMonitoring ();
driver . intercept do | request , & continue |
continue . call ( request ) do | response |
response . body = 'Creamy, delicious cheese!' if request . url . include? ( 'blank' )
end
end
Move Code
const connection = await driver . createCDPConnection ( 'page' )
let url = fileServer . whereIs ( "/cheese" )
let httpResponse = new HttpResponse ( url )
httpResponse . addHeaders ( "Content-Type" , "UTF-8" )
httpResponse . body = "sausages"
await driver . onIntercept ( connection , httpResponse , async function () {
let body = await driver . getPageSource ()
assert . strictEqual ( body . includes ( "sausages" ), true , `Body contains: ${ body } ` )
})
driver . get ( url )
Move Code
val driver = ChromeDriver ()
val interceptor = new NetworkInterceptor (
driver ,
Route . matching ( req -> true )
. to (() -> req -> new HttpResponse ()
. setStatus ( 200 )
. addHeader ( "Content-Type" , MediaType . HTML_UTF_8 . toString ())
. setContent ( utf8String ( "Creamy, delicious cheese!" ))))
driver . get ( appServer . whereIs ( "/cheese" ))
String source = driver . getPageSource ()
Request interception
Java
Python
CSharp
Ruby
JavaScript
Kotlin var handler = new NetworkRequestHandler
{
RequestMatcher = request => request . Url . Contains ( "one.js" ),
RequestTransformer = request =>
{
request . Url = request . Url . Replace ( "one" , "two" );
return request ;
}
};
INetwork networkInterceptor = driver . Manage (). Network ;
networkInterceptor . AddRequestHandler ( handler );
await networkInterceptor . StartMonitoring ();
driver . intercept do | request , & continue |
uri = URI ( request . url )
request . url = uri . to_s . gsub ( 'one' , 'two' ) if uri . path &. end_with? ( 'one.js' )
continue . call ( request )
end
2 - BiDirectional API (W3C compliant) The following list of APIs will be growing as the WebDriver BiDirectional Protocol grows
and browser vendors implement the same.
Additionally, Selenium will try to support real-world use cases that internally use a combination of W3C BiDi protocol APIs.
If there is additional functionality you’d like to see, please raise a
feature request .
2.1 - Browsing Context This section contains the APIs related to browsing context commands.
Open a new window Creates a new browsing context in a new window.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCreateAWindow () {
BrowsingContext browsingContext = new BrowsingContext ( driver , WindowType . WINDOW );
Assertions . assertNotNull ( browsingContext . getId ());
}
Selenium v4.8
const browsingContext = await BrowsingContext ( driver , {
type : 'window' ,
})
Open a new tab Creates a new browsing context in a new tab.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCreateATab () {
BrowsingContext browsingContext = new BrowsingContext ( driver , WindowType . TAB );
Assertions . assertNotNull ( browsingContext . getId ());
}
Selenium v4.8
const browsingContext = await BrowsingContext ( driver , {
type : 'tab' ,
})
Use existing window handle Creates a browsing context for the existing tab/window to run commands.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCreateABrowsingContextForGivenId () {
String id = driver . getWindowHandle ();
BrowsingContext browsingContext = new BrowsingContext ( driver , id );
Assertions . assertEquals ( id , browsingContext . getId ());
}
Selenium v4.8
const id = await driver . getWindowHandle ()
const browsingContext = await BrowsingContext ( driver , {
browsingContextId : id ,
})
Open a window with a reference browsing context A reference browsing context is a top-level browsing context .
The API allows to pass the reference browsing context, which is used to create a new window. The implementation is operating system specific.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCreateAWindowWithAReferenceContext () {
BrowsingContext
browsingContext =
new BrowsingContext ( driver , WindowType . WINDOW , driver . getWindowHandle ());
Assertions . assertNotNull ( browsingContext . getId ());
}
Selenium v4.8
const browsingContext = await BrowsingContext ( driver , {
type : 'window' ,
referenceContext : await driver . getWindowHandle (),
})
Open a tab with a reference browsing context A reference browsing context is a top-level browsing context .
The API allows to pass the reference browsing context, which is used to create a new tab. The implementation is operating system specific.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCreateATabWithAReferenceContext () {
BrowsingContext
browsingContext =
new BrowsingContext ( driver , WindowType . TAB , driver . getWindowHandle ());
Assertions . assertNotNull ( browsingContext . getId ());
}
Selenium v4.8
const browsingContext = await BrowsingContext ( driver , {
type : 'tab' ,
referenceContext : await driver . getWindowHandle (),
})
Navigate to a URL
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testNavigateToAUrl () {
BrowsingContext browsingContext = new BrowsingContext ( driver , WindowType . TAB );
NavigationResult info = browsingContext . navigate ( "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html" );
Assertions . assertNotNull ( browsingContext . getId ());
Assertions . assertNotNull ( info . getNavigationId ());
Assertions . assertTrue ( info . getUrl (). contains ( "/bidi/logEntryAdded.html" ));
}
Selenium v4.8
let info = await browsingContext . navigate ( 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html' )
Navigate to a URL with readiness state
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testNavigateToAUrlWithReadinessState () {
BrowsingContext browsingContext = new BrowsingContext ( driver , WindowType . TAB );
NavigationResult info = browsingContext . navigate ( "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html" ,
ReadinessState . COMPLETE );
Assertions . assertNotNull ( browsingContext . getId ());
Assertions . assertNotNull ( info . getNavigationId ());
Assertions . assertTrue ( info . getUrl (). contains ( "/bidi/logEntryAdded.html" ));
}
Selenium v4.8
const info = await browsingContext . navigate (
'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html' ,
'complete'
)
Get browsing context tree Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testGetTreeWithAChild () {
String referenceContextId = driver . getWindowHandle ();
BrowsingContext parentWindow = new BrowsingContext ( driver , referenceContextId );
parentWindow . navigate ( "https://www.selenium.dev/selenium/web/iframes.html" , ReadinessState . COMPLETE );
List < BrowsingContextInfo > contextInfoList = parentWindow . getTree ();
Assertions . assertEquals ( 1 , contextInfoList . size ());
BrowsingContextInfo info = contextInfoList . get ( 0 );
Assertions . assertEquals ( 1 , info . getChildren (). size ());
Assertions . assertEquals ( referenceContextId , info . getId ());
Assertions . assertTrue ( info . getChildren (). get ( 0 ). getUrl (). contains ( "formPage.html" ));
}
Selenium v4.8
const browsingContextId = await driver . getWindowHandle ()
const parentWindow = await BrowsingContext ( driver , {
browsingContextId : browsingContextId ,
})
await parentWindow . navigate ( 'https://www.selenium.dev/selenium/web/iframes.html' , 'complete' )
const contextInfo = await parentWindow . getTree ()
Get browsing context tree with depth Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context upto the depth value passed.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testGetTreeWithDepth () {
String referenceContextId = driver . getWindowHandle ();
BrowsingContext parentWindow = new BrowsingContext ( driver , referenceContextId );
parentWindow . navigate ( "https://www.selenium.dev/selenium/web/iframes.html" , ReadinessState . COMPLETE );
List < BrowsingContextInfo > contextInfoList = parentWindow . getTree ( 0 );
Assertions . assertEquals ( 1 , contextInfoList . size ());
BrowsingContextInfo info = contextInfoList . get ( 0 );
Assertions . assertNull ( info . getChildren ()); // since depth is 0
Assertions . assertEquals ( referenceContextId , info . getId ());
}
Selenium v4.8
const browsingContextId = await driver . getWindowHandle ()
const parentWindow = await BrowsingContext ( driver , {
browsingContextId : browsingContextId ,
})
await parentWindow . navigate ( 'https://www.selenium.dev/selenium/web/iframes.html' , 'complete' )
const contextInfo = await parentWindow . getTree ( 0 )
Get All Top level browsing contexts
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testGetAllTopLevelContexts () {
BrowsingContext window1 = new BrowsingContext ( driver , driver . getWindowHandle ());
BrowsingContext window2 = new BrowsingContext ( driver , WindowType . WINDOW );
List < BrowsingContextInfo > contextInfoList = window1 . getTopLevelContexts ();
Assertions . assertEquals ( 2 , contextInfoList . size ());
}
Close a tab/window
Java
Ruby
JavaScript
Kotlin Selenium v4.8
void testCloseAWindow () {
BrowsingContext window1 = new BrowsingContext ( driver , WindowType . WINDOW );
BrowsingContext window2 = new BrowsingContext ( driver , WindowType . WINDOW );
window2 . close ();
Assertions . assertThrows ( BiDiException . class , window2 :: getTree );
}
@Test
void testCloseATab () {
BrowsingContext tab1 = new BrowsingContext ( driver , WindowType . TAB );
BrowsingContext tab2 = new BrowsingContext ( driver , WindowType . TAB );
tab2 . close ();
Assertions . assertThrows ( BiDiException . class , tab2 :: getTree );
}
Selenium v4.8
const window1 = await BrowsingContext ( driver , { type : 'window' })
const window2 = await BrowsingContext ( driver , { type : 'window' })
await window2 . close ()
Activate a browsing context
Java
Ruby
JavaScript
Kotlin Selenium v4.14.1
BrowsingContext window1 = new BrowsingContext ( driver , driver . getWindowHandle ());
BrowsingContext window2 = new BrowsingContext ( driver , WindowType . WINDOW );
window1 . activate ();
Selenium v4.15
const window1 = await BrowsingContext ( driver , {
browsingContextId : id ,
})
await BrowsingContext ( driver , {
type : 'window' ,
})
const result = await driver . executeScript ( 'return document.hasFocus();' )
assert . equal ( result , false )
await window1 . activate ()
Reload a browsing context
Java
Ruby
JavaScript
Kotlin Selenium v4.13.0
BrowsingContext browsingContext = new BrowsingContext ( driver , WindowType . TAB );
browsingContext . navigate ( "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html" , ReadinessState . COMPLETE );
NavigationResult reloadInfo = browsingContext . reload ( ReadinessState . INTERACTIVE );
Selenium v4.15
await browsingContext . reload ( undefined , 'complete' )
Handle user prompt
Java
Ruby
JavaScript
Kotlin Selenium v4.13.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/alerts.html" );
driver . findElement ( By . id ( "prompt-with-default" )). click ();
String userText = "Selenium automates browsers" ;
browsingContext . handleUserPrompt ( true , userText );
Selenium v4.15
await browsingContext . handleUserPrompt ( true , userText )
Capture Screenshot
Java
Ruby
JavaScript
Kotlin Selenium v4.13.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/alerts.html" );
String screenshot = browsingContext . captureScreenshot ();
Selenium v4.15
const response = await browsingContext . captureScreenshot ()
Capture Viewport Screenshot
Java
Ruby
JavaScript
Kotlin Selenium v4.14.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/coordinates_tests/simple_page.html" );
WebElement element = driver . findElement ( By . id ( "box" ));
Rectangle elementRectangle = element . getRect ();
String screenshot =
browsingContext . captureBoxScreenshot (
elementRectangle . getX (), elementRectangle . getY (), 5 , 5 );
Selenium v4.15
const browsingContext = await BrowsingContext ( driver , {
browsingContextId : id ,
})
const response = await browsingContext . captureBoxScreenshot ( 5 , 5 , 10 , 10 )
Capture Element Screenshot
Java
Ruby
JavaScript
Kotlin Selenium v4.14.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/formPage.html" );
WebElement element = driver . findElement ( By . id ( "checky" ));
String screenshot = browsingContext . captureElementScreenshot ((( RemoteWebElement ) element ). getId ());
Selenium v4.15
const response = await browsingContext . captureElementScreenshot ( elementId )
Set Viewport
Java
Ruby
JavaScript
Kotlin Selenium v4.14.1
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/formPage.html" );
browsingContext . setViewport ( 250 , 300 , 5 );
Selenium v4.15
await browsingContext . setViewport ( 250 , 300 )
Print page
Java
Ruby
JavaScript
Kotlin Selenium v4.14.1
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
driver . get ( "https://www.selenium.dev/selenium/web/formPage.html" );
PrintOptions printOptions = new PrintOptions ();
String printPage = browsingContext . print ( printOptions );
Selenium v4.10
const result = await browsingContext . printPage ({
orientation : 'landscape' ,
scale : 1 ,
background : true ,
width : 30 ,
height : 30 ,
top : 1 ,
bottom : 1 ,
left : 1 ,
right : 1 ,
shrinkToFit : true ,
pageRanges : [ '1-2' ],
})
Navigate back
Java
Ruby
JavaScript
Kotlin Selenium v4.16.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
browsingContext . navigate ( "https://www.selenium.dev/selenium/web/formPage.html" , ReadinessState . COMPLETE );
wait . until ( visibilityOfElementLocated ( By . id ( "imageButton" ))). submit ();
wait . until ( titleIs ( "We Arrive Here" ));
browsingContext . back ();
Selenium v4.17
await browsingContext . back ()
Navigate forward
Java
Ruby
JavaScript
Kotlin Selenium v4.16.0
void canNavigateForwardInTheBrowserHistory () {
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
browsingContext . navigate ( "https://www.selenium.dev/selenium/web/formPage.html" , ReadinessState . COMPLETE );
wait . until ( visibilityOfElementLocated ( By . id ( "imageButton" ))). submit ();
wait . until ( titleIs ( "We Arrive Here" ));
browsingContext . back ();
Assertions . assertTrue ( driver . getPageSource (). contains ( "We Leave From Here" ));
browsingContext . forward ();
Selenium v4.17
await browsingContext . forward ()
Traverse history
Java
Ruby
JavaScript
Kotlin Selenium v4.16.0
BrowsingContext browsingContext = new BrowsingContext ( driver , driver . getWindowHandle ());
browsingContext . navigate ( "https://www.selenium.dev/selenium/web/formPage.html" , ReadinessState . COMPLETE );
wait . until ( visibilityOfElementLocated ( By . id ( "imageButton" ))). submit ();
wait . until ( titleIs ( "We Arrive Here" ));
browsingContext . traverseHistory (- 1 );
Selenium v4.17
await browsingContext . traverseHistory ( - 1 )
2.2 - Input This section contains the APIs related to input commands.
Java
Ruby
JavaScript
Kotlin Selenium v4.17
Actions selectThreeOptions =
actions . click ( options . get ( 1 )). keyDown ( Keys . SHIFT ). click ( options . get ( 3 )). keyUp ( Keys . SHIFT );
input . perform ( windowHandle , selectThreeOptions . getSequences ());
Selenium v4.17
const actions = driver . actions (). click ( options [ 1 ]). keyDown ( Key . SHIFT ). click ( options [ 3 ]). keyUp ( Key . SHIFT ). getSequences ()
await input . perform ( browsingContextId , actions )
Release Actions
Java
Ruby
JavaScript
Kotlin Selenium v4.17
Actions sendLowercase =
new Actions ( driver ). keyDown ( inputTextBox , "a" ). keyDown ( inputTextBox , "b" );
input . perform ( windowHandle , sendLowercase . getSequences ());
(( JavascriptExecutor ) driver ). executeScript ( "resetEvents()" );
input . release ( windowHandle );
Selenium v4.17
await input . release ( browsingContextId )
2.3 - Log This section contains the APIs related to logging.
Console logs Listen to the console.log
events and register callbacks to process the event.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
public void jsErrors () {
CopyOnWriteArrayList < ConsoleLogEntry > logs = new CopyOnWriteArrayList <>();
try ( LogInspector logInspector = new LogInspector ( driver )) {
logInspector . onConsoleEntry ( logs :: add );
}
driver . get ( "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html" );
const inspector = await LogInspector ( driver )
await inspector . onConsoleEntry ( function ( log ) {
logEntry = log
})
await driver . get ( 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html' )
await driver . findElement ({ id : 'consoleLog' }). click ()
assert . equal ( logEntry . text , 'Hello, world!' )
assert . equal ( logEntry . realm , null )
assert . equal ( logEntry . type , 'console' )
assert . equal ( logEntry . level , 'info' )
assert . equal ( logEntry . method , 'log' )
assert . equal ( logEntry . stackTrace , null )
assert . equal ( logEntry . args . length , 1 )
JavaScript exceptions Listen to the JS Exceptions
and register callbacks to process the exception details.
Java
Ruby
JavaScript
Kotlin logInspector . onJavaScriptLog ( future :: complete );
driver . get ( "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html" );
driver . findElement ( By . id ( "jsException" )). click ();
JavascriptLogEntry logEntry = future . get ( 5 , TimeUnit . SECONDS );
Assertions . assertEquals ( "Error: Not working" , logEntry . getText ());
const inspector = await LogInspector ( driver )
await inspector . onJavascriptException ( function ( log ) {
logEntry = log
})
await driver . get ( 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html' )
await driver . findElement ({ id : 'jsException' }). click ()
assert . equal ( logEntry . text , 'Error: Not working' )
assert . equal ( logEntry . type , 'javascript' )
assert . equal ( logEntry . level , 'error' )
Listen to JS Logs Listen to all JS logs at all levels and register callbacks to process the log.
Java
Ruby
JavaScript
Kotlin Selenium v4.8
driver . findElement ( By . id ( "consoleLog" )). click ();
ConsoleLogEntry logEntry = future . get ( 5 , TimeUnit . SECONDS );
Assertions . assertEquals ( "Hello, world!" , logEntry . getText ());
Assertions . assertNull ( logEntry . getRealm ());
Assertions . assertEquals ( 1 , logEntry . getArgs (). size ());
Assertions . assertEquals ( "console" , logEntry . getType ());
2.4 - Network This section contains the APIs related to network commands.
Add network intercept
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
String intercept =
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ));
Selenium v4.18
const intercept = await network . addIntercept ( new AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ))
Remove network intercept
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
String intercept =
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ));
Assertions . assertNotNull ( intercept );
network . removeIntercept ( intercept );
Selenium v4.18
const network = await Network ( driver )
const intercept = await network . addIntercept ( new AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ))
Continue request blocked at authRequired phase with credentials
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ));
network . onAuthRequired (
responseDetails ->
network . continueWithAuth (
responseDetails . getRequest (). getRequestId (),
new UsernameAndPassword ( "admin" , "admin" )));
driver . get ( "https://the-internet.herokuapp.com/basic_auth" );
Selenium v4.18
await network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ))
await network . authRequired ( async ( event ) => {
await network . continueWithAuth ( event . request . request , 'admin' , 'admin' )
})
Continue request blocked at authRequired phase without credentials
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ));
network . onAuthRequired (
responseDetails ->
// Does not handle the alert
network . continueWithAuthNoCredentials ( responseDetails . getRequest (). getRequestId ()));
driver . get ( "https://the-internet.herokuapp.com/basic_auth" );
Selenium v4.18
await network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ))
await network . authRequired ( async ( event ) => {
await network . continueWithAuthNoCredentials ( event . request . request )
})
Cancel request blocked at authRequired phase
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ));
network . onAuthRequired (
responseDetails ->
// Does not handle the alert
network . cancelAuth ( responseDetails . getRequest (). getRequestId ()));
driver . get ( "https://the-internet.herokuapp.com/basic_auth" );
Selenium v4.18
await network . addIntercept ( new AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ))
await network . authRequired ( async ( event ) => {
await network . cancelAuth ( event . request . request )
})
Fail request
Java
Ruby
JavaScript
Kotlin Selenium v4.18
try ( Network network = new Network ( driver )) {
network . addIntercept ( new AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ));
network . onBeforeRequestSent (
responseDetails -> network . failRequest ( responseDetails . getRequest (). getRequestId ()));
driver . manage (). timeouts (). pageLoadTimeout ( Duration . of ( 5 , ChronoUnit . SECONDS ));
2.5 - Script This section contains the APIs related to script commands.
Call function in a browsing context
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( id , driver )) {
List < LocalValue > arguments = new ArrayList <>();
arguments . add ( PrimitiveProtocolValue . numberValue ( 22 ));
Map < Object , LocalValue > value = new HashMap <>();
value . put ( "some_property" , LocalValue . numberValue ( 42 ));
LocalValue thisParameter = LocalValue . objectValue ( value );
arguments . add ( thisParameter );
EvaluateResult result =
script . callFunctionInBrowsingContext (
id ,
"function processWithPromise(argument) {\n"
+ " return new Promise((resolve, reject) => {\n"
+ " setTimeout(() => {\n"
+ " resolve(argument + this.some_property);\n"
+ " }, 1000)\n"
+ " })\n"
+ "}" ,
true ,
Optional . of ( arguments ),
Optional . of ( thisParameter ),
Optional . of ( ResultOwnership . ROOT ));
Selenium v4.9
const manager = await ScriptManager ( id , driver )
let argumentValues = []
let value = new ArgumentValue ( LocalValue . createNumberValue ( 22 ))
argumentValues . push ( value )
let mapValue = { some_property : LocalValue . createNumberValue ( 42 )}
let thisParameter = new ArgumentValue ( LocalValue . createObjectValue ( mapValue )). asMap ()
const result = await manager . callFunctionInBrowsingContext (
id ,
'function processWithPromise(argument) {' +
'return new Promise((resolve, reject) => {' +
'setTimeout(() => {' +
'resolve(argument + this.some_property);' +
'}, 1000)' +
'})' +
'}' ,
true ,
argumentValues ,
thisParameter ,
ResultOwnership . ROOT )
Call function in a sandbox
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( id , driver )) {
EvaluateResult result =
script . callFunctionInBrowsingContext (
id ,
"sandbox" ,
"() => window.foo" ,
true ,
Optional . empty (),
Optional . empty (),
Optional . empty ());
Selenium v4.9
const manager = await ScriptManager ( id , driver )
await manager . callFunctionInBrowsingContext ( id , '() => { window.foo = 2; }' , true , null , null , null , 'sandbox' )
Call function in a realm
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( tab , driver )) {
List < RealmInfo > realms = script . getAllRealms ();
String realmId = realms . get ( 0 ). getRealmId ();
EvaluateResult result = script . callFunctionInRealm (
realmId ,
"() => { window.foo = 3; }" ,
true ,
Optional . empty (),
Optional . empty (),
Optional . empty ());
Selenium v4.9
const manager = await ScriptManager ( firstTab , driver )
const realms = await manager . getAllRealms ()
const realmId = realms [ 0 ]. realmId
await manager . callFunctionInRealm ( realmId , '() => { window.foo = 3; }' , true )
Evaluate script in a browsing context
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( id , driver )) {
EvaluateResult result =
script . evaluateFunctionInBrowsingContext ( id , "1 + 2" , true , Optional . empty ());
Selenium v4.9
const manager = await ScriptManager ( id , driver )
const result = await manager . evaluateFunctionInBrowsingContext ( id , '1 + 2' , true )
Evaluate script in a sandbox
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( id , driver )) {
EvaluateResult result =
script . evaluateFunctionInBrowsingContext (
id , "sandbox" , "window.foo" , true , Optional . empty ());
Selenium v4.9
const manager = await ScriptManager ( id , driver )
await manager . evaluateFunctionInBrowsingContext ( id , 'window.foo = 2' , true , null , 'sandbox' )
const resultInSandbox = await manager . evaluateFunctionInBrowsingContext ( id , 'window.foo' , true , null , 'sandbox' )
Evaluate script in a realm
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( tab , driver )) {
List < RealmInfo > realms = script . getAllRealms ();
String realmId = realms . get ( 0 ). getRealmId ();
EvaluateResult result =
script . evaluateFunctionInRealm (
realmId , "window.foo" , true , Optional . empty ());
Selenium v4.9
const manager = await ScriptManager ( firstTab , driver )
const realms = await manager . getAllRealms ()
const realmId = realms [ 0 ]. realmId
await manager . evaluateFunctionInRealm ( realmId , 'window.foo = 3' , true )
const result = await manager . evaluateFunctionInRealm ( realmId , 'window.foo' , true )
Disown handles in a browsing context
Java
Ruby
JavaScript
Kotlin Selenium v4.15
script . disownBrowsingContextScript (
Selenium v4.9
await manager . disownBrowsingContextScript ( id , boxId )
Disown handles in a realm
Java
Ruby
JavaScript
Kotlin Selenium v4.15
script . disownRealmScript ( realmId , List . of ( boxId ));
Selenium v4.9
await manager . disownRealmScript ( realmId , boxId )
Get all realms
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( firstWindow , driver )) {
List < RealmInfo > realms = script . getAllRealms ();
Selenium v4.9
const manager = await ScriptManager ( firstWindow , driver )
const realms = await manager . getAllRealms ()
Get realm by type
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( firstWindow , driver )) {
List < RealmInfo > realms = script . getRealmsByType ( RealmType . WINDOW );
Selenium v4.9
const manager = await ScriptManager ( firstWindow , driver )
const realms = await manager . getRealmsByType ( RealmType . WINDOW )
Get browsing context realms
Java
Ruby
JavaScript
Kotlin Selenium v4.15
try ( Script script = new Script ( windowId , driver )) {
List < RealmInfo > realms = script . getRealmsInBrowsingContext ( tabId );
Selenium v4.9
const manager = await ScriptManager ( windowId , driver )
const realms = await manager . getRealmsInBrowsingContext ( tabId )
Get browsing context realms by type
Java
Ruby
JavaScript
Kotlin Selenium v4.15
List < RealmInfo > windowRealms =
script . getRealmsInBrowsingContextByType ( windowId , RealmType . WINDOW );
Selenium v4.9
const realms = await manager . getRealmsInBrowsingContextByType ( windowId , RealmType . WINDOW )
Preload a script
Java
Ruby
JavaScript
Kotlin Selenium v4.15
String id = script . addPreloadScript ( "() => { window.bar=2; }" , "sandbox" );
Selenium v4.10
const manager = await ScriptManager ( id , driver )
const scriptId = await manager . addPreloadScript ( '() => {{ console.log(\'{preload_script_console_text}\') }}' )
Remove a preloaded script
Java
Ruby
JavaScript
Kotlin Selenium v4.15
script . removePreloadScript ( id );
Selenium v4.10
await manager . removePreloadScript ( scriptId )