Script
Commands
This section contains the APIs related to script commands.
Call function in a browsing context
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));
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
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)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Call function in a sandbox
try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Call function in a realm
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());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Evaluate script in a browsing context
try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Evaluate script in a sandbox
try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
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')
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Evaluate script in a realm
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());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
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)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Disown handles in a browsing context
script.disownBrowsingContextScript(
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
await manager.disownBrowsingContextScript(id, boxId)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Disown handles in a realm
script.disownRealmScript(realmId, List.of(boxId));
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
await manager.disownRealmScript(realmId, boxId)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Get all realms
try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms();
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms()
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Get realm by type
try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Get browsing context realms
try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Get browsing context realms by type
List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Preload a script
String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Remove a preloaded script
script.removePreloadScript(id);
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WindowType; import org.openqa.selenium.bidi.module.LogInspector; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.browsingcontext.ReadinessState; import org.openqa.selenium.bidi.log.ConsoleLogEntry; import org.openqa.selenium.bidi.script.ChannelValue; import org.openqa.selenium.bidi.script.EvaluateResult; import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue; import org.openqa.selenium.bidi.script.EvaluateResultSuccess; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.ObjectLocalValue; import org.openqa.selenium.bidi.script.PrimitiveProtocolValue; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.bidi.script.RemoteReference; import org.openqa.selenium.bidi.script.ResultOwnership; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canCallFunction() { String id = driver.getWindowHandle(); 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)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithDeclaration() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithArguments() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { List<LocalValue> arguments = new ArrayList<>(); LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE"); LocalValue value2 = PrimitiveProtocolValue.numberValue(42); arguments.add(value1); arguments.add(value2); EvaluateResult result = script.callFunctionInBrowsingContext( id, "(...args)=>{return args}", false, Optional.of(arguments), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size()); } } @Test void canCallFunctionWithAwaitPromise() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function() {{\n" + " await new Promise(r => setTimeout(() => r(), 0));\n" + " return \"SOME_DELAYED_RESULT\";\n" + " }}", true, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithThisParameter() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { Map<Object, LocalValue> value = new HashMap<>(); value.put("some_property", PrimitiveProtocolValue.numberValue(42)); LocalValue thisParameter = LocalValue.objectValue(value); EvaluateResult result = script.callFunctionInBrowsingContext( id, "function(){return this.some_property}", false, Optional.empty(), Optional.of(thisParameter), Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals("number", successResult.getResult().getType()); Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get()); } } @Test void canCallFunctionWithOwnershipRoot() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "async function(){return {a:1}}", true, Optional.empty(), Optional.empty(), Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canCallFunctionThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty(), Optional.empty(), Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canCallFunctionInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.callFunctionInBrowsingContext( id, "sandbox", "() => window.foo", true, Optional.empty(), Optional.empty(), Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canCallFunctionInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateScript() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty()); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get()); } } @Test void canEvaluateScriptThatThrowsException() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "))) !!@@## some invalid JS script (((", false, Optional.empty()); EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result; Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType()); Assertions.assertEquals( "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText()); } } @Test void canEvaluateScriptWithResulWithOwnership() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT)); EvaluateResultSuccess successResult = (EvaluateResultSuccess) result; Assertions.assertTrue(successResult.getResult().getHandle().isPresent()); } } @Test void canEvaluateInASandBox() { String id = driver.getWindowHandle(); try (Script script = new Script(id, driver)) { EvaluateResult result = script.evaluateFunctionInBrowsingContext( id, "sandbox", "window.foo", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canEvaluateInARealm() { String tab = driver.getWindowHandle(); 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()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canDisownHandle() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); script.disownBrowsingContextScript( window, List.of(boxId)); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canDisownHandleInARealm() { String window = driver.getWindowHandle(); try (Script script = new Script(window, driver)) { BrowsingContext context = new BrowsingContext(driver, window); context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE); driver.findElement(By.id("adder")).click(); getLocatedElement(driver, By.id("box0")); List<RealmInfo> realms = script.getAllRealms(); String realmId = realms.get(0).getRealmId(); // Retrieve the handle for the element added to DOM EvaluateResult result = script.evaluateFunctionInBrowsingContext( window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT)); String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get(); LocalValue value = LocalValue.remoteReference( RemoteReference.Type.HANDLE, boxId); EvaluateResult checkHandle = script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty()); // The handle is present in memory, else it would result in exception Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType()); // Useful to memory management in a dynamic webpage where DOM mutations happen often script.disownRealmScript(realmId, List.of(boxId)); // Since the handle is now eligible for garbage collections, it is no longer available to be used. Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext( window, "arg => arg.a", false, Optional.of(List.of(value)), Optional.empty(), Optional.empty())); } } @Test void canGetAllRealms() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getAllRealms(); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmByType() { String firstWindow = driver.getWindowHandle(); String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle(); try (Script script = new Script(firstWindow, driver)) { List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW); Assertions.assertEquals(2, realms.size()); } } @Test void canGetRealmInBrowsingContext() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId); Assertions.assertEquals(1, realms.size()); } } @Test void canGetRealmInBrowsingContextByType() { String windowId = driver.getWindowHandle(); String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle(); try (Script script = new Script(windowId, driver)) { List<RealmInfo> windowRealms = script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW); Assertions.assertEquals(1, windowRealms.size()); } } @Test void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); driver.get("https://www.selenium.dev/selenium/blankPage"); ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("{preload_script_console_text}", logEntry.getText()); } } } @Test void canAddPreloadScriptWithArguments() { try (Script script = new Script(driver)) { String id = script.addPreloadScript( "(channel) => channel('will_be_send', 'will_be_ignored')", List.of(new ChannelValue("channel_name"))); Assertions.assertNotNull(id); } } @Test void canAddPreloadScriptInASandbox() { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox"); Assertions.assertNotNull(id); driver.get("https://www.selenium.dev/selenium/blankPage"); EvaluateResult result = script.evaluateFunctionInBrowsingContext( driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty()); Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType()); } } @Test void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { String id = script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}"); Assertions.assertNotNull(id); try (LogInspector logInspector = new LogInspector(driver)) { CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>(); logInspector.onConsoleEntry(future::complete); script.removePreloadScript(id); driver.get("https://www.selenium.dev/selenium/blankPage"); Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS)); } } } }
await manager.removePreloadScript(scriptId)
/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {By, until, Builder} = require("selenium-webdriver") const ScriptManager = require('selenium-webdriver/bidi/scriptManager') const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership"); const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue"); const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue"); const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); const BrowsingContext = require("selenium-webdriver/bidi/browsingContext"); const {WebDriverError} = require("selenium-webdriver/lib/error"); const {RealmType} = require("selenium-webdriver/bidi/realmInfo"); const LogInspector = require("selenium-webdriver/bidi/logInspector"); describe('Script commands', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can call function', async function () { const id = await driver.getWindowHandle() 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 64) }) it('can call function with declaration', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can call function to get element', async function () { await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded') const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, '() => document.getElementById("consoleLog")', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.type, 'node') assert.notEqual(result.result.value, null) assert.notEqual(result.result.value.nodeType, null) }) it('can call function with arguments', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let argumentValues = [] let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE')) let value2 = new ArgumentValue(LocalValue.createNumberValue(42)) argumentValues.push(value1) argumentValues.push(value2) const result = await manager.callFunctionInBrowsingContext( id, '(...args)=>{return args}', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value.length, 2) }) it('can call function with await promise', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', true, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 'SOME_DELAYED_RESULT') }) it('can call function with await promise false', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function() {{\n' + ' await new Promise(r => setTimeout(() => r(), 0));\n' + ' return "SOME_DELAYED_RESULT";\n' + ' }}', false, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.type, 'promise') }) it('can call function with this parameter', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) let mapValue = {some_property: LocalValue.createNumberValue(42)} let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap() const result = await manager.callFunctionInBrowsingContext( id, 'function(){return this.some_property}', false, null, thisParameter, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 42) }) it('can call function with ownership root', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) }) it('can call function with ownership none', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext( id, 'async function(){return {a:1}}', true, null, null, ResultOwnership.NONE, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.realmId, null) assert.equal(result.result.handle, undefined) assert.notEqual(result.result.value, null) }) it('can call function that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can call function in a sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox') const resultInSandbox = await manager.callFunctionInBrowsingContext( id, '() => window.foo', true, null, null, null, 'sandbox', ) assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) }) it('can call function in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(firstTab, driver) const realms = await manager.getAllRealms() const realmId = realms[0].realmId await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true) const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can evaluate script that throws exception', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, '))) !!@@## some invalid JS script (((', false, ) assert.equal(result.resultType, EvaluateResultType.EXCEPTION) assert.equal(result.exceptionDetails.exception.type, 'error') assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'") assert.equal(result.exceptionDetails.columnNumber, 39) assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0) }) it('can evaluate script with result ownership', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const result = await manager.evaluateFunctionInBrowsingContext( id, 'Promise.resolve({a:1})', true, ResultOwnership.ROOT, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(result.result.handle, null) }) it('can evaluate in a sandbox', async function () { const id = await driver.getWindowHandle() 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') assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS) assert.equal(resultInSandbox.result.value, 2) }) it('can evaluate in a realm', async function () { const firstTab = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') 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) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.equal(result.result.value, 3) }) it('can disown handles', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle await manager.disownBrowsingContextScript(id, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can disown handles in realm', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const browsingContext = await BrowsingContext(driver, {browsingContextId: id}) const info = await browsingContext.navigate( 'https://www.selenium.dev/selenium/web/dynamic.html', 'complete' ) await driver.findElement(By.id('adder')).click() await driver.wait(until.elementLocated(By.id('box0')), 10000) const realms = await manager.getAllRealms() const realmId = realms[0].realmId const evaluateResult = await manager.evaluateFunctionInBrowsingContext( id, "document.querySelector('.redbox');", false, ResultOwnership.ROOT, ) assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS) let boxId = evaluateResult.result.handle let argumentValues = [] let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId)) argumentValues.push(value1) let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues) assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS) await manager.disownRealmScript(realmId, boxId) await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => { assert(error instanceof WebDriverError) }) }) it('can get all realms', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getAllRealms() assert.equal(realms.length, 2) }) it('can get realm by type', async function () { const firstWindow = await driver.getWindowHandle() await driver.switchTo().newWindow('window') const secondWindow = await driver.getWindowHandle() const manager = await ScriptManager(firstWindow, driver) const realms = await manager.getRealmsByType(RealmType.WINDOW) assert.equal(realms.length, 2) }) it('can get realm in browsing context', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const tabId = await driver.getWindowHandle() const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContext(tabId) const tabRealm = realms[0] assert.equal(tabRealm.realmType, RealmType.WINDOW) }) it('can get realm in browsing context by type', async function () { const windowId = await driver.getWindowHandle() await driver.switchTo().newWindow('tab') const manager = await ScriptManager(windowId, driver) const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW) const windowRealm = realms[0] assert.equal(windowRealm.realmType, RealmType.WINDOW) }) it('can add preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry.text, '{preload_script_console_text}') }) it('can add preload script to sandbox', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox') await driver.get('https://www.selenium.dev/selenium/blank') let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext( id, 'window.bar', true, null, 'sandbox', ) assert.equal(result_in_sandbox.result.type, 'number') assert.equal(result_in_sandbox.result.value, 2) }) it('can remove preload script', async function () { const id = await driver.getWindowHandle() const manager = await ScriptManager(id, driver) const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}') let logEntry = null const inspector = await LogInspector(driver) await inspector.onConsoleEntry(function (log) { logEntry = log }) await manager.removePreloadScript(scriptId) await driver.get('https://www.selenium.dev/selenium/blank') assert.equal(logEntry, null) }) })
Events
This section contains the APIs related to script events.
Message
try (Script script = new Script(driver)) { CompletableFuture<Message> future = new CompletableFuture<>(); script.onMessage(future::complete); script.callFunctionInBrowsingContext( driver.getWindowHandle(), "(channel) => channel('foo')", false, Optional.of(List.of(LocalValue.channelValue("channel_name"))), Optional.empty(), Optional.empty()); Message message = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("channel_name", message.getChannel()); }
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.Message; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptEventsTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canListenToChannelMessage() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<Message> future = new CompletableFuture<>(); script.onMessage(future::complete); script.callFunctionInBrowsingContext( driver.getWindowHandle(), "(channel) => channel('foo')", false, Optional.of(List.of(LocalValue.channelValue("channel_name"))), Optional.empty(), Optional.empty()); Message message = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("channel_name", message.getChannel()); } } @Test @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI") void canListenToRealmCreatedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmCreated(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.navigate("https://www.selenium.dev/selenium/blankPage"); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } @Test @Disabled void canListenToRealmDestroyedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmDestroyed(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.close(); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } }
const manager = await ScriptManager(undefined, driver) let message = null await manager.onMessage((m) => { message = m }) let argumentValues = [] let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name'))) argumentValues.push(value) const result = await manager.callFunctionInBrowsingContext( await driver.getWindowHandle(), '(channel) => channel("foo")', false, argumentValues, )
/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver") const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue") const {RealmType} = require("selenium-webdriver/bidi/realmInfo") const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue") const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); describe('Script events', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can listen to channel message', async function () { const manager = await ScriptManager(undefined, driver) let message = null await manager.onMessage((m) => { message = m }) let argumentValues = [] let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name'))) argumentValues.push(value) const result = await manager.callFunctionInBrowsingContext( await driver.getWindowHandle(), '(channel) => channel("foo")', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(message, null) assert.equal(message.channel, 'channel_name') assert.equal(message.data.type, 'string') assert.equal(message.data.value, 'foo') }) it('can listen to realm created message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmCreated((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete') assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) xit('can listen to realm destroyed message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmDestroyed((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.close() assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) })
Realm Created
try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmCreated(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.navigate("https://www.selenium.dev/selenium/blankPage"); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); }
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.Message; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptEventsTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canListenToChannelMessage() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<Message> future = new CompletableFuture<>(); script.onMessage(future::complete); script.callFunctionInBrowsingContext( driver.getWindowHandle(), "(channel) => channel('foo')", false, Optional.of(List.of(LocalValue.channelValue("channel_name"))), Optional.empty(), Optional.empty()); Message message = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("channel_name", message.getChannel()); } } @Test @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI") void canListenToRealmCreatedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmCreated(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.navigate("https://www.selenium.dev/selenium/blankPage"); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } @Test @Disabled void canListenToRealmDestroyedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmDestroyed(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.close(); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } }
const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmCreated((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')
/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver") const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue") const {RealmType} = require("selenium-webdriver/bidi/realmInfo") const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue") const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); describe('Script events', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can listen to channel message', async function () { const manager = await ScriptManager(undefined, driver) let message = null await manager.onMessage((m) => { message = m }) let argumentValues = [] let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name'))) argumentValues.push(value) const result = await manager.callFunctionInBrowsingContext( await driver.getWindowHandle(), '(channel) => channel("foo")', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(message, null) assert.equal(message.channel, 'channel_name') assert.equal(message.data.type, 'string') assert.equal(message.data.value, 'foo') }) it('can listen to realm created message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmCreated((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete') assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) xit('can listen to realm destroyed message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmDestroyed((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.close() assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) })
Realm Destroyed
try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmDestroyed(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.close(); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); }
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; import org.openqa.selenium.bidi.module.Script; import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; import org.openqa.selenium.bidi.script.LocalValue; import org.openqa.selenium.bidi.script.Message; import org.openqa.selenium.bidi.script.RealmInfo; import org.openqa.selenium.bidi.script.RealmType; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; class ScriptEventsTest extends BaseTest { @BeforeEach public void setup() { FirefoxOptions options = new FirefoxOptions(); options.setCapability("webSocketUrl", true); driver = new FirefoxDriver(options); } @Test void canListenToChannelMessage() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<Message> future = new CompletableFuture<>(); script.onMessage(future::complete); script.callFunctionInBrowsingContext( driver.getWindowHandle(), "(channel) => channel('foo')", false, Optional.of(List.of(LocalValue.channelValue("channel_name"))), Optional.empty(), Optional.empty()); Message message = future.get(5, TimeUnit.SECONDS); Assertions.assertEquals("channel_name", message.getChannel()); } } @Test @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI") void canListenToRealmCreatedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmCreated(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.navigate("https://www.selenium.dev/selenium/blankPage"); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } @Test @Disabled void canListenToRealmDestroyedEvent() throws ExecutionException, InterruptedException, TimeoutException { try (Script script = new Script(driver)) { CompletableFuture<RealmInfo> future = new CompletableFuture<>(); script.onRealmDestroyed(future::complete); BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle()); context.close(); RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS); Assertions.assertNotNull(realmInfo.getRealmId()); Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType()); } } }
const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmDestroyed((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.close()
/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert") const firefox = require('selenium-webdriver/firefox') const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver") const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue") const {RealmType} = require("selenium-webdriver/bidi/realmInfo") const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue") const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult"); describe('Script events', function () { let driver beforeEach(async function () { driver = new Builder() .forBrowser('firefox') .setFirefoxOptions(new firefox.Options().enableBidi()) .build() }) afterEach(async function () { await driver.quit() }) it('can listen to channel message', async function () { const manager = await ScriptManager(undefined, driver) let message = null await manager.onMessage((m) => { message = m }) let argumentValues = [] let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name'))) argumentValues.push(value) const result = await manager.callFunctionInBrowsingContext( await driver.getWindowHandle(), '(channel) => channel("foo")', false, argumentValues, ) assert.equal(result.resultType, EvaluateResultType.SUCCESS) assert.notEqual(message, null) assert.equal(message.channel, 'channel_name') assert.equal(message.data.type, 'string') assert.equal(message.data.value, 'foo') }) it('can listen to realm created message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmCreated((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete') assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) xit('can listen to realm destroyed message', async function () { const manager = await ScriptManager(undefined, driver) let realmInfo = null await manager.onRealmDestroyed((result) => { realmInfo = result }) const id = await driver.getWindowHandle() const browsingContext = await BrowsingContext(driver, { browsingContextId: id, }) await browsingContext.close() assert.notEqual(realmInfo, null) assert.notEqual(realmInfo.realmId, null) assert.equal(realmInfo.realmType, RealmType.WINDOW) }) })
Last modified July 10, 2024: Release 4.22 Updates (#1765) (fa7b1165ed0)